Nginx Reverse Proxy: A Production Readiness Checklist
The headers, timeouts, TLS, logs, and failure behavior worth reviewing before an Nginx reverse proxy goes live.
A reverse proxy is part of the application boundary; its headers, timeouts, and logs should be designed and tested with the app.
An Nginx reverse proxy often begins as a short configuration copied from a framework guide. Production needs a little more thought because the proxy controls client identity, protocol information, request size, buffering, timeouts, TLS, and part of your failure experience.
Forward the right request context
The upstream application usually needs the original host, protocol, and client chain:
location / {
proxy_pass http://app_upstream;
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;
}
Your application must trust forwarded headers only when the request came through known proxies. Blindly trusting X-Forwarded-For lets a direct client invent its address.
Set timeouts from behavior
Timeouts are not performance tuning decorations. They define how long resources remain occupied and what failure the client sees.
Keep connection timeouts short. Set response timeouts from real endpoint behavior, and do not increase every timeout to support one slow export. Long-running work is usually better moved to a queue with status polling or a signed download when complete.
Review upload size and body buffering deliberately. A default that works for JSON APIs may reject legitimate media uploads; a generous global limit increases exposure everywhere.
Terminate TLS carefully
Use modern TLS protocol versions and an automated certificate renewal process. Test the renewal path before the first expiry date.
Add HSTS only after every required subdomain works over HTTPS. Security headers such as X-Content-Type-Options, Referrer-Policy, and a tested Content Security Policy belong in a documented ownership model so the proxy and application do not fight each other.
Make upstream failure understandable
Configure a small static error response for cases where the application is unavailable. It should return the correct status code, include a request or correlation ID when possible, and avoid pretending that a failed write succeeded.
Use multiple upstream instances only when the application and sessions support it. Health checking and load balancing cannot repair state stored on one instance’s local filesystem.
Log for operations, not curiosity
Useful access logs include request time, upstream response time, status, upstream address, request ID, method, and path. Avoid logging authorization headers, cookies, or sensitive query-string data.
Rotate logs, set retention, and confirm that the host cannot run out of disk. A server that fails because debug logging filled its filesystem is an operational design problem.
Test the boundary
Before launch, verify large requests, slow upstreams, connection failure, WebSocket upgrades if used, client cancellation, certificate renewal, HTTP-to-HTTPS redirects, real client IP handling, and the static failure page.
The reverse proxy is part of your application architecture. Review it with the same care as the code behind it.
End of field note.