Configuring nginx on Debian Lenny with FancyIndex

Introduction

nginx (pronounced Engine X) is super-quick. Really, really super quick. I came to it having used Apache for years, ending up deciding against LightHTTPd (memory leaks) and then eventually deciding to settle with the use of nginx due to its stability and speed. I’ve now got it running behind an instance of Varnish Cache.

On Debian, a few changes should be made to the default user/compile settings, both to make future maintenance and Debinification a little more straightforward. By default, Debian sticks configurations in /etc, but user binaries in /usr/local. Hence the point in writing a short how-to so that you may do the same.

Download/extract

Download the sources from the nginx home page, extract as necessary. This is what I did:

mkdir -p ~/stage/source && cd ~/stage/source
wget "http://nginx.org/download/nginx-0.8.54.tar.gz"
tar -zxvf nginx-0.8.54.tar.gz
cd nginx-0.8.54

Compile-Time Settings

There are some modules in nginx that come prescribed as default. Some other possibilities can be added in the ./conf stage, such as SSL support and WebDAV, without too much of a hassle. One which I use on many clients’ sites however, FancyIndex, is not as part of the mix and so has to be downloaded and provided during configuration.

Download the FancyIndex source and unpack in the nginx source path, as follows:

cd ~/stage/source/nginx-0.8.54 # - Or whichever directory you're using...
wget "http://furi-ku.org/+/cgit/code/ngx-fancyindex/snapshot/ngx-fancyindex-0.3.1.tar.gz"
tar -zxvf ngx-fancyindex-0.3.1.tar.gz

Sweet. Now, when you ls, you should be able to see both your ngx-fancyindex folder and your nginx’s ./configure script. Let’s now get on with compiling nginx itself …

‘Default’ Lenny settings are available on the InstallOptions nginx Wiki page. This is a hugely useful starting point, giving the following reccommendation:

./configure \
        --conf-path=/etc/nginx/nginx.conf \
        --error-log-path=/var/log/nginx/error.log \
        --pid-path=/var/run/nginx.pid \
        --lock-path=/var/lock/nginx.lock \
        --http-log-path=/var/log/nginx/access.log \
        --with-http_dav_module \
        --http-client-body-temp-path=/var/lib/nginx/body \
        --with-http_ssl_module \
        --http-proxy-temp-path=/var/lib/nginx/proxy \
        --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
        --with-debug \
        --with-http_flv_module

There are, however, a couple of options that I tend to add into the mix. The server status allows administrators who browse to /status of whichever site they’re on, see the status of the nginx server, using the module HttpStubStatus. Granted, not hugely useful, but good for seeing whether the server’s hanging.

We’re also about to add the fancyindex module as follows:

./configure --add-module=./ngx-fancyindex-0.3.1

These are, therefore, the complete ./configure options that I use for nginx:

./configure \
        --conf-path=/etc/nginx/nginx.conf \
        --error-log-path=/var/log/nginx/error.log \
        --pid-path=/var/run/nginx.pid \
        --lock-path=/var/lock/nginx.lock \
        --http-log-path=/var/log/nginx/access.log \
        --with-http_dav_module \
        --http-client-body-temp-path=/var/lib/nginx/body \
        --with-http_ssl_module \
        --http-proxy-temp-path=/var/lib/nginx/proxy \
        --with-http_stub_status_module \
        --with-debug \
        --with-http_flv_module \
        --add-module=./ngx-fancyindex-0.3.1

Creation of .deb file

Typically, installing from source means that the installation of the compiled binary and all its associated shenanigens leaves files splattered all over the disk, with not a single reference (in some cases) as to how and why it might have ended up there. Therefore, you might (like me), prefer to create a .deb (Debian) archive using checkinstall.

apt-get install checkinstall

Then, having done that, let’s go ahead with making the package and finally creating the installable .deb file:

make
checkinstall -d make install

checkinstall will now spit a few questions back at you - none of which you must answer - but can be useful for keeping track of packages if you should choose to install a more than a few by this method.

Finally, let’s install this newly created package using the dpkg package manager:

