Nginx Reverse Proxy Configuration

Nginx reverse proxy configuration is one of the most important infrastructure files in a production web application stack. Nginx sits in front of your application server (Node.js, Python/Gunicorn, Go, Java) and handles connection management, request routing, header forwarding, timeout configuration, and WebSocket support. Getting this configuration right means the difference between an application that handles production traffic gracefully and one that drops connections, loses client IP information, or fails to support real-time features. This example configures an upstream block with two application server instances on ports 3000 and 3001 — a simple round-robin load balancing setup. The keepalive 32 directive maintains a pool of 32 persistent connections to the upstream servers, significantly reducing connection setup overhead for high-throughput applications. The proxy headers are critical for application functionality: proxy_set_header Host $host passes the original request host so your application knows which virtual host was requested. proxy_set_header X-Real-IP $remote_addr passes the client's IP address to the application — without this, your application's access logs and IP-based features (rate limiting, geolocation, fraud detection) see only 127.0.0.1 (the Nginx server). proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for is the standard header for forwarding the chain of proxy IP addresses. WebSocket support requires two specific settings: proxy_http_version 1.1 upgrades from the default HTTP/1.0 (which doesn't support keep-alive) to HTTP/1.1 which is required for WebSocket connections. The Upgrade and Connection headers are the HTTP mechanism for upgrading a connection from HTTP to WebSocket — without passing these headers, WebSocket connections fail silently from the client's perspective while appearing to work in server logs. Timeout configuration matters for different types of applications: proxy_connect_timeout 10s is the time allowed to establish a connection to the upstream server. proxy_read_timeout 60s is the time allowed between receiving bytes from the upstream — for long-running requests (file uploads, report generation, streaming responses), this needs to be higher. Setting it too low causes 504 Gateway Timeout errors for legitimate long requests. Real-world variations: add upstream health checks (upstream { server 127.0.0.1:3000; server 127.0.0.1:3001 backup; }) to automatically remove unhealthy servers from rotation; configure ip_hash; for sticky sessions when your application stores state in memory; add proxy_cache for caching upstream responses at the Nginx layer. Tips: always run nginx -t to validate configuration syntax before applying changes. The error message from nginx -t points directly to the problematic line and directive, making debugging much faster than discovering errors at runtime.

Example
upstream app {
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
    keepalive 32;
}

server {
    listen 80;
    server_name app.example.com;

    location / {
        proxy_pass http://app;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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_connect_timeout 10s;
        proxy_read_timeout 60s;
    }
}
[ open in Nginx Config Formatter → ]

FAQ

Why should I set X-Forwarded-For in Nginx?
Without this header, your application sees only the Nginx server IP as the client address. X-Forwarded-For passes the original client IP so you can use it for logging, rate limiting, and geographic restrictions.
How do I enable WebSocket support in Nginx?
Set proxy_http_version 1.1 and pass the Upgrade and Connection headers. This upgrades the HTTP connection to the WebSocket protocol that your backend expects.
What load balancing algorithms does Nginx support?
The default round-robin, least_conn (fewest active connections), ip_hash (sticky sessions by client IP), and with Nginx Plus: least_time and random. Specify the algorithm before the server directives in the upstream block.

Related Examples