HOWTO: Install WordPress on Nginx

I recently moved all of my sites from a cheap shared host to a shiny new VPS at SliceHost, and couldn’t be happier. Running your own VPS means a great amount of flexibility since you have full root access to the server and get to configure everything exactly how you want it. That said, it also means that if you want to maintain high performance, you have to keep your resource usage to a minimum.

Apache is a very well-establish web server that can handle just about any situation. Unfortunately, that flexibility comes at the cost of size and relatively high demands on server resources. Nginx (“engine x”) is a lightweight web server/reverse proxy that is very efficient and perfect for hosting WordPress. Read on to see how that can be done…

Step One: FastCGI

First off, Nginx does not provide FastCGI for you (FastCGI is what your web server uses to interact with WordPress’s PHP code), so you’ve got to have a way to spawn your own FastCGI processes. My preferred method is to use the spawn-fcgi program provided by the web server lighttpd. You can use PHP’s built-in FastCGI manager php-cgi to do the same thing, but it’s not as straight-forward. Plus, if you learn how to use spawn-fcgi, you can easily adapt it for use with other web applications requiring FastCGI.

Install spawn-fcgi

To download and install spawn-fcgi, run the following commands. Don’t worry, all of the building happens in your current directory…nothing else will be installed on your machine.

$ wget http://www.lighttpd.net/download/lighttpd-1.4.18.tar.bz2
$ tar -xvjf lighttpd-1.4.18.tar.bz2
$ cd lighttpd-1.4.18/
$ ./configure
$ make
$ sudo cp src/spawn-fcgi /usr/bin/spawn-fcgi

NOTE: If you’re following the steps above verbatim, you will need to have root privileges in order to copy the binary to its final location…everything else should work fine as a normal user. To gain root privileges, the program sudo was used in the example above; you may or may not have access to sudo on your machine.

After spawn-fcgi has been copied to the desired location, you can safely remove the build directory and original source file:

$ cd ..
$ rm -rf lighttpd-1.4.18/
$ rm lighttpd-1.4.18.tar.bz2

Run spawn-fcgi

This part will be fairly distribution-specific, but I’ll provide the basic command that you’ll need. What you want to do is find a way to run this command as part of your init scripts so the processes will be spawned automatically when you reboot your server.

/usr/bin/spawn-fcgi -f /usr/bin/php-cgi -a 127.0.0.1 -p 53217 -P /var/run/fastcgi-php.pid

  • -f → the filename of the fcgi-application; in our case we want “php-cgi”, which is provided by your distribution’s PHP package. If you don’t know where to find it, try running which php-cgi on the command line.
  • -a → the IP address to bind the processes to; in our case we want the localhost
  • -p → the port number to bind the processes to; pick whatever you want that won’t cause a conflict (technically it would be best to pick a random number between 49152 and 65535), just make sure to remember the number and use that same port for your Nginx configuration file later on
  • -P → the location where to save the process id file; you can use this file to easily kill the processes later

For better security, you can also spawn the processes as a non-privileged user by specifying the user/group with the -u and -g flags respectively. For more information on all the available options, run spawn-fcgi -h on the command line.

If you’re interested in seeing the complete init script that I wrote for use with Arch Linux, you can download it here: fastcgi-php

Step Two: Complete 83.33% of the Famous 5-Minute Install

Next you should download the WordPress files and extract them to their final location on your server. Simply follow steps 1–5 of the Famous 5-Minute Install (the 6th and final step requires that your web server be up and running properly, so we’ll do it later). This guide will assume that you extracted the WordPress core files here: /srv/www/nginx/domain.com/

Step Three: Nginx Configuration

To get the web server up and running properly, the file you need to edit is called “nginx.conf” and is installed in different places depending on your Linux distribution. If you install Nginx from source, the default location is /usr/local/nginx/conf/nginx.conf, however yours may be somewhere else.

Once you find that file, open it with your favorite text editor and add a server declaration that looks something like this (I’ll cover what each part means after posting the code):

