Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdd100194e | ||
|
|
c1d1328426 |
1 changed files with 53 additions and 0 deletions
|
|
@ -466,3 +466,56 @@ follow-up.
|
||||||
display in the credential dialog. Defaults to `"hyperhive"`. Must not
|
display in the credential dialog. Defaults to `"hyperhive"`. Must not
|
||||||
contain `"` or `$`.
|
contain `"` or `$`.
|
||||||
|
|
||||||
|
**Custom 401 page:** when credentials are absent or wrong, nginx serves
|
||||||
|
a Catppuccin-styled `unauthorized.html` page (built into the same Nix
|
||||||
|
derivation as the agent error pages) that tells the operator which
|
||||||
|
`hivectl` command to run to create a user. The response status is still
|
||||||
|
`401` (`error_page 401 =401 /__hive_auth_unauthorized`) so browsers
|
||||||
|
present the login dialog on the first visit — users who dismiss the
|
||||||
|
dialog see the human-readable hint. The internal exact-match location
|
||||||
|
(`= /__hive_auth_unauthorized`) beats `location /` in nginx's prefix
|
||||||
|
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.<domain>`, `matrix.<domain>`):
|
||||||
|
|
||||||
|
| 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.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue