Free tool · Runs in your browser

Nginx Config Generator

Generate a production-ready nginx server block for a reverse proxy, static site, single-page app, or PHP - with HTTPS, gzip, security headers, and caching. Configure on the left, copy the config on the right.

Site type
Domain & target
SSL / HTTPS
Options
e.g. 20m - leave blank for the nginx default
example.com
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl;
    http2 on;
    server_name www.example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    return 301 https://example.com$request_uri;
}

# example.com - generated by CtrlOps Nginx Config Generator
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header X-XSS-Protection "1; mode=block" always;
    client_max_body_size 20m;
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
install steps
sudo nano /etc/nginx/sites-available/example.com
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Save to sites-available, symlink into sites-enabled, test with nginx -t, then reload. Always run nginx -t before reloading.

What is an nginx server block?

nginx configuration is organized as a hierarchy: the top-level http block contains one or more server blocks (called "virtual hosts" or "server blocks"), and each server block contains location blocks that decide how to handle requests for different paths.

A server block is matched by its listen port and server_name. This generator produces one ready-to-use server block (plus a redirect block when you enable HTTPS or a www redirect).

sites-available, sites-enabled, and reloading

On Debian/Ubuntu, configs live in /etc/nginx/sites-available/ and are activated by symlinking them into /etc/nginx/sites-enabled/. The main nginx.conf includes everything in sites-enabled.

The golden rule: after any change, run sudo nginx -t to test the syntax, and only then sudo systemctl reload nginx. Reloading applies the new config with zero downtime; testing first prevents a typo from taking your site offline.

Reverse proxy headers explained

When nginx proxies to a backend app, the backend sees nginx as the client unless you forward the original request details. These headers do that:

HeaderWhy it matters
HostPasses the original domain so the app routes and builds URLs correctly.
X-Real-IPThe client's real IP, not nginx's.
X-Forwarded-ForThe chain of client/proxy IPs.
X-Forwarded-ProtoWhether the original request was http or https.

For WebSockets, nginx also needs proxy_http_version 1.1 and the Upgrade/Connection headers - enable the WebSocket toggle and the generator adds them.

try_files and the SPA fallback

A single-page app (React, Vue, Svelte) handles routing in the browser, so every URL must return index.html and let the app take over. That is what try_files $uri $uri/ /index.html; does: serve the file if it exists, otherwise fall back to index.html.

Use the plain static type instead (try_files $uri $uri/ =404;) for a normal website where missing files should genuinely 404.

HTTPS with Let’s Encrypt

The easiest way to get a free certificate is certbot. Once issued, the cert and key live at /etc/letsencrypt/live/your-domain/fullchain.pem and privkey.pem- exactly the paths this generator fills in when you pick Let's Encrypt. Certbot also auto-renews them.

Turn on the HTTP-to-HTTPS redirect so visitors always land on the secure version. Add HSTS only once HTTPS works reliably - it tells browsers to refuse HTTP for a long time, which is hard to undo if your certificate later breaks. Need to lock down file permissions on your keys? See our chmod calculator.

Common gotchas

  • 413 Request Entity Too Large. nginx caps request bodies at 1 MB by default. Raise client_max_body_size (e.g. 20m) to allow larger uploads.
  • Trailing slash on proxy_pass. proxy_pass http://app/ (with a slash) rewrites the path; without it, the full URI is passed through. The difference matters.
  • root vs alias. root appends the full request path to the directory; alias replaces the matched location prefix. Mixing them up serves the wrong files.
  • Location order. Exact and regex locations are evaluated by specific rules, not top-to-bottom - put more specific matches where nginx expects them.

Common nginx directives

DirectiveWhat it does
listenThe port and protocol the server block accepts, e.g. 80 or 443 ssl.
server_nameThe domain(s) this block matches, e.g. example.com www.example.com.
rootThe filesystem directory files are served from.
locationRules that apply to matching request paths.
proxy_passForwards a request to a backend (reverse proxy).
try_filesTries each path in turn, falling back to the last - the basis of SPA routing.
return 301Issues a permanent redirect, e.g. HTTP to HTTPS.
ssl_certificatePath to the TLS certificate (with ssl_certificate_key for the key).
add_headerAdds a response header (security, caching, HSTS).
client_max_body_sizeLargest request body nginx accepts (raise to fix 413 errors).
Nginx FAQ

Frequently asked questions

Use a server block with a location / that has proxy_pass pointing at your app (e.g. http://localhost:3000), plus the forwarded headers (Host, X-Real-IP, X-Forwarded-For, X-Forwarded-Proto). Pick the Reverse proxy type in this generator, set the upstream, and copy the result. Enable WebSocket support if your app uses them.
Serve the built files from a root directory and add try_files $uri $uri/ /index.html; so any unknown path returns index.html and the client-side router takes over. Choose the SPA type in this generator to produce exactly that.
Add a server block listening on port 80 that does return 301 https://$host$request_uri;, and serve the real site on 443 with your certificate. Enable HTTPS and the HTTP-to-HTTPS redirect in this generator and it writes both blocks for you.
nginx limits request bodies to 1 MB by default. Add client_max_body_size with a higher value (for example 20m or 100m) inside the server or location block, then test and reload. Set the Max upload size field in this generator to add it.
The main file is /etc/nginx/nginx.conf; site configs typically live in /etc/nginx/sites-available/ and are enabled by symlinking into /etc/nginx/sites-enabled/. After editing, run sudo nginx -t to validate, then sudo systemctl reload nginx to apply with no downtime.
Pick one canonical host for SEO and redirect the other to it with a 301. This generator can redirect www to root or root to www automatically, emitting the extra redirect server block. Either choice is fine as long as you are consistent.
From config to live

Deploy your app without the YAML hell.

CtrlOps deploys Node.js, Next.js, and React apps with one click - it provisions the server, wires up nginx and SSL, and ships your code, all from a local-first desktop app with your credentials encrypted on your own machine.

Start instantly· No credit card· No sneaky autorenewals