server {
    listen       12.34.56.78:80;  # your server's public IP address
    server_name  domain.com;      # your domain name

    location / {
        root   /srv/www/nginx/domain.com;  # absolute path to your WordPress installation
        index  index.php index.html index.htm;

        # this serves static files that exist without running other rewrite tests
        if (-f $request_filename) {
            expires 30d;
            break;
        }

        # this sends all non-existing file or directory requests to index.php
        if (!-e $request_filename) {
            rewrite ^(.+)$ /index.php?q=$1 last;
        }
    }

    location ~ \.php$ {
        fastcgi_pass   localhost:53217;  # port where FastCGI processes were spawned
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME    /srv/www/nginx/domain.com$fastcgi_script_name;  # same path as above

        fastcgi_param  QUERY_STRING       $query_string;
        fastcgi_param  REQUEST_METHOD     $request_method;
        fastcgi_param  CONTENT_TYPE       $content_type;
        fastcgi_param  CONTENT_LENGTH     $content_length;

        fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
        fastcgi_param  REQUEST_URI        $request_uri;
        fastcgi_param  DOCUMENT_URI       $document_uri;
        fastcgi_param  DOCUMENT_ROOT      $document_root;
        fastcgi_param  SERVER_PROTOCOL    $server_protocol;

        fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

        fastcgi_param  REMOTE_ADDR        $remote_addr;
        fastcgi_param  REMOTE_PORT        $remote_port;
        fastcgi_param  SERVER_ADDR        $server_addr;
        fastcgi_param  SERVER_PORT        $server_port;
        fastcgi_param  SERVER_NAME        $server_name;

        # required if PHP was built with --enable-force-cgi-redirect
        fastcgi_param  REDIRECT_STATUS    200;
    }
}

You will need to edit all of the highlighted sections above using your own information. The first part is merely the server declaration where you define what your server’s publicly available IP address is and what domain name that address is associated with.

Next we add to that some default settings for the root location. The key part here is that WordPress uses the “Front Controller” design pattern, meaning that any request for a file that does not exist on the server should be handled by the main index.php file. To do this, we need an appropriate set of rewrite rules pointing to the proper path of our installation.

Last, we add one more location block that tells Nginx to dynamically forward PHP requests to the FastCGI processes we spawned earlier. That’s it!

Step Four: Finishing Up

Everything should be good to go…all you need to do now is start your Nginx server process (another distribution specific command), then complete the 6th step of the Famous 5-Minute Install and you should have WordPress up and running on Nginx!

If any of this needs further clarification or you’re just having trouble, leave me a comment and I’ll see what I can do to help…

