# Bach to Basics: nginx config for the static frontend container. # # Serves the built React app and proxies /api/* to the backend service. # Backend hostname "backend" is resolved via Docker Compose's network. server { listen 80; server_name _; root /usr/share/nginx/html; index index.html; # ── Security headers ──────────────────────────────────────────────────── # These are set here (server block) so they apply to all responses that # don't have their own add_header directives. # NOTE: nginx does NOT inherit server-level add_header into location blocks # that define their own add_header (e.g. /assets/). Those blocks repeat # the security headers explicitly to avoid the inheritance pitfall. # /api/ is intentionally excluded - the FastAPI backend sets its own. add_header X-Frame-Options "DENY" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer" always; add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; # SPA fallback: any route that isn't a real file goes to index.html location / { try_files $uri $uri/ /index.html; } # API proxy, strips the /api prefix on the way through location /api/ { proxy_pass http://backend:8000/; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # Sample / soundfont uploads can be large client_max_body_size 60M; # OMR + transcription can take a while proxy_read_timeout 300s; } # Cache static assets aggressively (Vite hashes filenames). # Repeats security headers because this block defines its own add_header # (nginx would otherwise drop the server-level ones here). location /assets/ { expires 1y; add_header Cache-Control "public, immutable" always; add_header X-Frame-Options "DENY" always; add_header X-Content-Type-Options "nosniff" always; add_header Referrer-Policy "no-referrer" always; add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; } }