mazzi.github.com

Nginx alias, virtual hosts and debugging 21 / 08 / 2013

Searching on The Internets about “How to configure one virtual host in nginx with multiple subdirs” I found a lot of different answers (mostly wrong or misconfigured) so I decided to write some (more) on my humble blog.

What’s the objective of the configuration? Being able to serve different folders under the same virtual host.

www.domain.com               == served in ==>   /srv/htdocs/domain.com/
www.domain.com/folder01/     == served in ==>   /srv/htdocs/deployment01/
www.domain.com/folder02/     == served in ==>   /srv/htdocs/deployment02/

The most common solution for this scenario would be changing the root under different location directives. This could lead to different problems; especially knowing that Nginx processes virtual hosts configuration files from top to bottom. If some other location relies on the root value and we change it after the first definition we are not going to get the desired result (global variables anyone?).

What’s the solution then? Using the alias directive.

server {
    listen      80;
    server_name www.domain.com;
    root        /srv/htdocs/domain.com;
    set         $alternate_folder01 /srv/htdocs/deployment01

    location /
    {
       index index.html index.htm index.php;
    }

    location ~ /folder01/(.*)$
    {
        alias $alternate_folder01/index.php;

        rewrite "^/folder01/(.*)$"      /folder01/index.php?$1;

        include       /etc/nginx/fastcgi_params;

        fastcgi_pass  127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $request_filename;

        break;
    }

We also need to change the way that fastcgi_parm SCRIPT_FILENAME is called. It’s important to use $request_filename instead of $document_root/$fastcgi_script_name (It’s the most common error when using alias).

In the example I used a variable called $alternate_folder01. This is the best way to keep the configuration modular and easy to read/configure if we have several sublocations added to that location later on.

One of the best ways of debugging the variables (and other stuff) in Nginx is to install HttpEchoModule. It’s so easy to debug like doing this:

 	location ~ /folder01/(.*)$
    {
        alias /srv/htdocs/deployment01/index.php;

        rewrite "^/folder01/(.*)$"      /folder01/index.php?$1;

        include       /etc/nginx/fastcgi_params;

        fastcgi_pass  127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $request_filename;

        echo $uri

        break;
    }

To see the results it’s better to use curl instead of a normal browser (we get rid of caches, cookies, whatever). You’ll receive as an answer the $uri variable and also you are going to be sure where your request was processed.

curl http://www.domain.com/folder01/

Probably you need to complile HttpEchoModule for Nginx (like I had to). But beleive me, it is worth it.