Ready for Kubernetes: trusted proxies, security headers, a spec #174

Merged
littlefox merged 1 commit from issue-k8s-lysator into main 2026-10-19 21:32:54 +00:00
Owner

Closes #173

D-050: Lysator hosts the image on Kubernetes behind their gateway, and writes the manifests from our spec.

  • NEOKOM_TRUSTED_PROXIES: CIDRs that Caddy believes in X-Forwarded-For, strict and right to left. Caddy passes exactly the client address to the relay, which still trusts only loopback. Without this, everyone behind a gateway shares one address and the 9th user is refused.
  • Security headers on every response: CSP (with eval and wasm-unsafe-eval, which the app needs; ws:/wss: connections; data:/blob: images; no framing), nosniff, Referrer-Policy, X-Frame-Options, Permissions-Policy and HSTS.
  • The e2e server (e2e/serve.py) sends the same headers, read from site.caddy, so the whole suite runs under the CSP.
  • docs/KUBERNETES.md: image, ports (8080 only), gateway needs (HTTPS, WebSocket on /relay, long idle timeouts, X-Forwarded-For), environment, probes, read-only root, resources and replicas, logs (24 h, D-040), headers, upgrading, and checking a deployment.
  • DOCKER.md and compose.yaml get the new setting.

Verified:

  • tools/web-image-smoke.sh on a local build: logins over http and https in Chromium with no console errors (so no CSP violations), the headers present, and a new check that a container trusting the network's CIDR counts the forwarded client 203.0.113.7 even with a forged 6.6.6.6 in front. The existing check that a direct client can't forge X-Forwarded-For still passes.
  • the full e2e suite under the CSP: 262 passed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XJW2ocwLunyaLiUwCBHEP8

Closes #173 D-050: Lysator hosts the image on Kubernetes behind their gateway, and writes the manifests from our spec. - **`NEOKOM_TRUSTED_PROXIES`:** CIDRs that Caddy believes in X-Forwarded-For, strict and right to left. Caddy passes exactly the client address to the relay, which still trusts only loopback. Without this, everyone behind a gateway shares one address and the 9th user is refused. - **Security headers on every response:** CSP (with eval and wasm-unsafe-eval, which the app needs; ws:/wss: connections; data:/blob: images; no framing), nosniff, Referrer-Policy, X-Frame-Options, Permissions-Policy and HSTS. - **The e2e server (`e2e/serve.py`) sends the same headers,** read from site.caddy, so the whole suite runs under the CSP. - **docs/KUBERNETES.md:** image, ports (8080 only), gateway needs (HTTPS, WebSocket on /relay, long idle timeouts, X-Forwarded-For), environment, probes, read-only root, resources and replicas, logs (24 h, D-040), headers, upgrading, and checking a deployment. - DOCKER.md and compose.yaml get the new setting. Verified: - tools/web-image-smoke.sh on a local build: logins over http and https in Chromium with no console errors (so no CSP violations), the headers present, and a new check that a container trusting the network's CIDR counts the forwarded client 203.0.113.7 even with a forged 6.6.6.6 in front. The existing check that a direct client can't forge X-Forwarded-For still passes. - the full e2e suite under the CSP: 262 passed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01XJW2ocwLunyaLiUwCBHEP8
Ready for Kubernetes: trusted proxies, security headers, a spec
All checks were successful
ci / check (push) Successful in 8m54s
packaging / arch (pull_request) Successful in 12m21s
ci / desktop (push) Successful in 14m14s
packaging / nix (pull_request) Successful in 18m27s
packaging / debian (pull_request) Successful in 20m12s
packaging / fedora (pull_request) Successful in 24m34s
packaging / release (pull_request) Has been skipped
ci / e2e (push) Successful in 26m14s
394868f506
D-050, #173. Lysator runs the image behind their gateway. Without
NEOKOM_TRUSTED_PROXIES every user would share the gateway's address
and the relay's per-address limit would refuse the 9th; now Caddy
believes the gateway's X-Forwarded-For (strict, right to left) and
passes the client to the relay. Every response gets a CSP and the
usual security headers, and the e2e server sends the same ones so all
specs run under them. docs/KUBERNETES.md tells Lysator's admins what
the app needs.

Refs #173

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJW2ocwLunyaLiUwCBHEP8
littlefox referenced this pull request from a commit 2026-10-19 21:34:02 +00:00
Sign in to join this conversation.
No description provided.