server { listen 80; server_name _; root /usr/share/nginx/html; index index.html; server_tokens off; # Resolve the backend hostname at request time (via Docker's embedded DNS) # instead of once at startup, so a recreated backend container is picked # up without needing to restart/reload this nginx. resolver 127.0.0.11 valid=30s; location /api/ { set $backend_upstream presencia-backend; # $request_uri (the raw, un-normalized original URI) must be appended # explicitly: when the proxy_pass target is built from a variable, # nginx does NOT replace the matched location prefix with the rest of # the request URI like it does for a static proxy_pass value — it # would otherwise always forward the literal "/api/" with nothing # appended, regardless of the actual path requested. proxy_pass http://$backend_upstream:4790$request_uri; 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; # The API sets these too (for direct access); keep a single copy. proxy_hide_header X-Frame-Options; proxy_hide_header X-Content-Type-Options; proxy_hide_header Referrer-Policy; include /etc/nginx/snippets/security-headers.conf; } # index.html, app.js and the stylesheets keep the same filenames across # releases, so without this a browser happily pairs a freshly fetched # index.html with a cached app.js from a previous deploy. That mismatch # throws on the first missing element id and kills the whole script — which # looks exactly like a server-side failure. "no-cache" still allows caching, # it only forces a revalidation, so unchanged files cost one 304. location ~* \.(?:html|js|css)$ { add_header Cache-Control "no-cache"; include /etc/nginx/snippets/security-headers.conf; try_files $uri $uri/ /index.html; } # Fonts are content-stable and large; let them sit in the browser cache. location ~* \.(?:woff2|woff|ttf)$ { add_header Cache-Control "public, max-age=2592000"; include /etc/nginx/snippets/security-headers.conf; } location / { add_header Cache-Control "no-cache"; include /etc/nginx/snippets/security-headers.conf; try_files $uri $uri/ /index.html; } }