Nginx, php-fpm and node.js install on Centos 5.5
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:bash
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.rpm
Install nginx and PHP-fpm
Remi has the php-fpm package (php 5.3.4); EPEL has nginx:
yum --enablerepo=remi install php-fpm nginx
Some other common packages:
yum --enablerepo=remi install mysql mysql-server php-mysql php-common php-gd php-mbstring php-mcrypt php-xml php-gd php-bcmath
PHPunit and PHPdocumentor:
yum --enablerepo=remi install php-channel-phpunit php-pear-PhpDocumentor php-phpunit-PHPUnit
Create a test application
mkdir /var/www/
In /var/www/index.php:
<?php
phpinfo();
Configure nginx
In /etc/nginx/nginx.conf:
server {
listen 80;
servername ;
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:bash
groupadd -r node
useradd -r --shell /bin/bash --comment 'User for running node.js' -g node --home /var/lib/node node
I 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/node
Create a test application
For node.js apps, I prefer to keep the www and node trees separate. Also note that I am running unstable 0.3.3 not 0.2.x, so the example is slightly different. Create the example file /var/node/hello_world/example.js:
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)
In /etc/nginx/nginx.conf (after the server definition has started):bash
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:bash
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 restart
Start/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
Comments
Andy: Great write up, still works on CentOS 6. Thanks!
Chris Abernethy: 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/
dim: 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 !
nico: Hi... recently i read this, mmm... it's really faster than previous configuration?