diff --git a/services/nginx.nix b/services/nginx.nix index c7c8847..cea9fad 100644 --- a/services/nginx.nix +++ b/services/nginx.nix @@ -32,6 +32,18 @@ let forceSSL = true; }; + # Security headers, shared across every location. add_header does NOT + # merge with an ancestor context if a location defines its own add_header, + # so any location below that sets add_header must re-include this string. + securityHeaders = '' + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; + add_header Content-Security-Policy "default-src 'self' https: wss: data: blob: 'unsafe-inline' 'unsafe-eval'; frame-ancestors 'self';" always; + ''; + # Simple reverse proxy vhost proxy = port: ssl // { locations."/" = { @@ -86,7 +98,7 @@ in appendHttpConfig = '' proxy_headers_hash_max_size 1024; access_log /var/log/nginx/access.log; - ''; + '' + securityHeaders; virtualHosts = { # --- Unprotected (own auth, or by design) --- @@ -104,7 +116,7 @@ in # auth.nordhammer.it, which trips the check. Strip it so qBit skips. # Cookie stripped too so cached SID cookies don't fight localhost-bypass. "torrent.nordhammer.it" = lib.recursiveUpdate (protectedProxy 8080) { - locations."/".extraConfig = autheliaAuthConfig + '' + locations."/".extraConfig = autheliaAuthConfig + securityHeaders + '' proxy_set_header Referer ""; proxy_set_header Cookie ""; proxy_hide_header Set-Cookie; @@ -118,7 +130,7 @@ in "shelfarr.nordhammer.it" = protectedProxy 5056; "sabnzbd.nordhammer.it" = protectedProxy 8085; "code.nordhammer.it" = lib.recursiveUpdate (protectedProxy 4444) { - locations."/".extraConfig = autheliaAuthConfig + '' + locations."/".extraConfig = autheliaAuthConfig + securityHeaders + '' # Prevent browser from restoring a cached page on tab reopen — # forces a fresh request so Authelia can redirect before JS # tries to open a WebSocket with an expired session.