Getting started with nginx

This guide explains how to configure nginx through a series of examples I’ve encountered. Links to the nginx docs are provided if you’d like to read more.

The location and structure of the nginx config files may vary depending on how you installed nginx. The main config file should typically be /etc/nginx/nginx.conf, but usually you won’t need to modify that file. Instead, you should use a folder of site config files (often /etc/nginx/sites-enabled/) to isolate per-website configuration from the main nginx config, even if you’re only using nginx to host a single website. You can find this for your installation by looking for a line inside the http { block in nginx.conf that looks like:

include /etc/nginx/sites-enabled/*;

In the following sections, each config sample that starts with server { represents the contents of a file in that site config folder. You can name site config files however you want, and they conventionally end with .conf.

Contents

Minimal config for a static website

server {
        listen 80;
        server_name example.com;
        root /var/www/example;
}

This will serve the contents of the folder /var/www/example in response to requests for example.com. For instance, requesting http://example.com/path/to/page.html will return the contents of /var/www/example/path/to/page.html, or an error page if the file doesn’t exist.

There are a variety of options you can add to change this behavior, if you’d like:

The listen option sets the port of the server, but it can also be used to bind to a specific address and/or enable IPv6; see the listen documentation for details.

To make nginx serve multiple websites from one installation, you can add more server { blocks (optionally in different files) as long as each of them has a different server_name so nginx can tell them apart. You can specify multiple server_names at once and even use wildcards; see the server_name documentation for details.

Varying config with location blocks

server {
        listen 80;
        server_name nkorth.com;
        root /var/www/nkorth;
        index index.html index.htm;

        location = /favicon.ico {
                log_not_found off;
        }

        location / {
                autoindex on;
        }

        location /cgi-bin/ {
                gzip off;
                index index.py index.html index.htm;
        }

        location /projects/ {
                alias /var/www/proj;
                autoindex on;
        }
}

Use location blocks to change the configuration for different paths in a website. Nginx finds the most specific (longest) location block that matches the requested path, and its contents will override any duplicate configuration options in the enclosing server block (eg. index in the above example.) See the location docs for more details including regular expression matching.

Explanation of each block:

Redirecting www.example.com to example.com

server {
        listen 80;
        server_name www.example.com;
        location / {
                return 301 $scheme://example.com$request_uri;
        }
}

Using HTTPS

(todo)

Reverse proxying web apps (subdirectory)

location /netbox/ {
        proxy_pass http://localhost:8002/netbox/;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        client_max_body_size 512M;
}
location /netbox/static/ {
        alias /mnt/apps/netbox/static/;
        access_log off;
        expires 2w;
}
location /netbox/media/ {
        alias /mnt/apps/netbox/media/;
        access_log off;
        expires 2w;
}

This is an example of reverse proxying a Django app. Follow the deployment instructions for your web app, then use proxy_pass to point nginx at its local server so you can host it in a subdirectory of your website. In this case, the Django WSGI server doesn’t handle static files (and nginx can do it faster anyway); in this case use more location blocks with root or alias as needed.

Reverse proxying web apps (subdomain)

server {
        listen 80;
        server_name netbox.nkorth.com;

        location / {
                proxy_pass http://localhost:8002/;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $remote_addr;
                client_max_body_size 512M;
        }
        location /static/ {
                alias /mnt/apps/netbox/static/;
                access_log off;
                expires 2w;
        }
        location /media/ {
                alias /mnt/apps/netbox/media/;
                access_log off;
                expires 2w;
        }
}

If you want to host your web app on a subdomain but you only have one IP address, you can reverse proxy it through your existing nginx server using a config like this example. Just like any other server block, nginx will use the server_name to distinguish it from your other websites.

cgi-bin

location /cgi-bin/ {
        alias /var/www/cgi-bin;
        fastcgi_intercept_errors on;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_filename;
        fastcgi_pass unix:/var/run/fcgiwrap.socket;
}

You’ll need to install fcgiwrap. The paths /var/run/fcgiwrap.socket and /etc/nginx/fastcgi_params correspond to its defaults from the Ubuntu/Debian package.

Enabling fastcgi_intercept_errors causes nginx to handle 4xx and 5xx errors.

If your scripts need partial output (eg. for progress bars), add gzip off and fastcgi_buffering off.