Apache to Nginx Migration Tips

For a simple beginning example configuration to start with please view my example configuration

Nginx currently holds shy of 6.5% of the known webserver market, which is just roughly shy of 13 million servers. This little lightweight webserver created by a sole Russian developer has been gaining a great deal of popularity over the last few years and is used by sites such as WordPress, Texts from Last Night and Hulu.

This guide will show you common examples in Nginx to make migration from Apache a bit easier.

HTTP Basic Authentication or htpasswd support

If you have been playing with nginx for a the first time you may have noticed that there is no .htaccess support. However Nginx can still utilize HTTP Basic Authenication with existing htpasswd files using the HTTP Auth Basic Module. The module is compiled by default.

If you still have Apache installed (but perhaps turned off or on a different port) you can still use htpasswd to generate a password file. But in the event that you don’t have or don’t want to install Apache you can use Perl or Ruby to generate at least the encrypted passwords. The .htpasswd files should be in the following format.

username:encrypted-password:comment

To generate a password with Ruby in irb:

"your-password".crypt("salt-hash")

Likewise to generate with perl from the terminal:

perl -le 'print crypt("your-password", "salt-hash")'

The two commands above will utilize a 56-bit DES encryption which can be used in the htpasswd file.

Once you have your password file saved, store it outside of the web-accessible location like you would have when using Apache (likewise you can ensure that web access to hidden files are denied, more on that later).

Lets say you have a subfolder on your server called ‘admin’ and you wish to protect it. Here is an example configuration:

location  /admin  {
  auth_basic            "Admin Access";
  auth_basic_user_file  conf/domain.com/admin/htpasswd;
}

If the above did not work, check your error logs as sometimes it will notify you if the path to the password file could not be found.

Ignoring robots.txt, favicon.ico and hidden files

Sometimes you may wish to omit commonly accessed files from being recorded in the access log as well as block access to hidden files (filenames beginning with a period such as .htpasswd and .htaccess). Even though nginx doesn’t support htaccess, you may still wish to secure files left behind from the migration. You can easily do this by adding a couple location blocks to your domain’s server block.

location = /favicon.ico { access_log off; log_not_found off; }	
location = /robots.txt { access_log off; log_not_found off; }
location ~ /\. { deny  all; access_log off; log_not_found off; }

The above will not record access to the favicon.ico or robots.txt in the root of your site, as well as ignore the file-not-found error if you do not have either file present. Also the last line will deny access to any file beginning with a period anywhere within the root path. You can actually save the above into a file such as /conf/drop.conf, and include it at the bottom of each of your server blocks like so.

include drop.conf;

Extremely Easy WordPress Migration

Most people now days take advantage of WordPress’ permalink feature which normally requires mod_rewrite enabled in the .htaccess file. However as of Nginx 0.7.26 and above this can be taken care of very easily with a single directive.

location / { 
   try_files $uri $uri/ index.php;
}

The above will attempt to try the requested URI first as a file, then as a folder, and if both of those come back negative it will fall back to index.php. WordPress can simply parse the request URI sent by the webserver so there is no need to manually add arguments onto index.php. If you instead need to do something further you can change the fallback from index.php to @fallback like so:

location / {
   try_files $uri $uri/ @wordpress;
}
 
location @wordpress {
     # Additional rewrite rules or such you need here.
}

For Nginx versions older than 0.7.26 you can use the older method shown below (however its strongly advised to have 0.7.26 or newer).

location / { 
        if (-f $request_filename) {
            expires 30d;
            break;
        }
 
        #Ultimately 'if' should only be used in the context of rewrite/return : http://wiki.nginx.org/IfIsEvil
         if (!-e $request_filename) {
            rewrite ^(.+)$ /index.php?q=$1 last;
        }
}

The two if blocks replace the common RewriteCond used by wordpress to test if the requested filename is an existing file or folder.

On the next page: Utilizing WP Super Cache, rewrite examples and more.

3 comments

  1. Tom says:

    Great stuff but there are some disadvantages in this configuration. The biggest problem is nginx and it’s lack of proper php module (and thus, slower processing). I tried nginx, then lighttpd and while they both are great pieces of software it’s just swimming against the flow using any other webserver than apache.

    So i decided to go with it, there are many tutorials how to pimp it to better performance. And I did not stop there. I installed HTTP accelerator named Varnish in front of it. That way varnish takes care of static files and cache, and when PHP processing is needed, Apache takes over.

    Tom

  2. kbeezie says:

    I actually don’t see Nginx’s lack of a ‘module’ to be a disadvantage, its not a modular webserver like apache. And even though they may be ‘swimming against the flow’ per se, they still outperform Apache, and work great on low resource systems.

  3. Victory says:

    I have been using nginx as a reverse proxy to a paster’s server to serve up my Pylons apps and its beautiful how easy it is on the hardware as compared to Apache.

    I still use Apache for a lot of stuff like wordpress, just because i am use to it, but when the big traffic comes, nginx really does shine.