# Production frontend: serve the built SPA, proxy /api to the backend container. # TLS is terminated in front of this (caddy service in docker-compose.prod.yml). server { listen 80; listen [::]:80; server_name _; root /usr/share/nginx/html; index index.html; # Uploads are 300-500 MB Amazon exports; the app enforces its own 2 GB cap. client_max_body_size 2g; gzip on; gzip_types text/plain text/css application/json application/javascript image/svg+xml; location /api { proxy_pass http://backend:8000; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; # Big uploads and long-running processing/status calls. proxy_request_buffering off; proxy_read_timeout 600s; proxy_send_timeout 600s; } # SPA routing: every non-file path renders index.html. location / { try_files $uri /index.html; } # Hashed assets can cache forever; index.html must not. location /assets/ { add_header Cache-Control "public, max-age=31536000, immutable"; } location = /index.html { add_header Cache-Control "no-cache"; } }