Jul 06

In this tutorial i will try to install php-fpm with nginx on centos 5.3. But first:

What is PHP-FPM ?

PHP-FPM is a patch for PHP4/5 to greatly improve PHP’s FastCGI SAPI capabilities and administration. This means that you don’t install php through your distribution’s package manager, but rather download the package from the PHP-website, and the patch from another site. You patch up the sourcecode, compile things, and get it started.

The following is a comparison chart of problems and how php-fpm handles them, when enabled with the FastCGI SAPI:

Description php “out of the box” spawn-fcgi + spawn-php.sh + daemontools php-fpm
php daemonization: pid file, log file, setsid(), setuid(), setgid(), chroot() (-) (+) (+)
Process Management. Ability to “graceful” stop and start php workers without losing any queries. The possibility of gradually update the configuration and binary without losing any queries. php4 (-), php5 (only graceful completion) (-) (+)
Restricting ip addresses from which requests can come from a web server php4 (-), php5 (+) (from 5.2.2) (-) (+)
Dynamic number of processes, depending on the load (-) (-) TODO
Starting the workers with different uid/gid/chroot/environment and different php.ini option. You do not need a safe mode! (-) (-) (+)
Logging stdout & stderr business processes (-) (-) (+)
Emergency restart all the processes in the event of accidental destruction of shared memory opcode cache, if used accelerator (-) (-) (+)
Forcing the completion of process if set_time_limit() fails (-) (-) (+)

Compare to spawn- fastcgi installation , php-fpm installation is much slower and you can refer to http://www.cyberciti.biz/faq/rhel-fedora-install-configure-nginx-php5/ for spawn-fcgi installation. Okay let’s start the installation.

Installation

1. Install some dependecies first
# yum install gcc libjpeg-devel libpng-devel libmcrypt libmcrypt-devel pcre pcre-devel

2. We need to get PHP-sourcecode and php-fpm patch, in this tutorial i use php-5.2.10 and php-5.2.10-fpm-0.5.13
# wget http://id.php.net/get/php-5.2.10.tar.bz2/from/us.php.net/mirror
wget http://php-fpm.org/downloads/php-5.2.10-fpm-0.5.13.diff.gz

3. Extract and run the patch
# tar xvf php-5.2.10.tar.bz2
# gzip -cd php-5.2.10-fpm-0.5.13.diff.gz | patch -d php-5.2.10 -p1

4. Configure and compile cd php-5.2.10 and hp-5.2.10-fpm-0.5.13 patch
# ./configure --enable-fastcgi --enable-fpm --with-mcrypt --enable-mbstring --enable-mysql --with-mysql=/usr/include/mysql --with-mysql-sock=/tmp/mysql.sock --with-curl --with-sockets --with-gd --with-zlib --with-iconv --with-dom --with-jpeg-dir=/usr/lib
make
make install

You should see this on the end of installation