dpkg -i <debfile-name>.deb

And Bob’s your uncle! (maybe)

nginx Configuration Files

While I realise the following configurations are neither tidy nor the ideal, they work for me. They might not work out for you. But I’ve picked up a few bad habits. You, on the other hand, have no excuse.

The init.d Script

Create /etc/init.d/nginx and put the following inside of it:

#!/bin/sh

# nginx init.d for Debian Lenny
# Modified just a bit by Ronald MacDonald/<ronald@rmacd.com>

### BEGIN INIT INFO
# Provides:          nginx
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the nginx web server
# Description:       starts nginx using start-stop-daemon
### END INIT INFO

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
RUNPATH=/var/run
DAEMON=/usr/sbin/nginx
NAME=nginx
DESC=nginx

test -x $DAEMON || exit 0
        # Include nginx defaults if available
        if [ -f /etc/default/nginx ] ; then
                . /etc/default/nginx
        fi

set -e

case "$1" in
        start)
        echo -n "Starting $DESC: "
        start-stop-daemon --start --quiet --pidfile $RUNPATH/$NAME.pid \
        --exec $DAEMON -- $DAEMON_OPTS
        echo "$NAME."
        ;;
    stop)
        echo -n "Stopping $DESC: "
        start-stop-daemon --stop --quiet --pidfile $RUNPATH/$NAME.pid \
        --exec $DAEMON
        echo "$NAME."
        ;;
    restart|force-reload)
        echo -n "Restarting $DESC: "
        start-stop-daemon --stop --quiet --pidfile \
        $RUNPATH/$NAME.pid --exec $DAEMON
        sleep 1
        start-stop-daemon --start --quiet --pidfile \
        $RUNPATH/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
        echo "$NAME."
        ;;
    reload)
        echo -n "Reloading $DESC configuration: "
        start-stop-daemon --stop --signal HUP --quiet --pidfile $RUNPATH/$NAME.pid \
        --exec $DAEMON
        echo "$NAME."
        ;;
    *)
        N=/etc/init.d/$NAME
        echo "Usage: $N {start|stop|restart|force-reload}" >&2
        exit 1
        ;;
    esac
exit 0

Then make executable:

chmod +x /etc/init.d/nginx

Server Configuration

We’re going to leave the configuration files in the location where nginx expects them, which actually makes uninstallation a little easier if we ever have to do that.

Point /etc/nginx to /usr/local/nginx/conf:

ln -s /usr/local/nginx/conf /etc/nginx

It’s a good idea to set up a few global settings, such as log format and a global catch-all home page, for those that land on unconfigured vhosts pointing towards your server. Additionally, it’s a good idea to follow the Apache/Debian-style configuration hierarchy, where site configs are kept in /etc/nginx/sites-available/<sitename> and ‘enabled’ sites are soft-linked to /etc/nginx/sites-enabled/<sitename>. Such a structure might go as follows:

/etc/nginx
|-- fastcgi.conf
|-- fastcgi_params
|-- mime.types
|-- nginx.conf
|-- scgi_params
|-- sites-available
|   |-- default
|   |-- host1.example.com
|   |-- host2.example.com    # This site isn't enabled, not in 'enabled' folder...
|   |-- testing.example.com  # This site isn't enabled either
|   `-- www.example.com
`-- sites-enabled
    |-- default -> /etc/nginx/sites-available/default
    |-- host1.example.com -> /etc/nginx/sites-available/host1.example.com
    `-- www.example.com -> /etc/nginx/sites-available/www.example.com

Let’s configure /etc/nginx/nginx.conf to reflect this structure:

http {

... default configs here ...

    # Enable all sites in 'enabled' folder
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;

    # I also prefer to explicitly specify my log format
    # Logging settings for log format type 'main' :
    log_format main '$http_x_forwarded_for - $remote_user [$time_local] '
                  '"$request" $status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$gzip_ratio"';
    access_log  /var/log/nginx/access.log main;

    # The following option is useful (and necessary) if you're going to have
    # nginx sitting in front of another server, eg Tomcat or Apache.
    port_in_redirect off;

}