Skip to main content

Nginx config generator

Generate production-ready Nginx configurations with SSL, proxy, caching, and security headers.

Free & unlimited
Quick presets
Server
Domain name
Listen port
Root directory
SSL / TLS
Reverse proxy
Static files & compression
Static file location
Security & limits
Max body size
All processing happens in your browser. No data is sent to any server.

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

Key facts about Nginx config generator
Presets6 — 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 offered80, 443, 8080 and 8443. With TLS enabled the directive is written as listen 443 ssl http2
HTTP to HTTPSAn optional separate server block on port 80 that returns 301 to https://$host$request_uri
TLS directivesssl_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 pathsPrefilled with the Let's Encrypt layout — /etc/letsencrypt/live/yourdomain.com/fullchain.pem and privkey.pem — and rewritten when you apply a preset
Proxy blockproxy_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 supportA checkbox that adds the Upgrade and Connection upgrade headers — without it a socket connection to the upstream will fail
Without a proxyThe root location falls back to try_files $uri $uri/ /index.html, which is the single-page-app pattern
Static locationAn alias block for a chosen path with expires 30d and Cache-Control public, immutable
Rate limitinglimit_req_zone on $binary_remote_addr with a 10 MB zone at your chosen rate, applied with burst=20 nodelay
Security blockX-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 writtenerror_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 generatedAn 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. 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. 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. 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. 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. 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. 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.

Specs & compatibility
TargetNginx 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 syntaxWritten in the listen directive. Nginx 1.25 and newer prefer a separate http2 on; line and will warn about the old form
Reload commandnginx -t to check the syntax, then systemctl reload nginx — reload does not drop live connections
Download nameThe domain with dots turned into underscores, plus .conf
HighlightingAround 40 recognised directives, with variables, quoted strings and time or size values coloured separately
ValidationNone — the generator produces well-formed blocks but does not check that your paths, certificates or upstreams exist
NetworkNone 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.
On Debian and Ubuntu, save it as /etc/nginx/sites-available/yourdomain.conf and create a symlink to it in /etc/nginx/sites-enabled, then run nginx -t and reload. On RHEL, Rocky, Alma and Amazon Linux there is usually no sites-available convention: drop the file into /etc/nginx/conf.d/ instead, where the default nginx.conf already includes everything ending in .conf. Either way the file contains a server context and must sit inside the http block, which those include lines already handle.
If you want plain HTTP requests to reach your site at all, yes. A server block listening only on 443 will simply not answer port 80, so visitors typing your domain without a scheme get a connection error rather than a redirect. The generated block listens on 80 for your server name and returns 301 to the same path over HTTPS. The one time to leave it out is when a CDN or load balancer in front of Nginx already does the redirect.
They are the two ways the root location can behave and the generator writes one or the other. With the reverse proxy enabled, every request is handed to your upstream process and Nginx is only a front door. With it disabled, the root location uses try_files $uri $uri/ /index.html, which serves a real file if one matches the path and otherwise returns index.html — the pattern a single-page app needs so that deep links survive a refresh instead of 404ing.
Nginx caps request bodies at 1 MB by default and rejects anything larger with 413 Request Entity Too Large before your application ever sees it. The client_max_body_size directive in the generated block replaces that limit — set it to a little above the largest upload you intend to accept. Remember to raise the matching limit in your application and, for PHP, in upload_max_filesize and post_max_size, or the request will simply fail one layer further in.
Only partially, and it is worth being clear about it. The WordPress preset sets the root, TLS, gzip and rate limiting for a typical install, but it does not write a fastcgi_pass location for PHP-FPM. You will need to add a location block matching .php files that passes to your PHP-FPM socket, along with the standard fastcgi_params include and SCRIPT_FILENAME line, plus WordPress's own try_files rule for permalinks. Use the custom locations section as the place to put it.
No. The configuration is built by joining strings in your browser and the download comes from a blob held in memory. An Nginx file is a map of your infrastructure — internal ports, upstream addresses, certificate locations, log paths — and none of that is transmitted, stored or logged here. Nothing survives a refresh, and once the page has loaded you can disconnect from the network and keep generating.
View all

Updated

We use anonymous analytics to improve ToolChamp. No personal data is stored or sold. Privacy Policy