Proxying and timeouts
16 answers
Getting a request to your application, and how long it waits.
Looking for something specific
The searchable index covers all 326 answers at once and filters as you type.
131 Turn on WebSockets
Open the site, Settings tab, WebSocket, and tick Enable WebSocket support. Save, then Apply config. That is the whole job.
Behind that one tick, nginx has to be told to speak HTTP/1.1 to the backend and to pass the upgrade headers through instead of swallowing them. Doing it by hand is three directives and a lookup table, and getting one of them wrong gives you a connection that opens and then dies with no useful error.
Chat, live dashboards, collaborative editors, terminal windows in a browser and anything using Socket.IO all need this.
132 My WebSocket drops after about a minute
The connection is idle and something closes it. Open the site, Settings tab, WebSocket, and raise WebSocket idle timeout. Ten minutes suits most applications, an hour suits a terminal or a dashboard somebody leaves open.
If it still drops, the application is probably not sending keepalive pings. Raising the timeout hides that for a while but does not fix it, because anything else in the path may have its own idea about idle connections.
133 Give a slow application more time to answer
Open the site, Settings tab, Proxy. Three boxes matter:
- Connect timeout: how long to wait for the backend to pick up. Leave this short, a few seconds. A backend that will not accept a connection is not going to get better in a minute.
- Read timeout: how long to wait for the answer once it has picked up. This is the one to raise for a report that takes two minutes to build.
- Send timeout: how long to wait while sending the request. Only matters for large uploads.
Raise Read timeout for one slow path rather than the whole site if you can. Add the path, tick Settings for this path only, and set it there. A site wide two minute timeout means a genuinely broken backend holds connections for two minutes each.
134 Stop slow visitors tying up my application
Leave Buffer responses on, which is the default. The load balancer takes the whole answer from your application as fast as the application can produce it, lets the application go, and then dribbles it out to the visitor at whatever speed the visitor has.
Without it, a worker on your application server is held open for the whole download. A few hundred people on bad connections is enough to fill up a small application server while the processor sits idle.
The buffer sizes are under Show advanced settings, but the defaults are sensible and almost nobody needs to change them.
135 Turn buffering off for streaming or server sent events
Buffering is exactly wrong for a response that is meant to arrive a piece at a time. With it on, a progress feed or an event stream sits in a buffer and arrives all at once at the end, which looks like the feature is broken.
- Add a path for the streaming endpoint, for example
/events. - Tick Settings for this path only.
- Turn Buffer responses off there.
- Raise Read timeout while you are in, because a stream is idle a lot.
Do it per path. Turning buffering off for the whole site gives back the slow client problem for every page on it.
136 Try the next backend when one fails
Open the site, Settings tab, Proxy, and tick Show advanced settings. The retry list appears: Connection error, Timed out, Backend sent garbage, and then the status codes 500, 502, 503, 504, 403 and 404.
Connection error, Timed out and 502 are safe and worth having on. 503 is usually worth it too, because it normally means a backend is restarting.
Leave 403 and 404 off. Those are real answers from a working application, and retrying them just asks three servers the same question and gets the same answer three times.
Maximum retries caps how many other backends get tried, and Total retry time caps how long the whole thing may take. Set both, or one slow failure can turn into a long one.
137 Stop retrying a request that changes something
A retry means the request is sent again. That is harmless for a page view and not harmless at all for a payment.
By default only GET and HEAD get retried, which is the safe choice. There is a box called Also retry POST and PATCH, and you should only tick it if you know the application handles being asked twice.
Never retry switches the whole thing off for that site or path. Worth it on a checkout, a webhook receiver, or anything that sends email.
138 Control what name the backend thinks it is answering for
This lives on the pool, not the site, because it is a fact about the servers rather than about the address people type.
Open the pool, Load balancing tab, What is on the other end:
- Servers running my app, answering to my site's name. The visitor's name is passed through. This is right for nearly everything you run yourself.
- Another website, on its own name. The backend is told its own name instead. This is right when you are putting a load balancer in front of something that already thinks of itself as a website, like a hosted service or an appliance.
Choosing the second one also points the backend's redirects back at you, so a visitor is not quietly walked off onto the other site's own address halfway through.
Get this wrong and you get a certificate warning, a redirect loop, or an application that builds every link with the wrong hostname in it.
139 Pass the visitor's real address to my application
Already done. Every proxied site sends the client address and the original scheme to the backend, because an application that logs the load balancer address for every request is no use to anybody.
What is left is the application end. Most frameworks ignore a forwarded address unless you tell them to trust the thing in front. Look for a trusted proxy setting and put the addresses of your load balancer nodes in it. Do not set it to trust everybody, or anybody can claim to be anybody.
The Cluster page lists the node addresses, which is what that setting wants.
140 My application lives under a sub path on the backend
Two places can set this, and the pool is usually the better one.
If every site using those backends needs the prefix, it is a fact about the servers. Put it on the pool, Load balancing tab, Where the application sits on these backends. Set once, right for everything pointed at it.
If only this site needs it, because the same pool is also reached another way, use the site instead: Settings tab, Proxy, Backend lives under this path. That overrides whatever the pool says.
Either way the prefix is added on the way in and taken back off the redirects on the way out. The other half of this is usually Rewrite redirect locations and Rewrite cookie paths in the same section, because an application that thinks it lives under a prefix will put that prefix into both.
141 Stop a header my backend sends from reaching visitors
Open the site, Settings tab, tick Show advanced settings, then Proxy, Hide these response headers. One name per line.
Worth hiding: anything naming the framework or its version, internal request identifiers, debug headers somebody left on, and any header carrying an internal hostname. None of it helps a visitor and all of it helps somebody working out what to try next.
142 Keep connections to the backends open instead of making a new one every time
Open the pool, Load balancing tab, and set Keep-alive connections. Somewhere between 16 and 64 suits most setups. Requests per connection caps how many requests one connection handles before it is replaced.
Setting up a connection costs a round trip, and a TLS connection costs several. On a busy site that is a real slice of the response time, spent doing nothing useful.
Make sure the site is on HTTP/1.1 under Settings, Proxy. Keepalive does not work on HTTP/1.0 and the setting is quietly ignored.
143 I get a 502 and the logs mention headers being too big
Something is sending a header bigger than the space set aside for it. A long list of cookies and a large signed in token are the usual causes, and single sign on tokens are the usual suspect of all.
Open the site, Settings tab, tick Show advanced settings, then Proxy and raise Header buffer size. Under Limits and Timeouts, raise Large header buffers too, because that one covers what the visitor sends rather than what the backend sends back.
Doubling is usually enough. If doubling twice is not enough, something is putting far too much into a cookie and that is worth fixing at the source.
144 Point a site at a backend whose address keeps changing
nginx normally looks a backend name up once at startup and holds on to it. That is fine for a fixed server and wrong for anything in a cloud that moves.
Open the site, Settings tab, tick Show advanced settings, go to Advanced and set a DNS resolver. Now the name is looked up again as its record expires rather than once, ever.
Use your own resolver or the one your cloud provides. Do not point it at a public resolver for an internal name, because it will not know the answer and you will get a wall of failures.
145 Speak https to a backend that has its own certificate name
Turn on Talk to these backends over https on the pool. Then, on the site, Settings tab, Proxy, with advanced settings shown, there are two more:
- Send SNI to backend. Leave this on. Without it a backend hosting several names has no idea which certificate to present, and hands over the wrong one.
- Verify backend certificate. Turn it on once the backend has a certificate that actually checks out. Leaving it off means the traffic is encrypted but you have not established who you are talking to, which is half a job.
146 Show my own error pages when the backend breaks
Open the site, Settings tab, tick Show advanced settings, then Proxy, and tick Use my error pages for backend errors.
With it off, a 500 from your application is passed through exactly as the application wrote it, stack trace and all. With it on, the visitor gets the page you designed under Error Pages.
Careful with an API. An API client wants the JSON error the application sent, not a nicely designed HTML page it cannot parse. Turn this on for the site and off for the API path.