How do I see what nginx rewrite rules are being applied to a request?

Solution 1:

There are several strategies you can use for debugging nginx request and response processing.

Rewrite-specific logging

If you enable the rewrite_log directive in a server block, then reload the nginx config, you'll get a whole pile of information (at notice severity) about what exactly nginx is doing with your request as it gets rewritten.

If you need to go deeper than that, though, you can enable debugging at a much broader level.

Virtual-host wide debugging

By setting nginx logging to debug level, you will get an extremely detailed account of everything that nginx does while processing requests and responses. It is a lot of information, but the answer to every problem you have with nginx is contained within it.

The easiest way to get debug logging is to set the severity on the error_log directive for the server block you wish to diagnose to debug. Replace any existing severity keyword that might be there, like info or warn. If the specific server block doesn't have an error_log directive, you should add one (because changing the server-wide error_log to debug will result in a lot of noise.

Once you've made this change, you'll need to cause nginx to reload its configuration (no need to restart).

Examples:

Existing error_log with severity:

Change this:

server {
  server_name foo.example.com;
  error_log /var/log/nginx/foo.example.com.error_log info;
  [...]

To this:

server {
  server_name foo.example.com;
  error_log /var/log/nginx/foo.example.com.error_log debug;

Existing error_log, no existing severity:

Change this:

server {
  server_name foo.example.com;
  error_log /var/log/nginx/foo.example.com.error_log;
  [...]

To this:

server {
  server_name foo.example.com;
  error_log /var/log/nginx/foo.example.com.error_log debug;

No existing error_log:

Change this:

server {
  server_name foo.example.com;
  [...]

To this:

server {
  server_name foo.example.com;
  error_log /var/log/nginx/foo.example.com.error_log debug;

Targeted debugging by IP address

If you're running a busy site, even turning on debugging for a single vhost will likely end with severe performance degradation (writing a lot of logs to disk slows things down) and you'll have so much irrelevant debugging cruft to wade through, that you'll never work out what's going on.

In that case, you can enable debugging only for requests from specific IP addresses (such as the machine you're testing from). For that, you want to edit the main nginx config file (say, /etc/nginx/nginx.conf), find the events section, and make it look like this:

events {
  debug_connection 192.0.2.42;
}

Replace 192.0.2.42 with the IP address that nginx will see (so, possibly the public IP address of your NAT gateway, or your proxy, rather than the IP of your workstation). Reload nginx.

You'll now get debug logs for all connection from that IP (and only that IP). If you need to debug requests from multiple locations, you can repeat the debug_connection directive multiple times, or specify a CIDR-style netmask to cover an entire block of IPs.

Laser-guided debugging

If you decide that you need to debug just the requests in a given location block, you can add an error_log directive in just that block, and so you can write debug logs to a separate location. Something like this will do the trick:

server {
  server_name foo.example.com;

  location ~ ^/somewhere/.*\.php {
    error_log /tmp/somewhere_php.log debug;
    [...]
  }
}

Now you can reload nginx, make a request, and go look in /tmp/somewhere_php.log for all the gory details. Just remember to remove the directive again when you're done, otherwise you'll probably fill up your /tmp partition in fairly short order.