[nginx] Nginx reverse proxy causing 504 Gateway Timeout

I am using Nginx as a reverse proxy that takes requests then does a proxy_pass to get the actual web application from the upstream server running on port 8001.

If I go to mywebsite.com or do a wget, I get a 504 Gateway Timeout after 60 seconds... However, if I load mywebsite.com:8001, the application loads as expected!

So something is preventing Nginx from communicating with the upstream server.

All this started after my hosting company reset the machine my stuff was running on, prior to that no issues whatsoever.

Here's my vhosts server block:

server {
    listen   80;
    server_name mywebsite.com;

    root /home/user/public_html/mywebsite.com/public;

    access_log /home/user/public_html/mywebsite.com/log/access.log upstreamlog;
    error_log /home/user/public_html/mywebsite.com/log/error.log;

    location / {
        proxy_pass http://xxx.xxx.xxx.xxx:8001;
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
} 

And the output from my Nginx error log:

2014/06/27 13:10:58 [error] 31406#0: *1 upstream timed out (110: Connection timed out) while connecting to upstream, client: xxx.xx.xxx.xxx, server: mywebsite.com, request: "GET / HTTP/1.1", upstream: "http://xxx.xxx.xxx.xxx:8001/", host: "mywebsite.com"

This question is related to nginx reverse-proxy proxypass http-status-code-504

The answer is


user2540984, as well as many others have pointed out that you can try increasing your timeout settings. I myself faced a similar issue to this one and tried to change my timeout settings in the /etc/nginx/nginx.conf file, as almost everyone in these threads suggest. This, however, did not help me a single bit; there was no apparent change in NGINX' timeout settings. After many hours of searching, I finally managed to solve my issue.

The solution lies in this forum thread, and what it says is that you should put your timeout settings in /etc/nginx/conf.d/timeout.conf (and if this file doesn't exist, you should create it). I used the same settings as suggested in the thread:

proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;

This might not be the solution to your particular problem, but if anyone else notices that the timeout changes in /etc/nginx/nginx.conf don't do anything, I hope this answer helps!


Probably can add a few more line to increase the timeout period to upstream. The examples below sets the timeout to 300 seconds :

proxy_connect_timeout       300;
proxy_send_timeout          300;
proxy_read_timeout          300;
send_timeout                300;

If you want to increase or add time limit to all sites then you can add below lines to the nginx.conf file.

Add below lines to the http section of /usr/local/etc/nginx/nginx.conf or /etc/nginx/nginx.conf file.

fastcgi_read_timeout 600;
proxy_read_timeout 600;

If the above lines doesn't exist in conf file then add them, otherwise increase fastcgi_read_timeout and proxy_read_timeout to make sure that nginx and php-fpm did not timeout.

To increase time limit for only one site then you can edit in vim /etc/nginx/sites-available/example.com

location ~ \.php$ {
    include /etc/nginx/fastcgi_params;
        fastcgi_pass  unix:/var/run/php5-fpm.sock;
    fastcgi_read_timeout 300; 
}

and after adding these lines in nginx.conf, then don't forget to restart nginx.

service php7-fpm reload 
service nginx reload

or, if you're using valet then simply type valet restart.


NGINX itself may not be the root cause.

IF "minimum ports per VM instance" set on the NAT Gateway -- which stand between your NGINX instance & the proxy_pass destination -- is too small for the number of concurrent requests, it has to be increased.

Solution: Increase the available number of ports per VM on NAT Gateway.

Context In my case, on Google Cloud, a reverse proxy NGINX was placed inside a subnet, with a NAT Gateway. The NGINX instance was redirecting requests to a domain associated with our backend API (upstream) through the NAT Gateway.

This documentation from GCP will help you understand how NAT is relevant to the NGINX 504 timeout.


Increasing the timeout will not likely solve your issue since, as you say, the actual target web server is responding just fine.

I had this same issue and I found it had to do with not using a keep-alive on the connection. I can't actually answer why this is but, in clearing the connection header I solved this issue and the request was proxied just fine:

server {
    location / {
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host      $http_host;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_pass http://localhost:5000;
    }
}

Have a look at this posts which explains it in more detail: nginx close upstream connection after request Keep-alive header clarification http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive


In my case i restart php for and it become ok.


Had the same problem. Turned out it was caused by iptables connection tracking on the upstream server. After removing --state NEW,ESTABLISHED,RELATED from the firewall script and flushing with conntrack -F the problem was gone.


You can also face this situation if your upstream server uses a domain name, and its IP address changes (e.g.: your upstream points to an AWS Elastic Load Balancer)

The problem is that nginx will resolve the IP address once, and keep it cached for subsequent requests until the configuration is reloaded.

You can tell nginx to use a name server to re-resolve the domain once the cached entry expires:

location /mylocation {
    # use google dns to resolve host after IP cached expires
    resolver 8.8.8.8;
    set $upstream_endpoint http://your.backend.server/;
    proxy_pass $upstream_endpoint;
}

The docs on proxy_pass explain why this trick works:

Parameter value can contain variables. In this case, if an address is specified as a domain name, the name is searched among the described server groups, and, if not found, is determined using a resolver.

Kudos to "Nginx with dynamic upstreams" (tenzer.dk) for the detailed explanation, which also contains some relevant information on a caveat of this approach regarding forwarded URIs.


If nginx_ajp_module is used, try adding ajp_read_timeout 10m; in nginx.conf file.


Examples related to nginx

Kubernetes service external ip pending nginx: [emerg] "server" directive is not allowed here Disable nginx cache for JavaScript files Nginx upstream prematurely closed connection while reading response header from upstream, for large requests Nginx: Job for nginx.service failed because the control process exited How can I have same rule for two locations in NGINX config? How to verify if nginx is running or not? Find nginx version? Docker Networking - nginx: [emerg] host not found in upstream How do I rewrite URLs in a proxy response in NGINX

Examples related to reverse-proxy

Nginx reverse proxy causing 504 Gateway Timeout From inside of a Docker container, how do I connect to the localhost of the machine? Error during SSL Handshake with remote server Configure Nginx with proxy_pass nginx - read custom header from upstream server Proxy with express.js How to serve all existing static files directly with NGINX, but proxy the rest to a backend server. What's the difference between a proxy server and a reverse proxy server?

Examples related to proxypass

Nginx reverse proxy causing 504 Gateway Timeout How to add a response header on nginx when using proxy_pass? Configure Nginx with proxy_pass apache ProxyPass: how to preserve original IP address Set up an HTTP proxy to insert a header

Examples related to http-status-code-504

Nginx reverse proxy causing 504 Gateway Timeout