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.
sudo aptitude update sudo apt-get install nginx /etc/init.d/nginx start
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:
sudo aptitude install python-software-properties sudo add-apt-repository ppa:brianmercer/php sudo aptitude update
Now that we have the new repository, we can install PHP5:
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
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:
pm.max_children = 20
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:
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/*; }
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:
# 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; } }
Now, we need to create the symlink from sites-enabled to sites-available:
ln -s /etc/nginx/sites-available/www.example.com /etc/nginx/sites-enabled/www.example.com
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.
Have you seen any issues running PHP 5.3 on Ubuntu from the repo you added? My company hesitates to add additional repos for security, but we also are thinking about migrating to Zend Framework 2.
LikeLike
Nice tutorial. You might wish to add some security tips to this… https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx-dont-trust-the-tutorials-check-your-configuration/
LikeLike
Huge shouts for the tutorial — it worked nice & smooth for me.
LikeLike
Great tutorial! I had it up and running and it worked without a hitch.
Thank you very much again!
LikeLike
I believe you could replace those if clauses in the nginx config with tryfiles, as suggested at http://wiki.nginx.org/IfIsEvil.
LikeLike
And by tryfiles I mean try_files. 🙂
LikeLike
root@mf102 ~: add-apt-repository ppa:brianmercer/php
Error: can’t find signing_key_fingerprint at https://launchpad.net/api/1.0/~brianmercer/+archive/php
Anyone have a suggestion?
LikeLike
@Israel
It means the repo is gone. The new LTS of ubuntu is just about to release, and it will have PHP-FPM in it’s official repos. I decided to go ahead and upgrade early since it’s so close to release anyway. sudo do-release-upgrade -d
LikeLike
i have an issue, i am around 23rd day about this matter, I installed nginx usiing this tuts. , Worked fine, Google listed my website, it is fast. But timthumb not working with nginx, i installed apache with fcgid with another vps, found working , with modern wordpress theme.
while checking long time, i found that there is no php-fpm.conf file in my system, not generated automatically, the file is empty!
just a php-fpm.conf can solve this?, if yes, kindly give me default php-fpm.conf file.
LikeLike
i found great installation instruction in this blog, found worked for me, i didnt found any post problem related to it
http://www.discusswire.com/nginx-php-fpm-mysql-auto-install-ubuntu/
LikeLike
@garrett
No it’s not
@Israel
I fixed it by running:
$ sudo apt-key adv –keyserver keyserver.ubuntu.com –recv-keys 8D0DC64F
$ sudo apt-get update
LikeLike