From Wiki
Jump to: navigation, search

The following content is a Work In Progress and may contain broken links, incomplete directions or other errors. Once the initial work is complete this notice will be removed. Please contact me via Twitter with any questions and I'll try to help you out.


nginx is thorny

I've been using Nginx for a few years now and plan to do so for many more, but it wasn't an easy setup to get used to. In fact, I'm still getting bit by the differences between it and Apache, which I have much more experience with.

Pay close attention to what version of nginx a book or web resource is based on as behavior may change between releases [1]



For the most part, Apache directives are matched in a top down manner with later directives overwriting earlier ones if duplicated. Nginx directives on the other hand seem to operate a little differently. One such example is that with Apache, directives in the configuration files are case-insensitive [2], but with nginx, directives are case-sensitive.

Array values

Another gotcha is setting array values [3]. It may not be immediately obvious, but when using a directive like access_log you are setting an array value. Because you are able to define multiple access logs, each use of the directive adds another entry in the array.

So in a configuration like this:

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    # Found in default nginx 1.2.2 conf file
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    log_format vhost_combined_debugging '$server_name $remote_addr - $remote_user [$time_local] '
                    '"(request = \'$request\')" $status $bytes_sent '
                    '(request_filename = \'$request_filename\') $request_uri (args = \'$args\') '
                    '"$http_referer" "$http_user_agent"';

    access_log  /var/log/nginx/access.log  main;

    # more conf statements here

    server {
        # more conf statements here

        # Enabled/disabled as needed for troubleshooting
        # Note: See explanation below about the first access_log that was defined
        access_log  /var/log/nginx/www.access.log vhost_combined_debugging;

        # more conf statements here


Defining that second access_log value resets the array and causes the earlier array values (other access logs) to be unset. This is unfortunate as it is easy to forget when you expect the default behavior to be one of inheritance. I've personally been bitten by this and only figured it out by observation.

Maxim Dounin explains it as:

Basically, when you set array directive at certan (sic) level this clears everything inherited from upper levels for this array. This applies to other array directives as well (proxy_add_header, access_log, etc.).

Location blocks

This one directive to me is the biggest difference between how Apache and nginx processes requests. The location blocks gave me a lot of trouble until I went through the nginx documentation and wiki pages. I also made the mistake of placing everything in include files which often muddied the picture for me. If you're new to nginx and are having trouble getting certain location blocks to match, I recommend not placing the location blocks in include files until you are comfortable with how nginx handles requests. See Nginx/Location for more information.

Additional Info




Unfortunately there are not a lot of books on nginx out there, and the ones that are available are starting to show their age.

Nginx HTTP Server

The one I got started with is Nginx HTTP Server and while it doesn't cover the current nginx versions available it is good place to start. Just make sure to check any suggestions it offers against current nginx documentation and wiki pages before putting the configurations into production.

nginx versions covered (Jun 2010)
Stable Dev Legacy
0.7.66 0.8.40 0.5.38, 0.6.39