Nginx+PHP+FastCGI: Testing your web application with bleeding edge PHP

If you enjoyed this article, please leave a comment, rss subscribe to my RSS feed and/or follow me on Twitter. Thank you very much!

So, every once in a while I find myself in need of trying out newer, maybe, not-yet-released features in PHP. For example, recently, I wanted to test RoundCube PHP6 — this is how I did it.

On a side note, the same setup would also work for testing code with previous versions of PHP.

Toolbox

I used nginx and the PHP source with a little bit of ./configure and make — for kicks!

My O.S. of choice is FreeBSD and therefor the installation steps covered are tailored to it. With a small amount of Linux/Unix-fu, anyone should make it work on another distribution regardless.

Install nginx

First off, install nginx. On FreeBSD, this should be all:

  • cd /usr/ports/www/nginx-devel && make install distclean

On other systems, this maybe a:

  • apt-get install nginx
  • emerg nginx
  • rpm -shoot-myself nginx

The next step includes the infamous spawn-fcgi which many people use to control the php-cgi processes. A lot of tutorials on the net suggest to install lighttpd because it's a part of it, but on FreeBSD, you may skip that and do the following instead:

  • cd /usr/ports/www/spawn-cgi && make install distclean

Pretty cool, huh?

So once this is done, the usual tasks need to be completed — in no particular order:

  • edit the nginx config and enable fastcgi in nginx (/usr/local/etc/nginx/nginx.conf)
  • enable nginx itself in /etc/rc.conf (nginx_enable="YES")
  • get another nifty start script (see Shell Script) to wrap spawn-cgi

... and done!

Install PHP

At first I created a directory to host all of this:

  • mkdir /home/user/php-test

Then I added prefix directories, for each PHP installation:

  • mkdir /home/user/php-test/5.3
  • mkdir /home/user/php-test/6

Depending on what I want to test, PHP offers yummy bleeding edge PHP code at snaps.php.net — ready to be consumed.

The installation steps for a recent PHP6 snapshot are as follows (in /home/user/php-test):

  • fetch http://snaps.php.net/php6.0-200907050030.tar.gz
  • tar zxvf php6.0-200907050030.tar.gz
  • cd php6.0-200907050030
  • ./configure --prefix=/home/user/php-test/6 --with-mysql
  • make
  • make install

... and done! ;-)

PHP 5.2.x

In case this is a 5.2.x version, ./configure --help needs to be consulted for --enable-fastcgi etc..

In PHP5.3 and PHP6 the fastcgi options are already assumed.

Make it faster

And just in case the build process is taking to long, I suggest to start with --disable-all and only building what is required (all options are available on ./configure --help).

Nginx, meet PHP, PHP, meet Nginx.

The default fastcgi configuration included in nginx assumes php to run on 127.0.0.1 on port 9000.

It may look like this:

location ~ \.php$ {
    root           html;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  /home/user/public_html$fastcgi_script_name;
    include        fastcgi_params;
}

The same settings are also what the shell script expects.

I called my shellscript php6-test and placed it in /usr/local/etc/rc.d. The only thing I needed to replace in it, is the following line:

PHP_CGI=/usr/local/bin/php-cgi

... with:

PHP_CGI=/home/user/php-test/6/bin/php-cgi

Finish it off with:

  • /usr/local/etc/rc.d/php6-test start
  • /usr/local/etc/rc.d/nginx start

Head over to a phpinfo():

php6-phpinfo

My installations:

dev% ls -lah /home/user/php-test
total 37438
drwxr-xr-x   5 user  user   512B Jul  5 07:18 .
drwx-----x  21 user  user   1.5K Jul  5 07:16 ..
drwxr-xr-x   6 user  user   512B Jul  5 07:38 5.3
drwxr-xr-x   6 user  user   512B Jul  5 07:48 6
drwxr-xr-x  17 user  user   2.0K Jul  5 07:16 php-5.2.10
-rw-r--r--   1 user  user    11M Jun 17 07:43 php-5.2.10.tar.gz
drwxr-xr-x  16 user  user   2.5K Jul  5 07:18 php-5.3.0
-rw-r--r--   1 user  user    13M Jun 29 16:36 php-5.3.0.tar.gz
drwxr-xr-x  15 user  user   2.5K Jul  5 07:16 php6.0-200907050030
-rw-r--r--   1 user  user    13M Jul  4 19:31 php6.0-200907050030.tar.gz

Conclusion

Wasn't so hard now, was it?

This tutorial is more or less scratching the surface. Nginx makes it super easy to configure a different vhosts with different PHP versions. I would not necessarily run the exact same setup in a production environment, but all in all just the port needs to be adjusted for each instance so they don't collide.

This setup made it a lot easier for me to debug PHP. Especially when differences between versions are of concern — I just had to exchange the php-cgi and get busy.

Hope that helps!

| More