Thoughts on Moving from Apache to Nginx

Posted by Matt Farmer on March 05, 2011 · 6 mins read

This week I made a pretty epic decision for someone who has spent a good majority of my time singing the praises of the Apache HTTPD server.
I switched to the nginx web server (pronounced “Engine-X”).

I don’t know what I was expecting – but the transition was not nearly as bad as I thought it would be. Took me a grand total of about 3 hours to get everything on the Farmdawg Nation network working correctly. Unfortunately, configuring virtual servers takes quite a bit of time right now as I haven’t found a nice GUI to tinker with the nginx configuration. So there are still a few virtual servers that need to be configured. However, given the dramatic increase in the performance of my server since I made the switch, I think I can live without it. I’m also finding that nginx’s rewrite rules are incredibly powerful. And, in my opinion, easier to understand than Apache’s. Unfortunately, I can’t load in configuration on the fly using a .htaccess file. And the configuration for running PHP is a little bit more complex. However, like I said before – with the performance increase I’ve seen, I’m not complaining.

I thought I would publish a short blurb on some lessons that I learned in the process of configuring and testing nginx. While I can’t tell you if nginx is right for what you need to do, I certainly can help you make sure you’re giving it a fare shake by saving you a few headaches.

Lesson 1: If is Evil, but sometimes necessary

One of the biggest differences between nginx and Apache is that nginx is what is called a “non-blocking” server. This means that, unlike Apache, one nginx process can handle multiple requests at a time. This makes nginx incredibly fast at serving up static files. So, naturally, if you’re going to be using nginx you might want to use as many static files as possible to speed up your service. And if you’re looking to make sure you’re serving up static files, one of the most powerful plugins for any WordPress install is the WordPress Supercache.

The supercache creates static versions of the output of WordPress. So instead of having hit a PHP script and your database every time, you can just shoot straight HTML down the wire. It makes the server run a lot faster, trust me. Unfortunately, Supercache isn’t automagically compatible with nginx as it is with Apache. To get it working, you’ve got to write your own URL rewrite rules – the rules that transform a normal URL into the cached version, but only if it exists… and only if you’re not logged in. The big snag comes in with the fact that nginx’s rules don’t let you get as complex as Apache, which is probably part of the reason why it is faster. This means that your server configuration is going to get long and ugly. And it also means you’re going to have to use a lot of if statements.

As anyone using nginx will tell you, if is evil. It just doesn’t always work as you’d expect, and I remember reading somewhere it is actually less optimized than the preferred try_files. Currently, I have not found a valid way to test all the conditions required to use the supercache without using if’s, and I have thankfully not experienced the Segfaults that the nginx wiki talks about. Certainly, when I start converting my own code to run on nginx environments, I will likely convert the code to work in such a way where ifs are not needed.

So, if is evil, but sometimes – it’s necessary.

Lesson 2: Google is your friend.

It’s really hard to find a product that you like and then to realize that the documentation isn’t always up to par with what you need, but unfortunately that is the case with nginx. Not to mention that there are some fun little tidbits that you don’t find out right away, like the fact that the default FastCGI parameters from the Ubuntu software repositories are missing the following line:

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

Without that, PHP just spits out blank pages. That was a really annoying error to track down. Sometimes it just takes some google searching. So, why don’t I save you a bit of time. Here are the two most useful articles I found, that took me a lot of digging to unearth:

Lesson 3: Faster doesn’t automatically mean lighter

One of the reasons nginx is faster than Apache, even with a PHP setup, is that PHP runs outside of the main server process. This means that handling additional static requests by adding more processes won’t require any un-needed overhead on the RAM for that process. However, I haven’t noticed as much of a difference in my memory usage as I would have liked. Personally, I would have liked to eliminate the usage of the slower swap memory on my server completely, but it seems that php5-fpm is somewhat heavy itself. On my machine, top shows %MEM values ranging from 6.9 to 10.5. One of the apache servers that I run for work shows %MEM values between 2.2 to 3.7 across all Apache instances. I still haven’t figured this out.

If anyone has any ideas, let me know – but color me somewhat confused. Just use the comments if you have some suggestions, or just leave me some comment love for any other reason whatsoever. Until next time.