Files
app/frontend/nginx-security-headers.conf
T
stroblmeandClaude Opus 5.5 0869e5b156 Serve index.html no-cache on every route; check the theme script's CSP hash
`try_files` served the SPA fallback inside `location /`, so `/` and every
client route went out without `Cache-Control: no-cache`. The fallback is now
the last argument, an internal redirect to the exact no-cache location.

`src/csp.check.ts` recomputes the inline theme script's sha256 and fails
`bun run check` with the new value when the CSP no longer names it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GAeg4Jo6xjZzjwy9QDWMQ
2026-10-07 09:32:06 +02:00

16 lines
1.3 KiB
Plaintext

# Security headers. Included at server level and again in every location with
# an add_header of its own, since nginx drops the inherited ones there.
#
# script-src: the bundle, plus the theme script inline in index.html by its
# hash. Edit that script and this hash must change with it (sha256 of the text
# between the tags, base64), or the app paints light-then-dark again;
# `bun run check` (src/csp.check.ts) fails with the new value.
# style-src 'unsafe-inline': Monaco, Radix's scroll lock and the toasts insert
# <style> elements at runtime, which no hash can name.
# img/frame-src take any http(s): a camera stream or website widget points
# wherever its dashboard says. connect-src is this origin plus the API's when
# the bundle calls one elsewhere; the Dockerfile fills that in.
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'sha256-FpmE/jXgh7LaQmoMHvqlYVa3hl7+cMNkDN2fSejs9So='; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: http: https:; media-src 'self' blob:; font-src 'self'; connect-src 'self'__API_ORIGINS__; worker-src 'self'; frame-src http: https:; frame-ancestors 'self'; object-src 'none'; base-uri 'self'; form-action 'self'" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;