Jun
28

NGinx Useful Tips

Posted in : nginx and sysadmin

During an epic debugging session with an NGinx configuration for a project, I discovered some useful, but not so common (at least to me) configuration.

Debug

NGinx do not provide so much help (by default) when it comes to debugging internal redirect, proxying and other rewrite rules. But it comes with a handy debug module which allows you to get a lot more info.

You have to enable it at compile time:

./configure --with-debug

And then in your configuration you can set:

http {
  # At the http level activate debug log for eveything
  error_log /path/to/my/detailed_error_log debug;

  server {
    # At the server level activate debug log only for this server
    error_log /path/to/my/detailed_error_log debug;
  }

  server {
    # At the server level without the debug keywords it disable debug for this server
    error_log /path/to/my/error_log;
  }
}

You can even debug only some connections:

error_log /path/to/my/detailed_error_log debug;
events {
    debug_connection   10.0.0.1;
    debug_connection   10.0.1.0/24;
}

Source: NGinx Debugging Log

Proxying

NGinx is well known for its proxy/reverse-proxy/caching-proxy capabilities, but you’d better know how some things works to not waste your time on some odd behaviors.

When proxying to remote host by URLs, be aware that NGinx use its own internal resolver for DNS name. This means in some cases it can’t resolve domains unless you specify which DNS to use.

Let’s take an example:

server {
  # Let's match everything which starts with /remote_download/
  location ~* ^/remote_download/(.*) {
    # but only when coming from internal request (proxy, rewrite, ...)
    internal;

    # Set the URI using the matched location
    set $remote_download_uri $1;

    # Set the host to use in request proxied (useful if remote is using vhost
    # but you're using its IP address to reach it in the proxy_pass config)
    set $remote_download_host download.mydomain.tld;

    # Set the url we want to proxy to
    # Using IP address of server, be sure to set the $remote_download_host
    set $remote_download_url https://10.0.0.1/$remote_download_uri;
    # Or using the full domain
    # set $remote_download_url https://$remote_download_host/$remote_download_uri;

    # Set Host header for vhost to work
    proxy_set_header Host $download_host;

    # This clears the Authorization
    proxy_set_header Authorization '';
    # If your remote server needs some auth you can set it there
    # Basic auth would be something like
    # proxy_set_header Authorization 'Basic kjslkjsalkdjaslasdoiejldfkj=';

    # Disable local file caching, when serving file
    proxy_max_temp_file_size 0;

    # Finally send query to remote and response back to client
    proxy_pass $download_url;
  }

  try_files $uri @fallback;

  location @fallback {
    proxy_pass http://my_backend;
  }
}

Example adapted from Nginx-Fu: X-Accel-Redirect From Remote Servers

This example is fully working because we used an IP address for $remote_download_url, but if we were using the domain (eg: download.mydomain.tld), any request would fail with a 502 Bad Gateway error.

This is due to the way NGinx default resolver works. It’s smart enough to resolve the domains in proxy_pass directives as long as they are statics (it can get them at boot time) and they are in /etc/hosts. But as we are constructing the URL here, it does not try to resolve it. Fortunately you can specify which DNS server it should use in such cases by setting:

http {
  # Globally
  resolver 127.0.0.1; # Local DNS

  server {
    # By server
    resolver 8.8.8.8; # Google DNS

    location /demo {
      # Or even at location level
      resolver 208.67.222.222; # OpenDNS
    }
  }
}
blog comments powered by Disqus