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.