Supercharge Your Self-Hosted WordPress Blog with Nginx & FastCGI

Supercharged WordPress

Supercharged WordPress

If you are running WordPress on a VPS, you’ve got all the power in the world to run the site exactly the way you want. If you know how to use that power, you can be serving tens of thousands of visitors using a 256MB VPS account. Amazed? Read on!

WordPress runs on something knows as an AMP (Apache, MySQL, PHP) stack. Apache is your web server software. MySQL is your database engine. And PHP is the language WordPress is written in. Out of these three, the web server is the only component that you can replace with something else. Most people use Apache just because it’s very simple to set up — and that WordPress supports it out of the box. But what if you could tweak around and install another web server that is immensely faster than Apache?

Enter Nginx. Pronounced Engine X (Engine 10), this web server software was created by a Russian developer to solve something known as the C10K problem. Most traditional Web servers (Apache included) uses threads to serve each request. I know this is kind of technical, but you’ll see — creating new threads is a very expensive operation for operating systems, and there’s a limit to the number of threads that can can be spawned. As such, the theoretical limit for Apache is 10,000 concurrent connections.

Nginx is a breed of new Web servers that use an event-driven technique to Web serving. Jobs are performed asynchronously (which basically means that tasks are executed in parallel, and that one task doesn’t have to complete for the next to commence) — which makes it immensely fast. Every new connection uses a small, and more importantly predictable amount of memory. The end result? A fast Web server which uses very less memory, and can serve more than 10,000 connections concurrently.

‘Nuff said.

Will WordPress Like Nginx?