18 Comments

  1. ric
    Posted February 28th, 2008 at 8:46am | Permalink

    nice tutorial. but how did you go about setting up the rewrite for wordpress’ permalink?

  2. Posted February 28th, 2008 at 11:18am | Permalink

    “how did you go about setting up the rewrite for wordpress’ permalink?”

    As long as all appropriate requests get forwarded to the main index.php file, you shouldn’t have to worry about rewrite rules beyond that; WordPress will figure it out if you’ve specified a permalink structure. For example, here at ElasticDog.com, I have this custom structure set in the Admin interface under Options → Permalinks:
    /%year%/%monthnum%/%postname%/

  3. Daniel
    Posted April 2nd, 2008 at 4:01pm | Permalink

    Can you update this for lighttpd-1.4.19?

    On a new Ubuntu 7.10 slice, 1.4.19 won’t ./configure. However, 1.4.18 does.

  4. Posted October 11th, 2008 at 4:51am | Permalink

    That helped, thanks!

  5. Posted October 30th, 2008 at 4:40pm | Permalink

    Hi Aaron,
    Nice tutorial here. Quick question for you….

    I am wanting to create a Wordpress blog within my Rails application and am wondering how in the heck I would do this.

    Can you define two app locations in the nginx.conf file? If so, how would this be done.

    example:
    http://railsapp.com (nginx 1)
    http://railsapp.com/blog (nginx 2)

    Thanks

  6. Avtar
    Posted October 30th, 2008 at 11:32pm | Permalink

    @Daniel … I just finished installing this using lighttpd 1.4.20 on a new Ubuntu 8.10 slice (it should probably work on previous versions as well). Only difference was that I had to run the configure script like this:
    ./configure –without-pcre –without-zlib –without-bzip2

  7. Posted February 18th, 2009 at 1:09am | Permalink

    This works well in combination with this tutorial: http://www.howtoforge.com/nginx_php5_fast_cgi_xcache_ubuntu7.04

    I used both of these and an now running Wordpress on a Slicehost slice.

  8. Posted February 18th, 2009 at 1:09am | Permalink

    Also, @Jonathan, yes you can, just specify a second server block with a different server_name.

  9. Posted February 26th, 2009 at 1:44pm | Permalink

    How about feed? I got 404 error when try to get /feed ;(

  10. Posted February 27th, 2009 at 4:50pm | Permalink

    spawn-fcgi is now a separate project. See http://redmine.lighttpd.net/projects/spawn-fcgi/wiki/SVN

  11. Satyajit
    Posted March 18th, 2009 at 7:39pm | Permalink

    Hi Aaron,
    I am trying to set up a wordpress on an already existing rails app (either as blog.myserver.com or myserver.com/blog). This article helped me immensely to set it up real quick. However, now after restarting nginx, it still going to rails app, my php-cgi is running on 53217, but I am unable to render a php page.
    When I try to access: mserver.com/blog/wp-admin/install.php, it gives me rails routing error:
    Routing Error: No route matches “/blog/wp-admin/install.php” with {:method=>:get}
    What may be missing?
    I have 2 server blocks in the nginx config (may be it will be a good idea to show a sample nginx config file of multiple servers in this page), but it doesn’t seem to be going to the php handler. The path to php-cgi etc are correct. Can you help?

  12. ben
    Posted April 4th, 2009 at 12:03pm | Permalink

    Your rewrite rules helped me a lot! thanks for the post!

  13. Alex
    Posted June 29th, 2009 at 6:46pm | Permalink

    Also you can find how to install WordPress on the nginx you can find here
    http://www.linuxspace.org/archives/1576

  14. Posted August 6th, 2009 at 10:18pm | Permalink

    Hi,
    Thanks for the article but I am having a problem. I followed what you wrote step-by-step on my ArchLinux box running Nginx (also at SH), however, when I do this “which php-cgi” nothing is found. I installed the script you wrote, which says DONE when I run fastcgi-php but when I “ps aux | grep fastcgi” nothing appears so I dont think it worked.

    Finally, after all that I setup the .conf file for the server, restarted the server and visited viewsfromapontoon.com but get a 502 bad gateway error.

    I dont think ArchLinux installed PHP when installed from SH but Im not sure. Could that be the problem? What do you suggest?

    Thanks,

    Josh

  15. Posted September 7th, 2009 at 11:37am | Permalink

    I looking this tutorial , it’s very helpful,
    thanks again.

  16. Posted November 4th, 2009 at 1:21pm | Permalink

    This post is *great* even almost 2 years later! Thaanks!

  17. Posted November 19th, 2009 at 12:25pm | Permalink

    It is a good tutorial. I think in my region all people uses apache web server. i have to probe lightthpd or maybe Nginx

  18. Stuart Coyle
    Posted December 17th, 2009 at 5:57pm | Permalink

    Thanks for the info. I have found though that spawn-fcgi is now in it’s own project so theres no need to get the whole of lighttpd.

    News for spawn-fcgi at: http://redmine.lighttpd.net/projects/spawn-fcgi/news
    Download: http://www.lighttpd.net/download/spawn-fcgi-1.6.3.tar.gz

Post a Comment

Your email address is never published nor shared. Required fields are marked *

*
*