How To Debug Nginx Reverse Proxy Issues

Nginx server is loved by many people for its proxy capabilities and ease of configuration. A simple proxy_pass can allow you to connect to any of the backends such as GoLang, php-fpm, NodeJS, another Nginx, Tomcat, Apache, Gunicorn, uwsgi, Flask, Django, an external CDN and many more.

When proxying a request to another server, you may or may not have access to a log of the server. So it is important to be able to debug the problem if an issue occurs. Common problems that you may face when proxying request are below

  • 502 Bad Gateway
  • 504 Gateway Timeout
  • 404 Page Not Found
  • 403 Access Denied
  • 400 Bad Request request header or cookie too large
  • Wrong Redirect
  • upstream sent too big header while reading response header from upstream
  • Primary script unknown while reading response header from upstream
  • upstream prematurely closed connection while reading response header from upstream

Few of these issues can occur because of below possible reasons

  • Error in the your server code
  • Error in Nginx config
  • Error in the information server receives
  • Fine tuning of timeouts

In this article I will explain few techniques to debug Nginx + PHP-FPM. These techniques will be applicable to other servers like Gunicorn, uwsgi, or other sites as well

Sample PHP Backend with Error

Consider the below Nginx config with a PHP config

The above config passes all php scripts to the running php-fpm server listening on And anything other than php is denied.

Now let’s create a php file error.php in /var/www/html/



This is weird, we requested a image and got an html. Let us open another socat session

And change our proxy_pass in nginx from to

In the window we can see the request as below

You can see that we are requesting /docker_swarm_security_group.png instead of /images/docker_swarm_security_group.png. If we check our proxy_pass, it is

When we add a trailing / to proxy_pass address then original uri is not sent to the server. So we need to modify our proxy_pass to

Now let us re-run our curl statement. The logs in socat will be

As we can see the url is now corrected. But we still have a 404. This could be because of Host: So we should set the host name also with our request

Note: This is only needed because we are sending the proxy to socat listener on localhost. If we had use as the proxy_pass address, this was not needed

Now our curl command will work. So the final proxy_pass that we need is

Want me to do this for you? Drop me a line: itgalaxyzzz {at} gmail [dot] com