check / check (push) Waiting to run
nginx sent index.html with no Cache-Control, so a browser could keep it after a deploy and ask for hashed assets the new build no longer has, and show an empty page. location / now adds Cache-Control: no-cache, which covers its try_files fallback to /index.html, and includes security-headers.conf again, since its own add_header drops the server's. /assets/ and the locations passed to the backend are unchanged. script/frontend-viewport-test fails unless / and a path that falls back to the page carry Cache-Control: no-cache and Content-Security-Policy, which comes from the same file as the other security headers. Model: opus-5-5
86 lines
3.2 KiB
Nginx Configuration File
86 lines
3.2 KiB
Nginx Configuration File
# A template: the nginx image renders it into conf.d at container start,
|
|
# filling in PORT and nothing else. bin/entrypoint.sh sets PORT and that
|
|
# limit.
|
|
server {
|
|
listen ${PORT};
|
|
server_name _;
|
|
|
|
# Keep the nginx version out of the Server header and error pages.
|
|
server_tokens off;
|
|
|
|
# The security headers, on every response. An add_header in a
|
|
# location drops every add_header from here, so a location with one
|
|
# of its own includes this file again.
|
|
include /etc/nginx/security-headers.conf;
|
|
|
|
root /usr/share/nginx/html;
|
|
index index.html;
|
|
|
|
# The client address comes from X-Forwarded-For only on a request
|
|
# from the reverse proxies in TRUSTED_PROXIES: bin/entrypoint.sh
|
|
# writes one set_real_ip_from line for each into this file. Unset,
|
|
# TRUSTED_PROXIES is the three private ranges of RFC 1918; set and
|
|
# empty, the file is empty and the client address is the one each
|
|
# request comes from.
|
|
include /etc/nginx/trusted-proxies.conf;
|
|
real_ip_header X-Forwarded-For;
|
|
real_ip_recursive on;
|
|
|
|
# Access log to stdout (Docker best practice)
|
|
access_log /dev/stdout combined;
|
|
error_log /dev/stderr warn;
|
|
|
|
# With no-cache, a browser never uses a copy of the page that names
|
|
# assets a newer build no longer has without first checking with the
|
|
# server that it is current.
|
|
location / {
|
|
try_files $uri $uri/ /index.html;
|
|
add_header Cache-Control no-cache;
|
|
include /etc/nginx/security-headers.conf;
|
|
}
|
|
|
|
# Cache static assets aggressively
|
|
location /assets/ {
|
|
expires 1y;
|
|
add_header Cache-Control "public, immutable";
|
|
include /etc/nginx/security-headers.conf;
|
|
}
|
|
|
|
# netwatch-server, the Go backend, runs in the same container and
|
|
# listens on loopback only: bin/entrypoint.sh starts it on
|
|
# 127.0.0.1:8081. These headers go with every request passed to it.
|
|
# X-Forwarded-For carries only the client address, as resolved by
|
|
# the real IP settings above, and not the chain the request came
|
|
# with. bin/entrypoint.sh starts the backend with
|
|
# TRUSTED_PROXIES=127.0.0.1/32, the address nginx connects from, so
|
|
# the backend takes that one entry as the client address.
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $remote_addr;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
|
|
# netwatch-server sets the same security headers on its own
|
|
# responses. Its copies are dropped so that each header goes out
|
|
# once, as configs/security-headers.conf sets it.
|
|
proxy_hide_header Strict-Transport-Security;
|
|
proxy_hide_header Content-Security-Policy;
|
|
proxy_hide_header X-Frame-Options;
|
|
proxy_hide_header X-Content-Type-Options;
|
|
proxy_hide_header Referrer-Policy;
|
|
proxy_hide_header Permissions-Policy;
|
|
|
|
location /api/ {
|
|
proxy_pass http://127.0.0.1:8081;
|
|
}
|
|
|
|
location = /.well-known/healthcheck {
|
|
proxy_pass http://127.0.0.1:8081;
|
|
}
|
|
|
|
# The backend's Prometheus metrics, behind its own basic auth. Unless
|
|
# METRICS_USERNAME and METRICS_PASSWORD are set, it answers 404.
|
|
location = /metrics {
|
|
proxy_pass http://127.0.0.1:8081;
|
|
}
|
|
}
|