Setting Up Nginx & PHP-FPM on Ubuntu 10.04

Posted by Justin Carmony on October 24th, 2011

This is another wonderful setup that I’ve found myself using rather than the traditional Apache & mod_php setup.


What is Nginx?


Nginx (pronounced engine-x) is a fast, powerful, lightweight web server. I won’t go into the theory under-the-hood, but it’s focus is high concurrency with low memory usage. So while Apache is more robust in supporting many different features, nginx focuses on handling the important features very quickly. I still use Apache internally for our SVN & Trac web server. Heck, even at this time I’m using Apache to host this blog. However, Dating DNA, Clipish, CEVO, Alienware Arena, and some other high traffic sites/apis use nginx.


Ngnix, unlike Apache, doesn’t actually load PHP. Instead, it hands it off as a proxy to a “php handler” which acts like an Application Server. So nginx by itself won’t serve PHP files, but just static files.


What is PHP-FPM?


In the past, when working with something like Nginx or lighttpd, you would use spawn-fcgi to host your PHP application. However, spawn-fcgi had some major drawbacks and problems. So a guy named Andrei Nigmatulin created PHP-FPM, which stands for “PHP FastCGI Process Manager.” Since then, several others have contributed and ultimately it was include into the PHP core in version 5.3.3.


So from a high level look, on every PHP request Apache will load the entire installed PHP environment each time. This is for every request, and while it has been optimized as much as it can, that is a lot of overhead! With PHP-FPM, it will spin up a configurable amount of children. Each load the PHP environment and then will serve as many requests as it can without having to reload the environment. This saves on a lot of overhead!


Why use Nginx & PHP-FPM?


I should note, it is possible to configure/compile Apache in such a way that it can have similar performance capabilities. However, it takes a ton of work. Meanwhile, Nginx & PHP-FPM are very fast from the start, so I prefer just using them. You do lose some features, like .htaccess files won’t work so you’ll have to do that configuration in your virtual hosts.


How to Setup Nginx & PHP-FPM


Nginx


First off, lets setup Nginx.


[code]

sudo aptitude update

sudo apt-get install nginx

/etc/init.d/nginx start

[/code]


Thats it! If you go to your server’s IP Address or Domain Name you should see a “Welcome to Nginx!”


PHP-FPM


Because PHP-FPM is only included by default in PHP 5.3.3 and later, and Ubuntu 10.04 LTS only has PHP 5.2.3, we have two options. Either we can install by source, or we can add another repository to install PHP-FPM. The latter is much, much easier, and there is a good PHP-FPM Repo for Ubuntu 10.04. To add it, you just run the following commands:


[code]

sudo aptitude install python-software-properties

sudo add-apt-repository ppa:brianmercer/php

sudo aptitude update

[/code]


Now that we have the new repository, we can install PHP5:


[code]

sudo aptitude install php5-cli php5-common php5-mysql php5-suhosin php5-gd php5-dev

sudo aptitude install php5-fpm php5-cgi php-pear php5-memcache php-apc

/etc/init.d/php5-fpm restart

[/code]


Excellent! Now, if you need to change some of PHP-FPM’s configurations, they are found in /etc/php5/fpm/. The file php5-fpm.conf configures how FPM will opporate, and the php.ini is the settings file that PHP will use while running in FPM.


A few settings I like to change in /etc/php5/fpm/php5-fpm.conf:


[code]

pm.max_children = 20

[/code]


The php5-fpm.conf that comes is pretty well documented on the different settings. Once you make a change, make sure to restart php5-fpm.conf: /etc/init.d/php5-fpm restart


Configuring Nginx


Now, we have a few settings for Nginx. The configuration files are found in /etc/nginx/. First we’ll edit nginx.conf. Here are a few settings we’ll want to change:


[code]

user www-data;

worker_processes 4; # 1 to 4, I normally put this to the number of cores


error_log /var/log/nginx/error.log;

pid /var/run/nginx.pid;


events {

worker_connections 1024;

multi_accept on; # uncomment this line

use epoll; # Add This - We’ll want Nginx to use epoll for event timing

}


http {

include /etc/nginx/mime.types;


access_log /var/log/nginx/access.log;


sendfile on;

#tcp_nopush on;


#keepalive_timeout 0;

keepalive_timeout 65;

tcp_nodelay on;


gzip on;

gzip_disable "MSIE [1-6].(?!.SV1)";


include /etc/nginx/conf.d/.conf;

include /etc/nginx/sites-enabled/;

}

[/code]


Now, we need to add a VirtualHost! Nginx uses the same layout in Ubuntu as Apache, so we’ll add configurations for each site we want under /etc/nginx/sites-available/. So using vi, nano, or whichever editor you prefer, create a /etc/nginx/sites-available/www.example.com file:


[code]

# rewrite from example.com to www.example.com

server {

listen 80;

server_name example.com;

rewrite ^(.) http://www.example.com$1 permanent;

}


server {

listen 80;

server_name www.example.com;

access_log /var/log/nginx/www.example.com.access.log;

error_log /var/log/nginx/www.example.com.error.log;


client_max_body_size 4M;

client_body_buffer_size 128k;

expires 24h;


location / {

root /var/www/example.com/;

index index.html index.php;


# if file exists return it right away

if (-f $request_filename) {

break;

}


if (-e $request_filename)

{

break;

}


# Useful rewrite for most frameworks, wordpress

if (!-e $request_filename) {

rewrite ^(.+)$ /index.php last;

break;

}


}


location /nginx_status {

# copied from http://blog.kovyrin.net/2006/04/29/monitoring-nginx-with-rrdtool/

stub_status on;

access_log off;

allow 127.0.0.1;

deny all;

}


location ~ .php$ {

expires off;

include /etc/nginx/fastcgi_params;

fastcgi_pass 127.0.0.1:9000;

fastcgi_index index.php;

fastcgi_param SCRIPT_FILENAME /var/www/example.com/$fastcgi_script_name;

}

}

[/code]


Now, we need to create the symlink from sites-enabled to sites-available:


[code]

ln -s /etc/nginx/sites-available/www.example.com /etc/nginx/sites-enabled/www.example.com

[/code]


Restart nginx with “/etc/init.d/nginx restart”. Go ahead and put a test.php file in your directory with a Hello World example, and see if it works. It should work, and you should be good to go.

About Justin Carmony

Justin is the Director of Engineering for Deseret Digital Media, President of the Utah PHP Usergroup, and member of the Utah Open Source Foundation which organizes the OpenWest Conference. Justin loves just about anything with web technologies from PHP, JavaScript, Node.js, Salt, and managing engineering teams.

Learn More