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
- Instead of using mod_php, mod_fastcgi is going to be utilized.
- Every single PHP version runs its own CGI server
- Configuration of used PHP version is made per virtual host.
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