Nginx config generator
Generate production-ready Nginx configurations with SSL, proxy, caching, and security headers.
# Generated by ToolChamp Nginx config generatorserver { listen 80; server_name example.com; root /var/www/html; index index.html index.htm; server_tokens off; # Security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; client_max_body_size 10m; # Gzip compression gzip on; gzip_min_length 1000; gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml; location / { try_files $uri $uri/ /index.html; } location /static/ { alias /var/www/html/static/; expires 30d; add_header Cache-Control "public, immutable"; } error_page 404 /404.html; error_page 500 502 503 504 /50x.html; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log;}Set a domain, a listen port and a document root, then switch on the pieces you need — TLS with a certificate path, a reverse proxy to an upstream port, WebSocket upgrade headers, gzip, a request rate limit, security headers — and the server block writes itself beside the form, syntax-highlighted and indented. Six presets fill the whole form in one click for the usual shapes: a static site, a Node app behind a proxy, a React single-page app, an API proxy, a WordPress root and a load-balancer front end. Extra location blocks can be added one at a time, each either proxying to a target or aliasing a directory. The result downloads as a .conf file named after the domain, ready to drop into sites-available.
Key facts about Nginx config generator
| Presets | 6 — static site, Node.js app, React SPA, API reverse proxy, WordPress/PHP and load balancer. Each sets domain, port, root, TLS, proxy target, gzip and rate limiting together |
|---|---|
| Listen ports offered | 80, 443, 8080 and 8443. With TLS enabled the directive is written as listen 443 ssl http2 |
| HTTP to HTTPS | An optional separate server block on port 80 that returns 301 to https://$host$request_uri |
| TLS directives | ssl_certificate, ssl_certificate_key, an editable ssl_protocols list defaulting to TLSv1.2 TLSv1.3, ssl_prefer_server_ciphers on, and ssl_ciphers HIGH:!aNULL:!MD5 |
| Certificate paths | Prefilled with the Let's Encrypt layout — /etc/letsencrypt/live/yourdomain.com/fullchain.pem and privkey.pem — and rewritten when you apply a preset |
| Proxy block | proxy_pass to your upstream, proxy_http_version 1.1, Host always, and optional X-Real-IP, X-Forwarded-For and X-Forwarded-Proto, plus read, connect and send timeouts on one shared value |
| WebSocket support | A checkbox that adds the Upgrade and Connection upgrade headers — without it a socket connection to the upstream will fail |
| Without a proxy | The root location falls back to try_files $uri $uri/ /index.html, which is the single-page-app pattern |
| Static location | An alias block for a chosen path with expires 30d and Cache-Control public, immutable |
| Rate limiting | limit_req_zone on $binary_remote_addr with a 10 MB zone at your chosen rate, applied with burst=20 nodelay |
| Security block | X-Frame-Options, X-Content-Type-Options, X-XSS-Protection and Referrer-Policy as always headers, HSTS when TLS is on, an optional starter Content-Security-Policy, and server_tokens off |
| Always written | error_page for 404 and for 500 502 503 504, access_log and error_log at the default /var/log/nginx paths, and client_max_body_size at your chosen value |
| Not generated | An upstream block for real load balancing, a fastcgi_pass block for PHP-FPM, HTTP/3, OCSP stapling and Diffie-Hellman parameters — the load balancer and WordPress presets set the surrounding options, not those directives |
What happens to your file
The configuration is assembled as an array of strings in this tab and joined at the end — there is no build service, no template API and no account. Your domain name, certificate paths, upstream address and internal port numbers are typed into a form whose state never leaves the page, which matters because an Nginx config is a description of your internal network. The download is produced from an in-memory blob and named after the domain with dots replaced by underscores. Nothing is written to local storage, so a refresh clears the form back to example.com, and the page keeps working with the network disconnected.
About this tool
- 1
Start from the closest preset
Pick static site, Node app, React SPA, API proxy, WordPress or load balancer. The preset fills the domain, port, root, TLS state, proxy target, gzip and rate limiting in one move, and everything stays editable.
- 2
Set the server basics
Enter your real domain and document root. The root is used by the static alias block as well as the server block, so a wrong path breaks caching as well as file serving.
- 3
Turn on TLS
Enabling SSL switches the listen directive to 443 with ssl and http2, exposes the certificate and key paths, and offers the separate port 80 block that 301s everything to HTTPS. The paths are prefilled in the Let's Encrypt layout.
- 4
Point the proxy at your app
If a process is listening on a local port, enable the reverse proxy and set the upstream — http://127.0.0.1:3000 for a typical Node app. Tick WebSocket support if your app uses sockets, and raise the timeout if requests are long-running.
- 5
Add extra locations
Use the locations section for paths that behave differently from the root: /api/ proxied to another port, /uploads/ aliased to a directory outside the document root.
- 6
Test before you reload
Save the file into sites-available, symlink it, then run nginx -t. Only reload when the syntax check passes — a broken config that is reloaded blindly takes every site on the server with it.
| Target | Nginx 1.18 and later; the output is a single server context to include from the http block |
|---|---|
| File placement | /etc/nginx/sites-available/ with a symlink into sites-enabled on Debian and Ubuntu, or /etc/nginx/conf.d/ on RHEL-family systems |
| HTTP/2 syntax | Written in the listen directive. Nginx 1.25 and newer prefer a separate http2 on; line and will warn about the old form |
| Reload command | nginx -t to check the syntax, then systemctl reload nginx — reload does not drop live connections |
| Download name | The domain with dots turned into underscores, plus .conf |
| Highlighting | Around 40 recognised directives, with variables, quoted strings and time or size values coloured separately |
| Validation | None — the generator produces well-formed blocks but does not check that your paths, certificates or upstreams exist |
| Network | None after page load |
- Run nginx -t after every edit. It names the file and the line number, and it is the difference between a five-second fix and a site that is down while you read logs.
- Reload rather than restart. systemctl reload nginx swaps the configuration without dropping in-flight connections; restart drops them all.
- The X-Forwarded-Proto header is not decoration. Without it an app behind a TLS-terminating proxy believes it is on plain HTTP and will generate http:// links and insecure cookies.
- WebSocket connections need proxy_http_version 1.1 plus the Upgrade and Connection headers. If sockets fail with a 400 or fall back to long polling, that checkbox is the first thing to check.
- Cache-Control immutable is only safe on files whose name changes when the content changes. Applied to a path that serves stable file names, it means returning visitors keep the old asset for thirty days.
- The rate limit is per client IP. Behind Cloudflare or another proxy, every request arrives from the proxy's address, so limit on the real client address instead or you will throttle everyone at once.
- client_max_body_size defaults to 1 MB in Nginx itself, which is the usual cause of a 413 on an upload form. The value set here replaces it for this server block.
- For real load balancing, define an upstream block with several servers above the server block and point proxy_pass at its name. This generator writes a single proxy target, which is a reverse proxy rather than a balancer.
- Six full-form presets
- TLS block with Let's Encrypt paths
- Separate HTTP to HTTPS redirect server
- Reverse proxy with forwarding headers
- WebSocket upgrade option
- Gzip, caching and rate limiting
- Custom location blocks
- Download as a named .conf
- Put a Node, Python or Go process behind Nginx on port 443 without writing the proxy headers from memory.
- Serve a built React or Vue app with the try_files fallback that makes client-side routing work on refresh.
- Add TLS to an existing site after issuing a certificate, including the redirect from the plain HTTP port.
- Stand up an API host with rate limiting and a raised body-size limit.
- Generate a starting point for a colleague who has never written an Nginx server block.
- Compare a working configuration against a clean generated one when a header or a cache rule is not taking effect.
Related tools
View allWorks well with this5
More in Data & Dev12
Updated