Installing PHP SAPI module: cgi
Installing PHP CGI binary: /usr/local/bin/
Installing FPM config: /usr/local/etc/php-fpm.conf
(installing as php-fpm.conf.default)
Installing init.d script: /usr/local/sbin/php-fpm
Installing PHP CLI binary: /usr/local/bin/
Installing PHP CLI man page: /usr/local/man/man1/
Installing build environment: /usr/local/lib/php/build/
Installing header files: /usr/local/include/php/
^[[BInstalling helper programs: /usr/local/bin/
program: phpize
program: php-config
Installing man pages: /usr/local/man/man1/
page: phpize.1
page: php-config.1
Installing PEAR environment: /usr/local/lib/php/
pear/pear dependency package "pear/Archive_Tar" installed version 1.3.3 is not the recommended version
1.3.2, but may be compatible, use --force to install
pear/Archive_Tar cannot be installed, conflicts with installed packages
[PEAR] Archive_Tar - upgraded: 1.3.3
[PEAR] Console_Getopt - already installed: 1.2.3
[PEAR] Structures_Graph- already installed: 1.0.2
[PEAR] XML_Util - installed: 1.2.1
[PEAR] PEAR - upgraded: 1.8.0
Wrote PEAR system config file at: /usr/local/etc/pear.conf
You may want to add: /usr/local/lib/php to your php.ini include_path
Installing PDO headers: /usr/local/include/php/ext/pdo/

5. Installing Init Script for PHP-FPM
# cd /etc/init.d/
# ln -s /usr/local/sbin/php-fpm php-fpm

add this to /etc/rc.local if you want php-fpm to start from booting
# vi /etc/rc.local
/etc/init.d/php-fpm start

6. Installing and configure nginx, when i write this tutorial the latest stable versions are nginx-0.7.61 you can go to http://nginx.net/ for latest nginx sourcode
wget http://sysoev.ru/nginx/nginx-0.7.61.tar.gz
tar xvf http://sysoev.ru/nginx/nginx-0.7.61.tar.gz
cd nginx-0.7.61
./configure --pid-path=/usr/local/nginx/logs/nginx.pid --sbin-path=/usr/local/sbin/nginx --with-md5=/usr/lib --with-sha1=/usr/lib --with-http_ssl_module --with-http_dav_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module
# make
# make install

7. Installing Nginx Daemon for CentOS, you can copy paste this script to your /etc/init.d/nginx

#! /bin/sh
### BEGIN INIT INFO
# Provides: skeleton
# Required-Start: $local_fs $remote_fs
# Required-Stop: $local_fs $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: S 0 1 6
# Short-Description: Example initscript
# Description: This file should be used to construct scripts to be
# placed in /etc/init.d.
### END INIT INFO
#
# Author: Ryan Norbauer
#
set -e
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DESC="nginx daemon"
NAME=nginx
DAEMON=/usr/local/sbin/$NAME
PIDFILE=/usr/local/nginx/logs/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
# Gracefully exit if the package has been removed.
test -x $DAEMON || exit 0
# Read config file if it is present.
#if [ -r /etc/default/$NAME ]
#then
# . /etc/default/$NAME
#fi
#
# Function that starts the daemon/service.
#
d_start() {
start-stop-daemon --start --quiet --pidfile $PIDFILE \
--exec $DAEMON \
|| echo -n " already running"
}
#
# Function that stops the daemon/service.
#
d_stop() {
start-stop-daemon --stop --quiet --pidfile $PIDFILE \
--name $NAME \
|| echo -n " not running"
}

#
# Function that sends a SIGHUP to the daemon/service.
#
d_reload() {
start-stop-daemon --stop --quiet --pidfile $PIDFILE \
--name $NAME --signal 1
}

case "$1" in
start)
echo -n "Starting $DESC: $NAME"
d_start
echo "."
;;
stop)
echo -n "Stopping $DESC: $NAME"
d_stop
echo "."
;;
#reload)
#
# If the daemon can reload its configuration without
# restarting (for example, when it is sent a SIGHUP),
# then implement that here.
#
# If the daemon responds to changes in its config file
# directly anyway, make this an "exit 0".
#
# echo -n "Reloading $DESC configuration..."
# d_reload
# echo "done."
#;;
restart|force-reload)
#
# If the "reload" option is implemented, move the "force-reload"
# option to the "reload" entry above. If not, "force-reload" is
# just the same as "restart".
#
echo -n "Restarting $DESC: $NAME"
d_stop
# One second might not be time enough for a daemon to stop,
# if this happens, d_start will fail (and dpkg will break if
# the package is being upgraded). Change the timeout if needed
# be, or change d_stop to have start-stop-daemon use --retry.
# Notice that using --retry slows down the shutdown process somewhat.
sleep 1
d_start
echo "."
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
exit 3
;;
esac
exit 0

Or you can download it from http://www.magnet-id.com/download/nginx/nginx-daemon
wget http://www.magnet-id.com/download/nginx/nginx-daemon -O /etc/init.d/nginx
and don’t forget to set the permission
# chmod 750 /etc/init.d/nginx

Install start-stop-daemonvand add nginx on the start up

wget http://www.magnet-id.com/download/nginx/apps-sys-utils-start-stop-daemon-IR1_9_18-1.tar.gz
tar zxvf apps-sys-utils-start-stop-daemon-IR1_9_18-1.tar.gz
cd apps/sys-utils/start-stop-daemon-IR1_9_18-1/
gcc start-stop-daemon.c -o start-stop-daemon
cp start-stop-daemon /usr/sbin
chkconfig --add nginx
chkconfig --level 345 nginx on

Nginx.conf configuration

go to nginx configuration file: “/usr/local/nginx/conf/nginx.conf” , and add the php configuration

location ~ \.php$ {
root /usr/share/nginx/html; # itmena the root of the coument are located on /usr/share/nginx/html
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}

Go to /usr/share/nginx/html and create php files
# vi index.php
<? phpinfo(); ?>

8. Start the nginx and php-fpm
# service php-fpm start
# service nginx start
9. You should go to your domain or server address and see the phpinfo

php-fpm1

php-fpm2

php-fpm3

Jul 02

Recently i am working with nginx and apache on wpmu. I am trying to test and bencmark both web server. Yes i have browse and heard that nginx is more fastest than apache but i also having difficulties with the nginx mod rewrite setting to wpmu supercache on the other side there were no problem with apache mod rewrite but i have a lot memory and resource when i use apache. Okay then when i stumble on this article http://tech.nocr.at/tech/how-to-speed-up-wordpress-with-nginx-and-wp-super-cache/ it will be a great idea if i can apply the article on the wpmu, i already have wpmu , wp supercache , nginx and apache. The main idea with that article is to split the static and dynamic content process, nginx will process the static content and the apache will process the dynamic content.