Good question. One of WordPress’s quirks is that it uses files named .htaccess (which is an Apache-specific feature) which are used to control redirections if you use pretty permalinks. If you don’t use pretty permalinks (e.g., your blog has links like then you’re pretty much set. If you do use pretty permalinks, (like then you’ll need some additional configuration (which I’m going to show you here).

Now there’s another problem. WordPress is very extensible, which means it supports plugins. WordPress itself doesn’t rely much on .htaccess files other than to handle redirections, but plugins may use it to handle access-control and permissions. Now the list of such plugins is infinitesimally small, and any such plugin which uses .htaccess files is badly designed anyway, since plugins shouldn’t make assumptions about the Web server its running under, but if you must use those plugins, then you’ll either have to do without the access-control (you can chmod the files appropriately), or you’ll have to do without Nginx.

Us? We still aren’t big enough to warrant moving to VPS, so we use whatever server out hosting provider provides. But here’s some trivia for you — itself runs on Nginx.

Getting Started

I’m assuming you’ve got a VPS with Apache, MySQL and PHP already hosting your blog. What we’ll do is install Nginx and the PHP connector, and switch the site over from Apache to Nginx in a single step that will typically involve less than a second of downtime.

Most servers run either Debian/Ubuntu Server or RHEL/CentOS. If you’re one of the lucky ones to afford SUSE Linux Enterprise, you’ll have to figure out how to install Nginx yourself.

Nginx development takes place very fast. For this reason, your distribution binaries are generally going to be way out of date. But there’s a way out — Nginx provides official repositories (yes, complete repos, not just binaries) for many operating systems.

If you run Debian Squeeze, add these lines to your /etc/apt/sources.list:

deb squeeze nginx
deb-src squeeze nginx

If you run Ubuntu Server, the lines for /etc/apt/sources.list are:

deb lucid nginx
deb-src lucid nginx

Needless to say, you should be running the LTS version of Ubuntu Server. Nginx also has official versions for RHEL and CentOS. To add their Yum repo, create a new repo file at /etc/yum.repos.d/nginx.repo with the contents (for CentOS):

name=nginx repo

And for RHEL:

name=nginx repo

Now you can install Nginx using your package manager. For Debian/Ubuntu, run:

sudo apt-get update && sudo apt-get install nginx

You’ll get Certificate errors for Nginx because apt does not automatically add certificates for repositories. The certificate links are in the Appendix section at the end of this article. Anyway, for RHEL/CentOS, run:

sudo yum install nginx

You now have Nginx. You’ll have to install the PHP FastCGI connector now.

You’ll need to add a repository if you’re on Debian Squeeze. Add these lines to the /etc/sources.list file:

deb stable all
deb-src stable all

You’ll also need to add a repository if you’re on RHEL/CentOS 5. Run the following commands:

sudo rpm -Uvh
sudo yum --enablerepo=webtatic update

Now, to install, on Debian/Ubuntu type:

sudo apt-get update && sudo apt-get dist-upgrade
sudo apt-get install php5-fpm

And on CentOS/RHEL, type:

sudo yum --enablerepo=webtatic install php-fpm

You’re officially on the road. All you need to do now is configure Nginx, start php-fpm, and then in one step stop Apache and start Nginx.

Configuring Nginx

I’m assuming your Webroot is at /var/www. If not, adjust the following file appropriately. Open up the file /etc/nginx/sites-available/default, and replace everything in there with the following:

server {
    listen;                # Your server's public IP address
    server_name;                   # Your domain name
    root         /var/www/;                     # Absolute path to your WordPress installation

    try_files $uri $uri/ /index.php;            # Handle permalinks
    if (!-e $request_filename) {
          rewrite ^.*$ /index.php last;         # More code to handle permalinks
    }                                           # This is what the HTACCESS is basically for

    location ~ \.php$ {
        include        fastcgi_params;
        fastcgi_pass   localhost:9000;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;

That’s it. Now, we’ve got to start php-fpm, by doing:

sudo /etc/init.d/php-fpm start

And then in one fell swoop, switch the Web server:

sudo /etc/init.d/httpd stop && sudo /etc/init.d/nginx restart

Don’t worry about the restart thing in the last command — some ditributions think its really cool to start nginx on port 8000 as soon as is it’s installed.

Now access your site. Happy?

You can now go ahead and remove all Apache packages from your system. That should be it. Oh, you should go ahead and install this plugin.

What If It Doesn’t Work?

Leave Comment below, and we’ll help you out.

Appendix: Certificates For Debian/Ubuntu

To add the DotDeb certificate, do:

cat dotdeb.gpg | sudo apt-key add -

And to add the Nginx certificate, do:

gpg --recv-key 7BD9BF62
gpg --armor --export 7BD9BF62 | sudo apt-key add -


  1. The reason NginX is faster than Apache as explained in this post is not taken. Running threads parallely is not the property of a thread but that on the system on which the threads are working. Threads do run parallely and do not have to wait for each other to get completed

    • @arnie41178 1) Threads do run in parallel, but for four cores and 10,000 connections, that’s 2500 context switches per core.

      2) If you’ve ever done asynchronous programming, you’ll know. If not, asynchronous programming relies on triggers and callbacks. There are multiple threads, like about 20-25, and they all form something called a thread pool. A task (like serving that webpage) is created and delegated to a thread from the pool. Once the task finishes, it fires the callback to let the main server know that its done, but the main server continues its work as soon as the delegate is created and pushed out to a thread in the pool. New threads aren’t spawned for every task – the threads are always there. And there are just one hundredth of the number of threads compared to a normal server.

  2. Thanks alot for this short, but powerful tutorial. You just saved me from an embarrassment from a client running a memory-hungry “wordpress” blog.
    Before the thing could work on my Ubuntu 12, I had to do some tweaking.
    1. /etc/nginx/sites-available/ was not included in my configuration file. So I added a line with “Include /etc/nginx/sites-available/*;” to “/etc/nginx/nginx.conf” file.
    2. An index file “index.php” was not specified in the default confuguration so the index of the site didn’t work until I embedded the following in the server { } of “/etc/nginx/sites-available/default” file.

    location / {
    index index.html index.htm index.php;
    It now works like a charm!


Please enter your comment!
Please enter your name here