`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
16 lines
1.3 KiB
Plaintext
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;
|