Why generate nginx configs with a tool
Writing an nginx server block from scratch requires remembering the correct directive order, the right `try_files` pattern for single-page applications, the gzip settings that actually compress, and the security headers that modern browsers expect. A misplaced `location` block or a missing `proxy_set_header` can cause hard-to-diagnose issues like infinite redirects, missing headers in the proxied request, or 403 errors on static assets. The nginx Config Generator at /developer-tools/validators/nginx-config-generator provides five presets that produce correct, production-ready configurations you can copy into `/etc/nginx/sites-available/` and enable immediately.
Each preset includes the appropriate `listen`, `server_name`, `root`, `location`, and header directives for its use case. The HTTPS preset adds SSL certificate paths pointing to Let's Encrypt's standard directory structure, HTTP/2 support, and a redirect from port 80 to 443.
The five configuration presets
Static site: serves files from a root directory with gzip compression, caching for static assets, and security headers.
SPA (Single Page Application): adds `try_files $uri $uri/ /index.html` so client-side routers in React, Vue, or Angular handle all routes.
Reverse proxy: forwards requests to a backend server with `proxy_pass`, preserving the original Host, X-Real-IP, X-Forwarded-For, and X-Forwarded-Proto headers.
PHP-FPM: configures `fastcgi_pass` to a PHP-FPM socket or port with the standard `SCRIPT_FILENAME` parameter.
Full HTTPS: combines the static site preset with SSL directives, HTTP/2, Let's Encrypt certificate paths, and a port 80 to 443 redirect.
SPA preset and client-side routing
Single-page applications like React Router or Next.js's client-side routing rely on the browser handling URL changes without server round-trips. When a user navigates directly to `/about` or refreshes the page, the browser sends a GET request for `/about` to the server. Without special configuration, nginx returns a 404 because no file named `about` exists in the root directory. The `try_files $uri $uri/ /index.html` directive solves this by falling back to `index.html` for any path that does not match a real file or directory, letting the JavaScript router take over.
This is the single most important directive in any SPA nginx config, and forgetting it is the most common cause of blank pages after deployment.
HTTPS preset and Let's Encrypt integration
The HTTPS preset generates `ssl_certificate` and `ssl_certificate_key` paths pointing to `/etc/letsencrypt/live/<domain>/fullchain.pem` and `privkey.pem` respectively. These are the standard paths created by Certbot when you run `certbot --nginx -d example.com`. The preset also enables `listen 443 ssl http2` for HTTP/2 support and includes a separate server block that redirects all HTTP traffic on port 80 to HTTPS on port 443.
Modern TLS settings are included: the server prefers the server's cipher suite order, disables SSLv3 and TLSv1.0/1.1, and sets the HSTS header. You still need to run Certbot separately to obtain the certificates; the config generator handles the nginx side only.
Reverse proxy preset details
The reverse proxy preset forwards all requests to a backend URL you specify (for example, `http://127.0.0.1:3000`). It includes the four essential `proxy_set_header` directives: `Host` (passes the original hostname), `X-Real-IP` (passes the client IP), `X-Forwarded-For` (the full proxy chain), and `X-Forwarded-Proto` (the original scheme, HTTP or HTTPS). Without these headers, the backend application cannot determine the client's real IP or whether the original connection was encrypted.
WebSocket support is included via the `Upgrade` and `Connection` headers, so the config works out of the box with Socket.io, Django Channels, and other WebSocket frameworks.
Step-by-step: generating a config
Select a preset from the dropdown: static, SPA, reverse proxy, PHP-FPM, or HTTPS.
Enter your domain name, document root path, and listen port.
For the reverse proxy preset, enter the backend URL.
Review the generated nginx.conf in the preview area.
Click Copy or Download to save the file.
For related server configuration tools, see /blog/htaccess-generator for Apache, /blog/dockerfile-generator for containerized deployments, /blog/gitignore-generator for repository exclusions, and /blog/csp-builder for security headers.
Gzip, caching, and security headers
The static, SPA, and HTTPS presets include `gzip on` with types for text, CSS, JavaScript, JSON, SVG, and XML. The `gzip_min_length` is set to 256 bytes to avoid compressing responses that are too small to benefit. Cache headers for static assets (images, fonts, CSS, JS) set long `expires` values to enable browser caching and reduce repeat requests.
Security headers include `X-Content-Type-Options: nosniff`, `X-Frame-Options: SAMEORIGIN`, and `Referrer-Policy: strict-origin-when-cross-origin`. The HTTPS preset adds `Strict-Transport-Security` with a one-year max-age. These headers are recommended by security auditors and are required for passing many security linter checks.
Privacy: local generation only
This matters because your config may contain domain names, internal IP addresses, and backend paths that you consider sensitive. Keeping generation client-side ensures this information never leaves your device. Visit /about for more on EasyDevTools's privacy practices.
Frequently asked questions
Q: Will the HTTPS config work with Let's Encrypt?
A: Yes. The `ssl_certificate` paths point to `/etc/letsencrypt/live/<domain>/`. Run Certbot to obtain the actual certificates.
Q: Does the SPA preset handle client-side routing?
A: Yes. `try_files $uri $uri/ /index.html` sends unknown routes to `index.html` so React Router, Next.js, or Vue Router can handle them.
Q: What about HTTP/2?
A: Enabled by default in the HTTPS preset via `listen 443 ssl http2`.
Q: Is the file uploaded?
A: No. The nginx.conf is generated locally in your browser.