Adventures With Nginx and PHP

Updated 5/22/2013: After some issues with this setup, I’ve updated the Dotdeb sources to not break after the release of Debian 7

As some may have seen on twitter, I have been toying with ditching the typical Apache in favor of nginx on my production web server. I chose to do this for four reasons:

  1. I’ve setup Apache more times than I can count, and nginx looks like the new cool kid on the block.
  2. I’m hoping that the raving fanboys are right, and the memory footprint is far better than Apache. Perfect for a cheap VPS.
  3. When I switched to W3 Total Cache for this blog, nginx seems to be the next logical step. Considering it excels with serving static HTML and gziped files, the combo was too good not to try out.
  4. It seems that I either love a challenge, or am incredibly masochistic.

When I began my journey to setup a LEMP (Linux EngineX MySQL PHP) server stack, I had no idea how many conflicting guides there are out there. So hey, why not put yet another one out there? I am writing this during the whole install/setup ordeal and picking what seems to make the most sense from the various guides, so hopefully this will be simple and straightforward.

Let’s start with the tools we will use: I am working with a Linode 512 running Debian 6.0, and plan to use php-fpm to manage my PHP processes. I won’t go too much into my decision to use php-fpm, as opposed to basic FastCGI or CGI. It just seemed to be the most popular and best performing option out there right now. Though I haven’t done enough research and testing yet to necessarily back up that opinion with cold, hard facts.

Once you get your linode created and log in, install whatever base utilities you need/prefer (editor and such), then we can get some basics out of the way. For simplicity’s sake I chose to setup everything from root, but if you want to do this with a regular user, make sure to sudo or su through everything.

The Basics

Something you may have already done, but I consistently forget when setting up a new server: setting up the hostname and Fully Qualified Domain Name (FQDN).

Hostname:

echo "ServerName" > /etc/hostname
hostname -F /etc/hostname

FQDN:

Modify /etc/hosts and add your machine’s IPv4 and IPv6 addresses (which you can find by running ifconfig) along with the host and domain name, replacing my placeholders as needed.

127.0.0.1                       localhost.localdomain       localhost
[IPv4 Address]                  ServerName.example.com      ServerName

::1                             ip6-localhost ip6-loopback
fe00::0                         ip6-localnet
ff00::0                         ip6-mcastprefix
ff02::1                         ip6-allnodes
ff02::2                         ip6-allrouters
[IPv6 Address]                  ServerName.example.com      ServerName

Now we add Dotdeb, a great resource for debian installs that provides bleeding edge packages for a stable and up to date LA(/E)MP stack. Update your /etc/apt/sources.list to include the repo:

deb http://packages.dotdeb.org squeeze all
deb-src http://packages.dotdeb.org squeeze all

Then add the GnuPG key:

wget http://www.dotdeb.org/dotdeb.gpg
apt-key add dotdeb.gpg

And with that done, we can get down to to the nitty-gritty!

Installing The (L)EMP Stack

If you haven’t yet, make sure to update your package listings and update anything out of date with apt-get update and apt-get upgrade. Something to keep in mind as you go through the various installs, if you don’t always do this anyway, run the install with -s first to make sure apt is not trying to install apache2 or some other random, unneeded nonsense.

Now if it hasn’t become overwhelmingly obvious by now, I plan on handling all of the installs through apt. Sure I may not be as hard core or cool compared to those who compile everything themselves, but I will take the ease of apt-get install and apt-get upgrade over geek cred any day. Not to mention that there are already tons of guides, some even linked above, that lead you through the hand compiled method.

Rms_at_pitt

I will never have a beard this awesome, no matter what I compile.

nginx

apt-get install nginx

MySQL

apt-get install mysql-server

PHP5

For a no-frills php install, just run:

apt-get install php5 php5-fpm php-pear php5-common php5-cli php5-mysql

This will only install the core php5 executables and libraries we will need to run simple php scripts through nginx, and to interact with MySQL. There are plenty of other libraries and extensions required to take full advantage of more advanced web apps, but that can be covered later.

At this point you you have the full LEMP stack installed, damn easy right? All that’s left is tweaking some of the configs.

Basic Configs

The purpose of this setup is to get you up and running, with as little deviation from defaults as possible. With php-fpm and nginx, there are tons of tweaks for performance and customization, but I will leave that for another post.

PHP-FPM

One performance tweak I am going to allow myself here is switching php-fpm to use a UNIX socket instead of the default TCP loopback. Some say the difference in performance between the two is negligible, but I prefer it regardless. Hopefully one day soon I will have time to test the theory myself.

Begin by creating/choosing a directory for the socket file and granting ownership of the directory the socket will be created in, to the user and group that will listen for requests (defaults shown):

mkdir -p /home/sockets/php
chown www-data:www-data /home/sockets/php

Open up /etc/php5/fpm/pool.d/www.conf and look for the line that specifies where php-fpm listens for requests, looks something like this:

listen = 127.0.0.1:9000

And change it to listen on a socket that you just created the directories for:

listen = '/home/sockets/php/php-fpm.socket'

Scroll further down and uncomment these lines (remove the semicolons) to specify what user the socket will be created under:

listen.owner = www-data
listen.group = www-data
listen.mode = 0666

nginx

Before messing with the nginx configs, you will want to setup the directory structure for your web root and logs. This is strictly a matter of preference, so you can put the web root anywhere. Just make sure to modify the configs accordingly.

mkdir -p /home/webroots/default
mkdir /home/webroots/default/public_html
mkdir /home/webroots/default/logs
chown -R www-data:www-data /home/webroots/default

Nginx will keep usually the virtualhost config files in one of two places: /etc/nginx/conf.d/ or the apache style of files in /etc/nginx/sites-available/ sym-linked to /etc/nginx/sites-enabled/ when they are enabled. When in doubt, just look at /etc/nginx/nginx.conf for something like this to find out where the files are:

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

Knowing where to look, find the default site file and open that for edit. Update the web root and log location to the directories you created previously, along with the index to whatever file you have in your webroot:

access_log /home/webroots/default/logs/access.log;
error_log  /home/webroots/default/logs/error.log;

root   /home/webroots/default/public_html;
index index.php;

Then look for, and uncomment the following lines (this time remove the ‘#’ characters) to tell nginx where to send php script files to be run:

location ~ \.php$ {
       fastcgi_split_path_info ^(.+\.php)(/.+)$;
       fastcgi_pass 127.0.0.1:9000;
       fastcgi_index index.php;
       include fastcgi_params;
}

Of course since we switched to the UNIX socket, you will have to modify the fastcgi_pass line to read:

fastcgi_pass   unix:/home/sockets/php/php-fpm.socket;

Testing Things Out

With all of that set, create a test index file (/home/webroots/default/public_html/index.php is what we specified above) and make a simple html page with some php mixed in. I prefer to keep it simple by just writing a loop to print a bunch of list elements.

After doing so much, I like to restart the machine/vps to hopefully expose any catastrophic issues with the setup as quickly as possible. If you would rather avoid that, just make sure to restart both php-fpm and nginx so they get the updated configs.

Finally, we can see the fruits of our labor! Just navigate to the domain/ip address pointing to your server, and verify that you can access the page and the php script is actually being parsed. If that’s the case, then congratulations my friend, you have successfully installed and configured a LEMP stack!

nginx_home

This is what victory looks like

Now go crack open your favorite celebratory beverage, you deserve it!

d9fc_zombie_blood_caffeinated_energy_potion

Like one of these bad boys

%d bloggers like this: