Ubuntu: nginx+php-cgi on a socket
Moving our PHP application into the cloud, means for us that we are leaving FreeBSD for Linux. Not the best move (IMHO), but I shall elaborate on this in a future blog post.
Once we decided on Ubuntu as the Linux of our choice, I started by moving our development server to an instance on Slicehost. Point taken, Slicehost is not the cloud (as in Amazon EC2, Rackspace, Flexiscale or GoGrid) yet, but Linux on Slicehost and Linux on Amazon EC2 will be alike (or so I hope :-)) and a getting a small slice versus getting a small EC2 instance is an economical decision in the end.
Introduction
The following is the start script for my php-cgi
processes, which I ported from FreeBSD (I previously blogged about it here).
The advantages of this script are:
php-cgi
runs on a unix domain socket — no need for tcp/ip on localhost.- No need for the infamous
spawn-fcgi
script, which never worked for me anyway, and on Ubuntu requires you to installlighttpd
(if you don't happen to be on Karmic Koala). - You can setup different websites with different instances of
php-cgi
. This is great for virtual hosting, especially on a development server where the different workspaces may have different PHP settings and you want to run versions in parallel without sharing settings and therefore maybe affecting each other. - Icing on the cake: we could even add a custom
php.ini
to the start call for each instance (-c
option) to customize it even further.
Start script
The setup is simple, just put the following into a php-fcgid
file in /etc/init.d/
, chmod +x
it and don't forget it to use update-rc.d php-fcgid defaults
in case you want to start the processes when the server boots up:
#!/bin/sh
#
# Author: Till Klampaeckel <[email protected]>
#
# Credits
#
# * original script: http://unix.derkeiler.com/Mailing-Lists/FreeBSD/questions/2007-09/msg00468.html
# * improved: http://till.klampaeckel.de/blog/archives/30-PHP-performance-III-Running-nginx.html
# * all linux start script fu inspired by CouchDB's start script (by Noah Slater)
#
SCRIPT_OK=0
SCRIPT_ERROR=1
DESCRIPTION="php-fcgi super-duper-control thing"
NAME=php-fgcid
SCRIPT_NAME=$(basename $0)
WWW_GROUP=www-data
PHP_CGI=/usr/bin/php-cgi
phpfcgid_users="johndoe jandoe"
phpfcgid_children="2"
phpfcgid_tmpdir="/tmp"
phpfcgid_requests="100"
log_daemon_msg () {
echo [email protected]
}
log_end_msg () {
# Dummy function to be replaced by LSB library.
if test "$1" != "0"; then
echo "Error with $DESCRIPTION: $NAME"
fi
return $1
}
phpfcgid_start() {
echo "Starting $NAME with $phpfcgid_children children (req: $phpfcgid_requests)."
export PHP_FCGI_CHILDREN=$phpfcgid_children
export PHP_FCGI_MAX_REQUESTS=$phpfcgid_requests
for user in ${phpfcgid_users}; do
socketdir="${phpfcgid_tmpdir}/.fastcgi.${user}"
mkdir -p ${socketdir}
chown ${user}:${WWW_GROUP} ${socketdir}
chmod 0750 ${socketdir}
su -m ${user} -c "${PHP_CGI} -b ${socketdir}/socket&"
done
}
phpfcgid_stop() {
echo "Stopping $NAME."
pids=`pgrep php-cgi`
pkill php-cgi
}
phpfcgid_status() {
log_daemon_msg "To be implemented: status"
log_end_msg $SCRIPT_ERROR
}
parse_script_option_list () {
case "$1" in
start)
log_daemon_msg "Starting $DESCRIPTION" $NAME
if phpfcgid_start; then
log_end_msg $SCRIPT_OK
else
log_end_msg $SCRIPT_ERROR
fi
;;
stop)
log_daemon_msg "Stopping $DESCRIPTION" $NAME
if phpfcgid_stop; then
log_end_msg $SCRIPT_OK
else
log_end_msg $SCRIPT_ERROR
fi
;;
restart|force-reload)
log_daemon_msg "Restarting $DESCRIPTION" $NAME
if phpfcgid_stop; then
if phpfcgid_start; then
log_end_msg $SCRIPT_OK
else
log_end_msg $SCRIPT_ERROR
fi
else
log_end_msg $SCRIPT_ERROR
fi
;;
status)
phpfcgid_status
;;
*)
cat << EOF >&2
Usage: $SCRIPT_NAME {start|stop|restart|force-reload|status}
EOF
exit $SCRIPT_ERROR
;;
esac
}
parse_script_option_list [email protected]
General PHP Installation
The required steps in order to get the php installation:
apt-get update
apt-get install php5-cgi
apt-get install nginx
(These steps are working on Ubuntu Jaunty (aka 9.04), but they should work on virtually any other Ubuntu or Debian installation.)
Nginx configuration
This is a simple virtualhost for nginx:
server {
listen 80;
server_name example.org;
access_log /var/log/nginx/example.org-access.log;
error_log off;
location / {
root /var/www/example.org/htdocs;
index index.php index.html index.htm;
}
location ~ .php {
include fastcgi_params;
fastcgi_pass unix:/tmp/.fastcgi.johndoe/socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/example.org/htdocs/$fastcgi_script_name;
}
}
Place the above into /etc/nginx/sites-available
and symlink it from /etc/nginx/sites-enabled
.
One thing to note is that you may have to adjust the line with fastcgi_pass
. Depending on which user the socket belongs to.
Conclusion
There really isn't one. ;-) It just works for me, and I hope it helps someone out there.
I also created a repository on github where I'll keep this script, manage changes and open source my other findings on my journey with Ubuntu.
If you happen to have an addition, please fork and contribute. One of the things for the start script that I'd like to do (aka I have to figure them out) is install it through a package and create a configuration file in /etc/defaults
so I don't have to edit the start script when I add a user or change the parameters passed on to the php-cgi
process.
Trackbacks
The author does not allow comments to this entry
Comments