High Performance WordPress with Nginx and PHP-Fpm

This is a step by step guide on how to set up your own unmanaged server or vps to run as a WordPress Performance server environment. Using this setup you will have the ability to host a large WordPress Multisite set up or numerous single installs. This guide assumes you have a basic understanding of using SSH via the Mac Terminal app or Putty for Windows and requires an unmanaged dedicated server or VPS hosting account with either the 32 or 64 bit Debian kernal available.

In my last guide I touted a Nginx reverse proxy cache with WordPress and Apache as the ultimate WordPress performance stack but since then I have found that there is really no reason to use Apache unless you have a specific need for it. Nginx has matured and works great with the WordPress rewrite engine and even W3 Total Cache now includes Nginx rewrite rules for page cache, minify and browser caching.

If you ever decide that managing you own web server isn’t for you then I highly recommend WP Engine WordPress Hosting WP Engine runs on Nginx and they handle all the caching for you.

Choosing a web host with Debian “squeeze” images available

Debian 6 aka “squeeze” is considered the grandfather of Linux distors and Debian is known for relatively strict adherence to the Unix and free software philosophies. Debian is also distributed with access to repositories containing thousands of software packages ready for installation and use.

Most of the large managed hosting companies don’t give you the option of choosing your Linux distro so your going to need to find one that does. The reason for this is that it’s much easier for a hosting company to provide support using cPanel or Parallels Virtuozzo VPS virtualization. Virtuozzo allows them to squeeze many more VPSs on a box and control the resources and your limited to guess what – Cent OS.

Your going to need a provider that offers Xen virtualization. Xen is a powerful open source virtualization platform that supports a wide range of guest operating systems including Linux – Debian, Ubuntu, Free BSD, Cent OS, Fedora and more. When you set up your account have your provider load the Debian 6 aka “squeeze” image on your VPS or install it on your dedicated server. If you have over 2GB memory go for the 64 bit version.

I use Softlayer (formally The Planet) for my dedicated server because of the state of the art data centers and major broadband backbone it’s connected to. It also has a very powerful back end portal and allows you to connect to your box over a private VPN. Linode, Slicehost, and VPS.net are also very good choices. I would stay away from Media Temple and Rackspace as I’ve had problems with both and they’ve had well documented security vulnerabilities in the past.

Your provider will either provide you with an ip address and password to connect to your server for the first time or give you access to a control panel that you can use to load the image.

Some hosts include the network setup on the image others provide a java ssh console to connect. If your only provided the java console you will need to set up the networking settings.

*Note: all entries in this article that require opening a file assume the nano text editor, some of you might prefer vim or if your a real Linux Ninja Emacs (If you use Emacs you don’t need to read this article .) If you prefer vim just substitue vi for nano.

If your provider pre-installed the image for you skip to Security.

nano /etc/network/interfaces

This is the file that contains the connection settings for each of the network cards on your server. You will need your ip address and the gateway address which is to the router. Your host should provide these for you.

With networking and ssh setup you will be able to connect via ssh using Terminal or Putty

ssh root@xxx.xx.xx.xx

Enter your password at the prompt and accept the key fingerprint prompt which will add your new server or vps to your local known_hosts file.

Securing your server

The first step is securing your server. To properly secure your server you need to disable password auth and use ssh keys to access your server. Your key authorization will also be used for adding files via an SFTP program like Transmit. We will also be updating all the packages and configuring the firewall using ufw.

Open another terminal window to generate the ssh keys on your LOCAL machine.

mkdir ~/.ssh
cd ~/.ssh
ssh-keygen -t rsa

You will be prompted for a password to further secure your key and a name to save it under. Unless you all ready have existing keys just press enter to accept the default name of id_rsa / id_rsa.pub. The id_rsa.pub file is your public key and will need to be moved to the server.

scp ~/.ssh/id_rsa.pub root@xxx.xxx.xx.xx:

You will be prompted for your server password and your public key file will be in your root directory. Now will move it to the correct place and add it to the authorized_keys file. Close your 2nd terminal window and go back to the one you were using and connected to the server with.

Now we will configure the firewall using ufw. UFW is an uncomplicated firewall that acts as an interface to control the servers iptables without the confusing syntax. It is shipped with Ubuntu but for Debian you will need to install: apt-get install ufw.

The following commands will open up the ports for ssh, web, smtp (php-mail), and mysql. You can add rules for any of the network services defined in the /etc/services file or roll your own custom rules.

Now we will restart ssh and test our connection. VERY IMPORTANT don’t disconnect your current ssh session! Test by opening another terminal window. If your on Mac you will get a keychain notice for your key password. Click the remember button so you won’t have to enter it every time.

Current terminal window

/etc/init.d/ssh reload

New Terminal window

ssh root@xxx.xxx.xx.xx
:Linux DebianLinux-001 2.6.32-5-amd64 #1 SMP Mon Mar 7 21:35:22 UTC 2011 x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Jul 12 21:40:45 2011 from 108-71-13-85.lightspeed.hstntx.sbcglobal.net
root@servername ~:

If you were successful give your self a pat on the back and close your original terminal window.

The Performance Stack – Nginx, PHP-FPM, MySQL

In the past, with Debian 5, it was very frustrating trying to stay up to date with the latest versions of PHP, MySQL and Nginx because the packages were always so outdated. Debian 6 shipped with up to date versions but if you want the latest performance packages your going to need the Dotdeb repositories.

Install Nginx, PHP-FPM, MySQL, APC

