Nginx + PHP + PHP-FPM on Debian Etch 4.0
mercoledì, 30 aprile 2008 | di Gianluca | Archiviato in Tech | 7 interventi
This walktrough is intended for a just provisioned clean Server/Slice/VPS, running Debian 4 Etch. (Ubuntu 7/8 should work as well).
We are going to install a complete LEMP stack (Linux, EngineX, MySql, PHP), in order to run one or more wordpress blogs with the minimum memory footprint, and maximum performances.
Benchmark on a 256mb xen vps:
apache2+mod_php+xcache = 42 req/sec
nginx+xcache+php-fpm = 150 req/sec
NginX and PHP will be compiled from Source as these are softwares with a very fast development, and pre-compiled packages are often prehistoric and are not suitable to apply custom patches (like php-Fpm).
1) First of all we install all the needed software available from binary packages.
- I am going to install postfix, as mysql-server provides exim4 as a dependency otherwise, and I do prefer postfix as it’s easier to setup. This of couse could not apply to you, this is just a sample of my own configuration.
#aptitude install postfix
- Then of course we are going to install mysql
#aptitude install mysql-server
- We run this script to setup a root password for mysql and secure the installation a bit
#mysql_secure_installation
- We need to compile stuff, so we install all the needed libraries
aptitude install build-essential libtool libltdl3-dev libgd-dev libmcrypt-dev libxml2-dev libmysqlclient15-dev flex m4 awk automake autoconf bison make libbz2-dev libpcre3-dev libssl-dev zlib1g-dev vim re2c
- We are indeed going to compile from source PHP with the PHP-FPM patch. That’s why i do not install the php5-cgi package available both on debian and ubuntu. I should use spawn-fcgi from lighttpd project otherwise, but I rather prefer PHP-FPM both for easiness and performances.
#cd /usr/local/src
#wget http://it2.php.net/get/php-5.2.6.tar.gz/from/de2.php.net/mirror
#tar xzvf php-5.2.6.tar.gz
#wget http://php-fpm.anight.org/downloads/head/php-5.2.6-fpm-0.5.8.diff.gz
#gzip -cd php-5.2.6-fpm-0.5.8.diff.gz | patch -d php-5.2.6 -p1
#cd php-5.2.6
#./configure --enable-fastcgi --enable-fpm --with-mcrypt --with-zlib --enable-mbstring --with-openssl --with-mysql --with-mysql-sock --with-gd --with-jpeg-dir=/usr/lib --enable-gd-native-ttf --without-sqlite --disable-pdo --disable-reflection
#make all install
#strip /usr/local/bin/php-cgi
Of course you may use any PHP version. Procedures shouldn’t change that much. And, indeed, you may need to change ./configure options to match your needs. GD with JPG support, for instance, is needed if you want to take advantage of the gallery capability (with jpg resizing) in Wordpress. zLib is needed for automatic plugin update, and to gzip xml sitemaps, and so on.
- Then we setup PHP-FPM, choosing the user php-cgi should run as:
vi /usr/local/etc/php-fpm.conf
:63
www-data
:66
www-data
In the php-fpm.conf you also may be interested to setup an appropriate number of workers (default is 5).
This is a quote from PHP-FPM author and developer, Andrei Nigmatulin :
The practical approach is
1) watching 'top' for running php-cgi workers
2) watching 'netstat -np | grep 127.0.0.1:9000' for fastcgi connections (if in linux):tcp 0 0 127.0.0.1:9000 127.0.0.1:59053 ESTABLISHED 21881/php-cgi
tcp 0 0 127.0.0.1:9000 127.0.0.1:59057 ESTABLISHED -The first line corresponds to accepted fastcgi connection and the second is
still waiting in a backlog (not accepted).
You'll need to set higher max_children in php-fpm.conf in order to minimize amount of awaiting connections.
- We are then going to install X-Cache opcode php cacher, as it gives a good performance boost in my experience
#cd /usr/local/src
#wget http://xcache.lighttpd.net/pub/Releases/1.2.2/xcache-1.2.2.tar.gz
#tar xzvf xcache-1.2.2.tar.gz
#phpize
#./configure --with-php-config=/usr/local/bin/php-config --enable-xcache
#make install
- We install NGINX web server, without some mail proxy capabilities as i don’t need them.
#cd /usr/local/src
#wget http://sysoev.ru/nginx/nginx-0.6.31.tar.gz
#tar xzvf nginx
#cd nginx
#./configure --sbin-path=/usr/local/sbin --with-http_ssl_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module
#make
#make install
- And we customize nginx configuration file, in a debian-like fashion, so it’s easy to add several virtual hosts
#cd /usr/local/nginx/
#vi conf/ngingx.conf
user www-data;
worker_processes 2;
events {
worker_connections 768;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nodelay on;
keepalive_timeout 10 10;
gzip on;
gzip_comp_level 1; gzip_proxied any;
gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
include /usr/local/nginx/sites-enabled/*;
}
- We also customize the fastcgi_params file in /usr/local/nginx/conf adding the following line (saves a lot of time if you have several virtual hosts, as makes us able to do a simple include for each).
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
- A wordpress virtual host example, with perfect plain PERMALINKS (without messing with rewrite rules).
#mkdir sites-enabled
#vi sites-enabled/wordpress-domain.ext
server {
listen domain.ext:80
server_name www.wordpress-domain.ext;
index index.php;
root /var/www/wordpress-domain;
location / {
error_page 404 = //index.php?q=$uri;
}
location ~ .php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include /usr/local/nginx/conf/fastcgi_params;
}
}
Please note, when wordpress realizes you don’t run a mod_rewrite webserver like apache, it will present you a new ugly /index.php/bla_bla/ permalink structure, with those leading /index.php/ everywhere: so in Settings->Permalink you need to use the custom tags section to remove that index.php tag, and keep using your usual permalinks (very useful if you’re migrating your already existing blog from apache).
- Ok, now we should polish our php installation and enable modules and extension like xcache. This is a very simple and perfectible, but working, example:
#vi /usr/local/lib/php.ini
magic_quotes_gpc=0
[xcache-common]
zend_extension = /usr/local/lib/php/extensions/no-debug-non-zts-20060613/xcache.so
[xcache]
xcache.shm_scheme = "mmap"
xcache.size = 64M
date.timezone = "Europe/Rome"
default_charset = "utf-8"
- Let’s check everything is working.
At this time YOU of course need DNSs (or at least hosts file) properly set-up.
You also need wordpress installed and properly configured in the root /var/www/whatever/ directory!
And remember to import your previous mysql databases if you’re changing server!
If you are changing server at this time you should also stop apache first, otherwise nginx won’t bind on the same :80 port, of course
#php-fpm start
#nginx
Try and visit your blog, and it should work. If something does not work (ie. blank pages, random errors) you have to double check your php ./configure options, because maybe you lack something. I am not a php expert so I can’t help you with this, but i can assure you i run SEVERAL wordpress blogs, both 2.3.3 and 2.5.1 version, with LOTS of plugins, and everything works for me.
- If everything is working, SUCCESS! You just may want to create an init script for nginx, and add it to autostart along as php-fpm init script, so when your server reboots you don’t need to start manually php-fpm.
Here you find a working init.d script
Follow the instructions, including the
#/usr/sbin/update-rc.d -f nginx defaults part.
Then do the same for PHP-FPM, that luckily already provides us with a init script, so :
#cd /etc/init.d/
#ln -s /usr/local/sbin/php-fpm php-fpm
# /usr/sbin/update-rc.d -f php-fpm defaults
- Try to reboot the server/vps and everything should be starting and working just fine.
- Of course if you’re changing server from apache to nginx, the first one should be always stopped (vi /etc/defaults/apache2 , replace 0 with 1).
Here you go.
maggio 23rd, 2008 at 9:20 (#)
Addendum: Don’t forget to rotate logs, so you can process and delete them.
#vi /etc/logrotate.d/nginx
/usr/local/nginx/logs/*.log {
daily
missingok
rotate 9
compress
delaycompress
notifempty
postrotate
kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`
endscript
}
luglio 16th, 2008 at 22:25 (#)
Hi,
I don’t know if I have to speak english … anyway … Do you think it’s a good guide for Hardy 8.04.1 ? Or it’s 7.10 native ?
And … can I use it as is for Ubuntu Hardy 8.04.1 ?
Thanks
Carlo
luglio 16th, 2008 at 22:49 (#)
Carlo this entry has been written in English – despite the blog main language – just to reach a broader audience, so I’d appreciate to keep comments in that language as well in order to make them useful for everyone stopping by.
Coming to the question, the walktrough has been written and tested in Debian 4.0 etch, but most part will work on any *nix system as the main software (nginx+ php-fpm + php) will be compiled from sources.
I have infact successfully deployed nginx systems following these guide lines on several platforms (debian, ubuntu, centos, freebsd, sun solaris).
The only part where this tutorial is distribution-dependent is where I install the needed libraries from binary packages at the beginning (the ‘aptitude install’ part).
Specifically, as Ubuntu 8.04 LTS is completely Debian based this should work seamlessly following the tutorial, you just may need to change the name of some libraries according to the package names (i.e.: libjpeg-dev and libpng-dev have a different name in Ubuntu). Apt will suggest you an alternative, anyway.
Of course – despite the tutorial being really step by step – you need a decent experience in linux system administration to implement this solution and you need at least to know how to use VI or a similar text editor, this goes without saying!
ottobre 18th, 2008 at 12:29 (#)
[...] large part of this post is compromised of this tutorial I found on the web on nginx. Really well written and modified a little by me for [...]
novembre 28th, 2008 at 1:22 (#)
[...] This set up interestingly serves around three times more requests per second than apache2 mod_php xcache.Nginx PHP-FPM Xcache Debian Etch. [...]
gennaio 21st, 2009 at 4:47 (#)
CentOS5.2にnginx + php-fpm(PHP FastCGI Process Ma……
nginxのことについて調べていると、たまたま
Nginx + PHP + PHP-FPM on Debian Etch 4.0
というエントリーを見つけました。
早速CentOSで試してみます。
MySQLは使いたいので、インストール
yu…
giugno 1st, 2009 at 10:30 (#)
Just a quick note on the “benchmarking method”, as someone contacted me to ask for further information on the performance improvement switching from apache+mod_php to nginx + php_fpm.
This was a http-perf benchmark based on my own website, of course “req/sec” is NOT THE SAME as “page views / sec”.
Aside that your mileage may vary, my improvement results could not be repeatable for some simple reasons:
1) you could be running some other processes on your vps (imap server, antispam daemon) that i don’t run,
2) your wordpress php codebase could be different (dozen of plugins require more time to be processed by the php interpreter than a simple blog like mine),
3) your mysql server could be poorly tuned,
4) your mysql server could be way more loaded, because you run a lot of addictional plugin, you display a lot of stuff in the home page, and so on, so wordpress does 90 sql queries rather than 15 or 20 to generate each page. This would make a big difference not dependent on the web server and php engine.
So, while nginx+php-fpm are in my opinion faster in any case, of course the real, final performance improvement of your website as a whole may not be the same that i experienced if the bottle-neck is elsewhere (for example in the mysql server, or in the bad coding of a plugin).