System requirement:

– Centos 5.3

– Apache ( httpd-2.2.8 )

– Nginx (nginx-0.6.36-1.el5)

– wp super cache plugin Version: 0.9.4.3

Okay let’s start the changes

1.  I assume you have installed apache and wpmu first of all we need to changes the apache(httpd) port firstwe can changes it on the httpd.conf at /etc/httpd/conf/httpd.conf

# vi /etc/httpd/conf/httpd.conf
Listen 80
Listen 8080

2. Next we are going to turn KeepAlives off on Apache since Nginx will be dealing with all of the actual browser connections. This will ensure that all of the child processes in Apache die quickly and don’t hang around chewing up memory. Find the KeepAlive entry in your /etc/httpd/conf/httpd.conf file and set it to off

# vi /etc/httpd/conf/httpd.conf
KeepAlive Off

3. You need to changes your virtual directory to match the nginx config. Here is my config

# vi /etc/httpd/conf/httpd.conf

NameVirtualHost localhost:8080
ServerName *.blog.myblog.org
< VirtualHost localhost:8080>
DocumentRoot /blog.myblog.org/public_html/
< Directory "/blog.myblog.org/public_html" >
AllowOverride All
Options All
Order allow,deny
Allow from all
< / Directory>
ErrorLog logs/blog.myblog.org-error_log
CustomLog logs/blog.myblog.org-access_log combined
< / VirtualHost>
< VirtualHost localhost:8080 >
ServerName myotherweb.com
DocumentRoot /myotherweb.com/public_html/
< Directory "/myotherweb.com/public_html" >
AllowOverride All
Options All
Order allow,deny
Allow from all
< / Directory >
ErrorLog logs/myotherweb.com-error_log
CustomLog logs/myotherweb.com-access_log common
< / VirtualHost>

5. You neew to reload your httpd service
# /etc/init.d/httpd reload

6.  Okay we will set the nginx , if you did not have nginx yet on centos you can insstall it from EPEL repository you can refer to here http://www.cyberciti.biz/faq/rhel-fedora-install-configure-nginx-php5/

Okay we will set the nginx.conf on /etc/nginx/nginx.conf
# vi /etc/nginx/nginx.conf

#user nginx;
user apache;
worker_processes 10;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] $request '
'"$status" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
gzip on;
server {
listen 80;
server_name blog.myblog.org *.blog.myblog.org;
# Main location
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
location ~ wp-login.php$ {
root /blog.myblog.org/public_html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index wp-login.php;
fastcgi_param SCRIPT_FILENAME /blog.myblog.org/public_html$fastcgi_script_name;
include fastcgi_params;
}
# Static files location
location ~*^.+^.+^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ {
root /blog.myblog.org/public_html;
# if the requested file exists, return it immediately
if (-f $request_filename) {
break;
}
set $supercache_file '';
set $supercache_uri $request_uri;
if ($request_method = POST) {
set $supercache_uri '';
}
# Using pretty permalinks, so bypass the cache for any query string
if ($query_string) {
set $supercache_uri '';
}
if ($http_cookie ~* "comment_author_|wordpress|wp-postpass_" ) {
set $supercache_uri '';
}
# if we haven't bypassed the cache, specify our supercache file
if ($supercache_uri ~ ^(.+)$) {
set $supercache_file /wp-content/cache/supercache/$http_host/$1index.html;
}
# only rewrite to the supercache file if it actually exists
if (-f $document_root$supercache_file) {
rewrite ^(.*)$ $supercache_file break;
}
# all other requests go to WordPress
if (!-e $request_filename) {
rewrite . /index.php last;
}
}
# Static files location
location ~*^.+^.+^.+ (jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ {
root /myotherweb.com/public_html;
}

}
}

you can remove the wp-login.php because i set my wp-login.php to be process with the nginx php_cgi ( i use ldap and ldap session will refer to blog.myblog.org:8080 and i need blog.myblog.org port 80 )

location ~ wp-login.php$ {
root /blog.myblog.org/public_html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index wp-login.php;
fastcgi_param SCRIPT_FILENAME /blog.myblog.org/public_html$fastcgi_script_name;
include fastcgi_params;
}

7. And the final steps is to start your nginx
# /etc/init.d/nginx start
and in my case since i process the wp-login.php on nginx i need to turm on the spawn-fcgi /php_cgi
# /etc/init.d/php_cgi start

8. And that’s it you can start test your sites http://blog.myblog.org