Nginx Reverse Proxy Config Builder

Configure Nginx as a reverse proxy for your Node or Python backend

Generate an Nginx reverse proxy configuration with an upstream block, forwarded proxy headers, connection and read timeouts, request buffering, body-size limits, and WebSocket upgrade support. Copy a working config built entirely in your browser. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

Why use an upstream block instead of proxy_pass to one address?

An upstream block lets you list multiple backends for load balancing, enable keepalive connections, and choose a balancing method like least_conn. Even with one backend it gives you a single named target to reference and a clean place to add more servers later.

An Nginx reverse proxy config builder for putting Nginx in front of a Node, Python, or any HTTP backend. It generates an upstream block, a server block with the correct forwarded headers, sensible timeouts, request buffering, and optional SSL and WebSocket support — copy-and-deploy ready.

How it works

The config has two parts. The upstream block names your backend pool and lists each host:port. With more than one backend it adds least_conn load balancing; in all cases it adds keepalive 32 so Nginx reuses connections to the backend instead of opening a new socket per request (which is why proxy_http_version 1.1 and an empty Connection header matter).

The server block proxies location / to that upstream and forwards the four headers a backend needs to know the real client: Host, X-Real-IP, X-Forwarded-For, and X-Forwarded-Proto. When WebSocket support is on, it adds a top-level map that drives the Connection: upgrade header so socket upgrades pass through. Timeouts, client_max_body_size, and proxy_buffers round out the block, and enabling SSL adds a 443 listener plus an 80→443 redirect.

Why use an upstream block even with one backend

Pointing proxy_pass directly to http://localhost:3000 works but the upstream block gives you more control. With keepalive 32, Nginx maintains a pool of persistent connections to the backend rather than opening a new TCP connection for each request — at moderate traffic this meaningfully reduces latency. When you are ready to add a second backend for load balancing or blue/green deployments, you just add another server line to the upstream block without touching the location.

WebSocket proxying — what the map block does

WebSocket connections start as an HTTP Upgrade request. Nginx by default forwards HTTP/1.0 and strips the Upgrade header. The generated map block detects the Upgrade header and sets $connection_upgrade to either upgrade or close:

map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
}

Combined with proxy_http_version 1.1 and forwarding both the Upgrade and Connection headers, this lets WebSocket handshakes pass cleanly through the proxy to a backend like Socket.IO or a real-time API.

Handling different backend response patterns

  • Standard JSON API — keep proxy_buffering on (the default). Nginx buffers the full response into memory, which frees the backend connection quickly and improves throughput.
  • Server-sent events (SSE) or streaming endpoints — set proxy_buffering off on the specific location. Buffering would hold the stream until the backend closes the connection, defeating the purpose.
  • Large file uploads — raise client_max_body_size to match the largest file your API accepts, otherwise Nginx returns 413 Request Entity Too Large before the request even reaches your backend.

Tips and notes

  • The map $http_upgrade $connection_upgrade directive must live in the http{} context, not inside a server block — keep it at the top of the file as generated.
  • Forwarding X-Forwarded-Proto is essential for frameworks like Express (trust proxy) and Django (SECURE_PROXY_SSL_HEADER) to build correct absolute URLs and set secure cookies behind the proxy.
  • For server-sent events or streaming responses, set proxy_buffering off; on that specific location so clients receive data as it is produced.
  • Validate with nginx -t before reloading; a typo in an upstream address will otherwise take the whole virtual host down.