You will be prompted to accept installs and apt-get will make sure all dependencies are met and install additional packages if needed. When you get to the MySQL install a semi-graphical interface will pop up. Make sure you choose a password for the root mysql user.

If you have made it this far go grab a beer or an espresso you deserve it, Systems Administrator.

The .conf files – configuring your web server

The default .conf files included in the Dotdeb packages will almost work right out of the box. You will need to make a few adjustments.

Nginx and PHP-FPM
Before you set up the Nginx.conf files you need to decide your folder structure and where the root of your websites will live. I like to use /srv/www/sitename/public for the web root and /srv/www/sitename/logs for the error and access logs. The files in your web root need to be owned by the same user as Nginx runs under. The Debian way is to run the server as www-data.

File: /etc/nginx/nginx.confNote: be wary of some of the copy and paste guides out there. The Slicehost and Linode tutorials are out of date and contain security vulnerabilities. If you don’t understand something question it and do your own research. The following files have been tested and are in use on real production servers.

If your familiar with the Apache Vhost concept you will be fine with Nginx. The Nginx server files we create act as individual site vhost.conf files and can either be in one large file or for better organization you can create a separate file for each site. The Debian way is to create 2 directories under /etc/nginx/, sites-available for the files and sites-enabled for sym links pointing to the file in sites-available. This allows you to turn off a site without having to delete it if you ever need it again.

File: /etc/nginx/sites-available/your_domain.com
This is for a single WordPress install. We are also including the W3 Total Cache Nginx rewrite rules in a separate file w3-total.conf. You will need to run touch /etc/nginx/w3-total.conf and chown www-data:www-data /etc/nginx/w3-total.conf and list the path in the W3 Total Cache general settings so it can write to the file. *Note: Anytime you make a change to an Nginx server file you will need to restart.

Open a browser and go to your domain or ip and if you did everything right you should see:

WordPress Multisite, alternative configuration and multiple non WordPress vhosts
If you want to host a multisite setup or add additional websites to your server or VPS you can include the WordPress Multisite rewrite rules in a separate file and simplify your per site vhosts.

Use the Compatibility Check in W3 Total Cache to make sure everything is set up right. Yours will look similar to this one.

Set page cache and minify to disk enhanced. Object and database to APC. You can experiment with page cache via APC but with Nginx disk enhanced will most likely be faster.

Final thoughts

If your doing this for the first time set up a test install to get the hang of if before you rely on this for a production set up or client site. Using Debian and the apt-get repos it’s pretty easy to manage your own dedicated server or VPS and you can lose the cPanel training wheels. Not only will your page load times drop you will have a good feeling of accomplishment.

To maintain your packages run apt-get update and apt-get upgrade every once in a while and you can follow @dotdeb on Twitter to stay up to date with upgrades.

Feel free to leave a comment or question. I would love to hear how this set up works for you.

Yes you really only need the W3 rules for disc cache. They just add a finer level of control for the browser cache rules. I just updated the server file to show a full example of the W3 Rules using disk enhanced page cache and disk minify.

I’ve got a noob question about SSH keys. If I’ve installed the SSH key on the server it means that I can only login to it from my computer right? What if I don’t have my computer with me and have an emergency and need to SSH into the server?

Using SSH keys you will only be able to login if your computer contains a private key that matches a public key installed on the server. I prefer the added added security they provide but if you often need to access your server away from your computer then maybe a really strong password would be better for you.

If your using password authentication you can change the ssh port to prevent a majority of the brute force attempts. Also some VPS and dedicated server hosts have a java console you can use to access your server without having to use your ssh keys.

> When installing everything the first ‘php5-mysql’ should be ‘mysql-server’ instead since there is already a php5-mysql package a little later in the command

> There’s a missing closing ‘}’ at the end of the file in the sites conf

> Upon trying to install wordpress I got “Your PHP installation appears to be missing the MySQL extension which is required by WordPress.” Fixed this by editing the php.ini inside the php-fpm dir.
>> I un-commented ‘extention=mysql.so’ as well as uncommenting ‘extention_dir = “./”‘ and changing ‘./’ to /usr/lib/php5/20090626+lfs and all was well.

Hi, using your guide to try and become a sys admin :). Anyway, got stuck on the security bit. Have a windows machine so I used puttygen to make keys, got it moved over to the right spot, changed the things in the sshd_config I thought I was supposed to but can’t get in (using pageant).. Any thoughts?

Woohoo, figured it out… The file that puttygen created had some extra stuff in it. I nano’d in in the terminal you so wisely told us to keep open. deleted the contents, then pasted the actual code from the puttygen window and BAM. It’s working

Also, to add: “there is no need for Apache” is not true for most production environments. When Nginx gets real rewrite functionality, the ability to have mod_security equivalents etc, *without* a gazillion “IF” conditions in the config file (which according to Nginx itself slows down the server considerably) that’s when Nginx can survive on its own. Until then, sure there are websites running only Nginx with PHP-FPM, but they have sacrificed a lot of production quality stuff.

Just found this tutorial and managed to get the WordPress install working just fine. Great tutorial, thanks.

However, I have one small problem, namely WordPress 3.5.1 friendly URLs. The nginx re-write rules seems to prepend index.php onto all the permalink options, and if I have the 404 error option (the one where you mention the security hole), I just get 404 pages whenever I try to visit any content in the site.

How do I get rid of the “index.php” from the rewrite rule and stop receiving 404 errors on all the pages/posts? I’ve tried various other sites for solutions, as this is apparently quite common, but even the recommended solution by the nginx developers doesn’t work.