Found while verifying the first real provision: none of the four
security headers reached the browser on any HTML page.
nginx's add_header inheritance is all-or-nothing — a location that sets
any add_header of its own discards every header inherited from the
server block. "/" resolves through try_files to `location = /index.html`,
which sets Cache-Control, so HSTS, X-Content-Type-Options,
X-Frame-Options and Referrer-Policy were silently dropped exactly where
they matter. /assets/ lost them the same way.
Move the four into snippets/security-headers.conf and include it in the
server block and in both locations that add a header of their own.
Also from the same provision run:
- ssl_stapling is dead config now that Let's Encrypt certificates carry
no OCSP responder URL; it only logs a warning per cert on each reload;
- README step 3 chmod'ed /etc/exo to 750 but never set its group, so the
exo user could not traverse it and exo-deploy died on "cannot read
/etc/exo/<app>.env";
- README step 7 dropped http-extras.conf into conf.d without disabling
the same directives in Debian's stock nginx.conf, and nginx refuses to
start on a duplicate gzip / server_tokens.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>