From fdd100194e28b5293e0fcca2e8a1d587b1eb5315 Mon Sep 17 00:00:00 2001 From: iris Date: Fri, 5 Jun 2026 16:25:37 +0200 Subject: [PATCH] docs(gateway): document security headers + HSTS opt-in option --- docs/gateway.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/docs/gateway.md b/docs/gateway.md index 9673cc19..592a5269 100644 --- a/docs/gateway.md +++ b/docs/gateway.md @@ -477,3 +477,45 @@ dialog see the human-readable hint. The internal exact-match location ordering, preventing the subrequest from looping back through `auth_basic`. +## Security headers + +The following headers are emitted at server scope on every gateway +vhost (`_`, `forge.`, `matrix.`): + +| Header | Value | +|--------|-------| +| `X-Frame-Options` | `SAMEORIGIN` | +| `X-Content-Type-Options` | `nosniff` | +| `Referrer-Policy` | `strict-origin-when-cross-origin` | + +nginx's `add_header` inheritance rule: a `location` block that sets its +own `add_header` does **not** inherit server-scope headers. API locations +that carry their own CORS headers (e.g. `/.well-known/matrix/client`, +`/_matrix/`) are therefore unaffected. HTML-serving and proxy locations +with no `add_header` of their own pick the security headers up +automatically. + +### HSTS (`gateway.hsts`) + +HSTS is **opt-in** and disabled by default: + +```nix +services.hyperhive.gateway.hsts = { + enable = true; # default: false + maxAge = 31536000; # default: 1 year (required for preload list) + includeSubDomains = true; # default: true +}; +``` + +When enabled, a `Strict-Transport-Security: max-age=...[; includeSubDomains]` +header is added alongside the other security headers. + +**Opt-in rationale**: HSTS pins HTTPS in the browser's preload cache; +enabling it on a deployment that later loses TLS locks browsers out +until `max-age` expires. Only enable when TLS is permanent. + +**Assertion**: `hsts.enable = true` without a TLS mode configured +(`selfSignedTls`, `tls.certDir`, or `tls.acme.enable`) is a NixOS +build-time assertion failure — HSTS over plain HTTP is harmless but +almost always a misconfiguration. +