# nginx vhost for the RFC app — single-process FastAPI behind nginx, # frontend served as static files from the Vite build output. # # Install: # sudo cp deploy/nginx/ohm.wiggleverse.org.conf \ # /etc/nginx/sites-available/ohm.wiggleverse.org # sudo ln -s /etc/nginx/sites-available/ohm.wiggleverse.org \ # /etc/nginx/sites-enabled/ # sudo nginx -t && sudo systemctl reload nginx # # Then add the Let's Encrypt cert: # sudo certbot --nginx -d ohm.wiggleverse.org # Certbot will rewrite this file to add the 443 listener and certificate # directives; the rest of the config below stays as written. server { listen 80; listen [::]:80; server_name ohm.wiggleverse.org; # v0.25.0 security hardening (audit 0026 M2/L8) # # NOTE: certbot promotes THIS server block to the HTTPS listener # (`listen 443 ssl`) and adds a separate port-80 → 443 redirect # block (see the install comment above). These response headers # therefore ride into the HTTPS server block on the VM. They use # `add_header ... always` so they also apply to nginx-generated # error responses (4xx/5xx), not just 200s. # # `server_tokens off` (L8) — suppress the nginx version in the # Server header and on error pages so we don't advertise the # build to scanners. server_tokens off; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Frame-Options "DENY" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; # Content-Security-Policy (M2). Tuned to what the SPA actually loads: # - default-src 'self': everything not called out below is same-origin. # - script-src 'self' + challenges.cloudflare.com: the only external #