Running Apache with a dozen PHP versions

After showing you how to set up multiple PHP versions on a single machine, it's time to explain how to stuff all those compiled php-cgi executables into a single Apache web server instance.

Idea

Installation of FastCGI

Debian

The Debian setup is painless:

$ aptitude install libapache2-mod-fastcgi apache2-mpm-worker apache2-suexec
a2enmod actions fastcgi suexec

CentOS

The open source version of Redhat's operating system does not provide the fastcgi module for Apache, which is why one needs to install it by hand. It's trivial.

Setting up permissions for the fastcgi state files is required: chmod +x /var/log/httpd.

FastCGI setup

After mod_fastcgi is available, we need to prepare the FastCGI servers. Open /etc/{apache2,httpd}/{apache2,httpd}.conf and make it load conf/php-cgisetup.conf before including server.conf. Put the following lines into conf/php-cgisetup.conf:

#php-cgi setup
#used for multiple php versions
FastCgiServer /var/www/cgi-bin/php-cgi-5.2.12
FastCgiServer /var/www/cgi-bin/php-cgi-5.3.0
FastCgiServer /var/www/cgi-bin/php-cgi-5.3.1
ScriptAlias /cgi-bin-php/ /var/www/cgi-bin/

PHP-CGI setup

For each single php version you installed with phpfarm, you need to create a file /var/www/cgi-bin/php-cgi-$version and make it executable. Example for php-cgi-5.3.2:

#!/bin/sh
PHPRC="/etc/php5/cgi/5.3.2/"
export PHPRC
 
PHP_FCGI_CHILDREN=3
export PHP_FCGI_CHILDREN
 
PHP_FCGI_MAX_REQUESTS=5000
export PHP_FCGI_MAX_REQUESTS
 
exec /opt/phpfarm/inst/bin/php-cgi-5.3.2

Activating a PHP version in a virtual host

If you followed all of the previous steps, everything is setup now and ready to be used. In your /etc/{apache2,httpd}/conf/server.conf, put the following code in each <VirtualHost ..> section that you like to switch to a certain version of PHP:

  <Directory "/var/www/FIXME">
    AddHandler php-cgi .php
    Action php-cgi /cgi-bin-php/php-cgi-5.3.2
 
    <FilesMatch "\.php$">
      SetHandler php-cgi
    </FilesMatch>
  </Directory>

Conclusion

With the simple steps listed above and the help of phpfarm, you are able to test your web applications in a dozens or more PHP versions easily.

As as side note: The CGI versions of PHP are only used on the vhosts that you determine. All others are still served by mod_php that was probably setup before, making it trivially easy to keep your server's main web sites up-to date with your distribution's package manager.

FEP

Permission denied: FastCGI: can't create server … bind() failed

In this case, FastCGI is not able to create/access its socket files that are, by default, created in /var/log/apache2/fastcgi/ - because /var/log/apache2 is only root-accessible.

Either move that directory away and re-configure your apache to use the new one, or simply make the directory executable:

chmod +x /var/log/apache2
chmod +x /var/log/apache2/fastcgi

FastCGI: comm with server … aborted: idle timeout

- often in combination with FastCGI: incomplete headers (0 bytes) received from server …

By default, a timeout of 30 seconds is used for the communication between web server and FastCGI instance. This might be a bit short for long-running or complex processes. The documentation shows us how to fix that: -idle-timeout n (30 seconds).

So all we need to do is to edit conf/php-cgisetup.conf and modify the FastCgiServer lines to:

FastCgiServer /var/www/cgi-bin/php-cgi-5.3.1 -idle-timeout 120

Invalid command 'Action'

The full message is

Invalid command 'Action', perhaps misspelled or defined by a module
  not included in the server configuration

If that happens, the action module is not loaded.

$ a2enmod actions

mod_php still handles .php files

If you have both mod_php and PHP via CGI installed, the Apache module sometimes takes precedence over CGI and is used to execute the PHP files - although you specified an AddHandler php-cgi .php directive.

To fix that, SetHandler needs to be added inside the <Directory> section of your vhost:

 
    Action php-cgi /cgi-bin-php/php-cgi-5.3.2
    <FilesMatch "\.php$">
      SetHandler php-cgi
    </FilesMatch>
  </Directory>

FastCGI: failed to connect to (dynamic) server

When you get the error

No such file or directory:
FastCGI: failed to connect to (dynamic) server

then it might be that the CGI configuration is loaded too late.

To fix that, prefix the file name in conf.d with a number, e.g. 001-php-cgisetup.conf. By doing that, you ensure that Apache loads the file at first.

Thanks to Jelle Scholtalbers for the tip.

FastCGI: server php-cgi-5.2.17 restarted (pid 2342)

Sometimes the PHP CGI process restarts itself again and again:

[warn] FastCGI: server "/var/www/cgi-bin/php-cgi-5.2.17" (pid 2342)
 terminated by calling exit with status '0'
[warn] FastCGI: server "/var/www/cgi-bin/php-cgi-5.2.17" restarted (pid 2342)

The reason for this error is that the php-cgi binary is not a FastCGI binary, but either a normal CGI one (without "fast") or a command line version (CLI).

Check it with --version. The correct FastCGI version indicator is cgi-fcgi:

$ php-cgi-5.5.5 --version
PHP 5.5.5 (cgi-fcgi) (built: Oct 24 2013 06:44:46) (DEBUG)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies

Note that on PHP 5.2 and lower, you have to enable the --enable-fastcgi configure flag, by creating a custom config file custom-options-5.2.sh:

#!/bin/sh
configoptions="$configoptions\
 --enable-fastcgi
"

no php-cgi binary found

When phpfarm emits that warning at the end of a compile.sh run, you're not lost: PHP itself automatically disables the CGI compilation if you also enable compiling the Apache module, e.g. via --with-apxs2

You have to do two compilation runs to get both. phpfarm doesn't assist you here; the best is probably to modify config.nice in the PHP version's source folder and run it again (followed by make and make install).

SetEnv has no effect

Unfortunately you cannot use the SetEnv directive to set environment variables from your apache configuration with mod_fastcgi.

Instead, you have to pass the variable definitions as parameters to FastCgiServer:

FastCgiServer /var/www/cgi-bin/php-cgi-5.5 -initial-env MODE=development

Written by Christian Weiske.

Comments? Please send an e-mail.