Files
exploded-cluster/nginx/default.conf
T

58 lines
1.9 KiB
Plaintext

# nginx config for the static teaching site, baked into the image.
# Base: nginxinc/nginx-unprivileged (uid 101, listens on 8080).
# Read-only rootfs in k8s: /tmp and /var/cache/nginx are emptyDir mounts.
server {
listen 8080;
server_name _;
root /usr/share/nginx/html;
index index.html;
server_tokens off;
# Behind the Cloudflare Tunnel on :443 while nginx listens on :8080 — without these,
# nginx emits ABSOLUTE redirects to http://host:8080/... and breaks every link.
absolute_redirect off;
port_in_redirect off;
include /etc/nginx/security-headers.conf;
# ---- Caching -------------------------------------------------------------
# Scene images are content-hashed at build time → safe to cache hard.
location /assets/ {
include /etc/nginx/security-headers.conf;
expires 1y;
add_header Cache-Control "public, immutable" always;
}
# Scripts are NOT fingerprinted yet — revalidate so a deploy actually propagates.
location ~* \.js$ {
include /etc/nginx/security-headers.conf;
add_header Cache-Control "no-cache" always;
}
location ~* \.html$ {
include /etc/nginx/security-headers.conf;
add_header Cache-Control "no-cache" always;
}
# Probe endpoint - no file IO, no cache headers, invisible to the CDN.
location = /healthz {
access_log off;
return 200 "ok";
}
# ---- Routing -------------------------------------------------------------
location / {
try_files $uri $uri/ $uri.html =404;
}
# ---- Compression ---------------------------------------------------------
# WebP/PNG are already compressed — gzipping them burns CPU for nothing.
gzip on;
gzip_comp_level 6;
gzip_min_length 1024;
gzip_types text/plain text/css application/javascript application/json image/svg+xml;
gzip_vary on;
}