Refresh on a deep route returns 404
SPA fallback is off, so Nginx looks for the literal file and finds nothing.
Fix: Enable 'SPA fallback' to send all unmatched routes to /index.html (or your build's HTML entry).
Search tools and pages.
Generate an nginx.conf for serving a static site with try_files, SPA fallback, gzip, brotli, and aggressive cache headers
sidebar • 160x600
Written by Giorgos Kostas. Last reviewed:
Nginx Static Site Config Generator emits the canonical static-host server block — `root`, `index`, and the right cache rules for fingerprinted versus non-fingerprinted assets.
Toggle SPA fallback on for Vite/Next/Astro client-routed apps; toggle it off for content sites where 404s should stay 404s.
server_name = www.example.com root = /var/www/example.com SPA fallback = on Cache assets = on
server {
listen 80;
server_name www.example.com;
root /var/www/example.com;
index index.html;
location / { try_files $uri $uri/ /index.html; }
location ~* \.(?:css|js|woff2|png|jpg|svg|ico)$ {
expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable";
}
location ~* \.html$ {
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
}
}SPA fallback is off, so Nginx looks for the literal file and finds nothing.
Fix: Enable 'SPA fallback' to send all unmatched routes to /index.html (or your build's HTML entry).
`/index.html` was cached for a year, so the browser never fetches the new fingerprinted bundles.
Fix: Keep the asset/HTML split that the generator emits — HTML stays uncached.
Nginx worker user (often `nginx` or `www-data`) can't read your build output.
Fix: Run `sudo chown -R nginx:nginx /var/www/example.com` (or set ACLs).
Yes — toggle SPA fallback on for Vite/Next/Astro/etc. Toggle it off for Hugo/Jekyll output where 404s should stay 404s.
HTML is the only file that links to the new fingerprinted assets — caching it forever pins users to old code. The generator emits an explicit `no-cache, no-store, must-revalidate` block for *.html.
Brotli requires the `ngx_brotli` module which isn't shipped with most distros' Nginx packages. Stick with gzip; ship Brotli at the CDN layer.
Run `next build && next export` and point `root` at the `out/` directory. Keep SPA fallback on — Next's static export still relies on it for dynamic routes.
Either works — but a CDN in front of this Nginx is usually the right answer for scale. Long-cache headers in this config make CDNs cache forever automatically.
Switch to the Nginx SSL Config Generator and re-enter the same fields. The static-site bits stay; SSL fields are layered on top.
Static-site neighbours. You can also browse the full DevOps & Infra category for more options.
Generate an HTTPS-ready nginx.conf with SSL certificate paths, modern protocols, ciphers, HSTS, and HTTP-to-HTTPS redirect
Generate a production-ready nginx.conf for reverse proxying with proxy_pass, headers, timeouts, and gzip from a focused form
Build a Content Security Policy header from per-directive cards with chip-style sources, presets, and a live header + meta-tag preview
Paste response headers to audit HSTS, CSP, CORS, X-Powered-By disclosure, and Set-Cookie flags
Validate robots.txt rules from pasted text or a live URL
Generate an nginx upstream + load balancer config with round-robin, least_conn, ip_hash, weights, health checks, and keepalive
Generate an nginx config for proxying WebSocket connections with Upgrade and Connection headers and long read timeouts
Validate docker-compose.yml against the Compose Spec schema with hand-written lints (port collisions, undefined networks, depends_on cycles)
Edit .env files in a key/value table with type detection, masked secrets, duplicate-key warnings, and export to JSON, YAML, shell, or docker-compose
Explore multi-document Kubernetes manifests grouped by kind with a cross-reference graph (Service to Deployment, ConfigMap mounts, Ingress backends)
sudo nginx -t && sudo systemctl reload nginxcontent bottom • up to 300x250