After some time with node.js I recently decided to move to nginx + php-fpm + node.js for my future servers. Here we will be installing:
- Nginx as a fast HTTP server with reverse proxy to node.js
- php-fpm for running PHP scripts. The php-fpm (PHP FastCGI sapi) is built into the PHP core but only since 5.3.3, so we need a recent version of PHP.
- node.js for handling comet and high-concurrency/persistent connections.
- Monit is used to restart node.js in case of errors.
For all the packages other than node.js (obviously, since it’s new/actively changing), you can get the most recent version without to patching/compiling anything anymore.
Start by updating your packages and uninstalling httpd if you had it installed:
yum update
yum remove httpd
Add repositories for nginx and PHP-fpm
Just add the EPEL and Remi repos:
rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm
rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-5.rpmInstall nginx and PHP-fpm
yum --enablerepo=remi install php-fpm nginxyum --enablerepo=remi install mysql mysql-server php-mysql php-common php-gd php-mbstring php-mcrypt php-xml php-gd php-bcmathPHPunit and PHPdocumentor:
yum --enablerepo=remi install php-channel-phpunit php-pear-PhpDocumentor php-phpunit-PHPUnitCreate a test application
mkdir /var/www/
In /var/www/index.php:
<?php
phpinfo();Configure nginx
server {
listen 80;
server_name _;
access_log logs/host.access.log main;
root /var/www;
index index.php index.html index.htm;
location ~ .php$ {
# Security: must set cgi.fixpathinfo to 0 in php.ini!
fastcgi_split_path_info ^(.+.php)(/.+)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
include /etc/nginx/fastcgi_params;
}
}Default fastcgi_params
I start the php location by including /etc/nginx/fastcgi_params. This is because I want to use those as defaults, then override them individually afterwards. It is also recommended to have one root directive per server.
PHP path
I use fastcgi_split_path_info which became available in 0.7.31 to pass PATH_INFO.
Security settings
IMPORTANT: Change cgi.fix_pathinfo to 0 in php.ini to prevent a security issue which arises with the default PHP configuration when PHP incorrectly tries to guess which file you want for URLS specifying nonexistent files. Setting cgi.fix_pathinfo=0 causes PHP to only try the literal path given. Alternatively check that the file exists: if (!-f $request_filename) { return 404; }
See also: Nginx pitfalls.
Start/restart and test
service php-fpm start
service nginx restart
Test by going to your server root, it should show you your phpinfo().
Prepare to install node.js
Excellent post: http://wavded.tumblr.com/post/475957278/hosting-nodejs-apps-on-centos-5
Add a user for node.js:
groupadd -r node
useradd -r --shell /bin/bash --comment 'User for running node.js' -g node --home /var/lib/node nodeI prefer using /var/lib/node rather than /home/node because this is more in line with how other server daemon users are defined (e.g. nginx, mysql). -r is for –system, –comment is for –gecos.
Install node.js
yum install gcc-c++ openssl-devel
wget --no-check-certificate https://github.com/ry/node/tarball/v0.3.3
tar -xzvf ry-node-v0.3.3-0-g57544ba.tar.gz
cd ry-node-v0.3.3-0-g57544bac1
./configure
make
make install
mkdir /var/nodeCreate a test application
var sys = require("sys"),
http = require("http");
http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("Hello Worldn");
}).listen(8000);
sys.puts("Server running at 127.0.0.1:8000");Configure nginx for node.js (subdirectory approach)
location /node {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:8000/;
proxy_redirect off;
}Install monit
yum install monit
Create monit script
/etc/monit.d/hello_world content:
check host hello_world with address 127.0.0.1
start program = "/usr/local/bin/node /var/node/hello_world/example.js" as uid node and gid node
stop program = "/usr/bin/pkill -f 'node /var/node/hello_world/example.js'"
if failed port 8000 protocol HTTP
request /
with timeout 10 seconds
then restartStart/restart and test
service monit start
service nginx restart
Test by going to /node on your server.
Also, run ps -Af to verify that node is running with the uid node.
The reboot test
Finally, test everything by restarting your server. A friendly reminder:
chkconfig nginx on
chkconfig monit on
chkconfig php-fpm on
chkconfig mysqld on
chkconfig –list




Great write up, still works on CentOS 6. Thanks!
Agreed, this is a great writeup on a good alternative to the standard apache stack.
If you’re interested in also managing node.js with RPM, check out my post on that here: http://www.chrisabernethy.com/installing-node-js-on-centos-redhat/
Hi, thx for this post, i am trying to do something similar on ubuntu, and he question i have is:
Does your setup works with simple websocket server written in nodejs (with socket io for example).
And 2nd question: what version of nginx do you use?
@ref https://github.com/LearnBoost/socket.io/wiki/Nginx-and-Socket.io
thanks !
Hi… recently i read this, mmm… it’s really faster than previous configuration?