Defining Terms

Moving From Apache to Nginx

I’ve been having problems with too much memory usage on the 256 slice I use to serve my web pages. I was using Apache and mod_php, and the Apache processes were growing large enough that I could only have 4 of them running at once, which killed any hope of decent concurrency. I decided to switch to using PHP with FastCGI and after some research decided to go with nginx. The switch has now been made and page generation is faster, the server can handle greater concurrency, and memory usage is under control.

I actually ended up using nginx, PHP, PHP-FPM, and xcache. I’m running 8 instances of PHP and 2 nginx worker processes. First, I got started by using the step-by-step instructions I found on someone’s blog. After the initial setup, there was still a lot of configuration to do, some of which was not trivial. Below are some notes from my experience:

  1. When setting up FastCGI processes for PHP, make sure the firewall isn’t blocking access to the port the FastCGI servers are listening on. If your firewall is filtering packets to the port, you’ll get a “504 Gateway Time-out” page from nginx whenever you try to access a PHP page. To open up the port, if you’re using iptables, add something to your iptables startup script like this:

    1
    
    iptables -A INPUT -p tcp -s localhost --dport 9000 -j ACCEPT
  2. Somewhere I saw a redirect example to eliminate the www from URLs that caused me to add this to the config file:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    server {
        listen          80;
        server_name     www.definingterms.com;
        rewrite         ^/(.*) http://definingterms.com/%1 permanent;
    }
    
    server {
        listen          80 default;
        server_name     definingterms.com;
        [...]
    }

    I’m not sure why I thought I needed this, but it was messing up the loading of static images on this blog. The right thing to do is just list multiple server_names for the host, and let WordPress handle the redirect:

    1
    2
    3
    4
    5
    
    server {
        listen          80 default;
        server_name     definingterms.com www.definingterms.com;
        [...]
    }
  3. Moving most of my sites from Apache to nginx was easy, but there was the problem of rewrite rules. A lot of the software I use (e.g. Wordpress, Mediawiki, Gallery) needs rewrite rules. If you’re using Apache, there’s always an example .htaccess file either in the documentation, or in some user forum. However, the nginx rewrite rules work differently, and you can’t always find an example config, so it took some time and brain power to get them all right. Actually, this is true for all parts of the nginx configuration. The English documentation is sparse and it’s sometimes hard to find examples of what you want to do.

  4. nginx doesn’t have CGI support. If you’ve got those one or two sites that use non-PHP CGI, you’ll have to set up a FastCGI instance for each language you want to support. For example, I had a copy of ViewVC running, which is written in Python. With Apache, it was just using CGI. With nginx, I’d have to constantly run a whole Python FastCGI process for the rare event when someone wants to browse ViewVC.

In the end, I think the move to nginx was worth it purely for the performance gains, since it keeps me from having to pay for a heftier VM every month. But, it did take a fair amount of work and if I had slightly more complex needs, it might not have been a good fit for me.