This answer is specifically for Gentoo with Profile 17. It will probably work with a few versions plus and minus. I used Red Hat's PHP Configuration Tips page for inspiration. The same idea should work for other Linux distributions (of course the specific commands will differ).
The solution is to use PHP-FPM (FastCGI Process Manager). Each version of PHP gets its own PHP-FPM service that listens on a socket. Apache passes the PHP execution requests to a particular PHP-FPM service depending on which version of PHP is required.
You can use mod_php for one version of PHP and PHP-FPM for the other(s) but I decided to drop mod_php altogether. First, I read somewhere that you can save some memory overhead by disabling mod_php. Second, the solution seemed a little cleaner with all versions of PHP being handled in the same way. Third, it is always better to have the least amount of/only the necessary software installed from a security perspective.
USE flags for
dev-lang/php to add
fpm and remove
Current Gentoo convention is to create a file like
/etc/portage/package.use/php and specify the
USE flags here. If you specify exact versions in the file, make sure all versions of PHP you want to use pick up the these
Install/reinstall the versions of PHP you are going to be using.
# emerge -av =dev-lang/php-7.2.3
# emerge -av =dev-lang/php-5.6.7
APACHE2_MODULES variable to build the
proxy_fcgi Apache modules.
You specify what Apache modules using by adding/updating the
APACHE2_MODULES variable in
USE flags, Gentoo has some defaults already set-up for your profile. Unlike
USE flags, it seems that you need to explicitly tell Gentoo to start with the defaults by prepending
$APACHE2_MODULES to the variable:
APACHE2_MODULES="$APACHE2_MODULES proxy proxy_fcgi"
- Reinstall Apache.
# emerge -av apache
- Install PHP-FPM.
# emerge -av php-fpm
Create PHP-FPM startup scripts for each version of PHP you are using with Apache.
The PHP-FPM installation creates a single startup script (
/etc/init.d/php-fpm) that allows you to to choose the version of PHP to run using
eselect or by changing the script's file name suffix (e.g.
php-fpm-php7.2, etc.). Since we would only want to use
eselect if we only wanted to use a single version of PHP at a time or if we wanted to use no more than two versions with mod_php for one and PHP-FPM for the second, we will use the suffix method. Instead of copying the script, we want to symlink it (valid suffixes are those directory names from
ls -ld /usr/lib64/php* e.g.
# cd /etc/init.d
# ln -s php-fpm php-fpm-php5.6
# ln -s php-fpm php-fpm-php7.2
Change the PHP-FPM configuration so that each PHP version's service runs on a different port.
The specific file names vary between versions but you want to edit a config file for each PHP version in these general locations:
/etc/php/fpm-php*/*.conf so that the
listen directive has a different port for each.
Configure PHP-FPM services to start.
# rc-update add php-fpm-php5.6 default
# rc-update add php-fpm-php7.2 default
# /etc/init.d/php-fpm-php5.6 start
# /etc/init.d/php-fpm-php7.2 start
Edit the Apache start-up configuration to enable proxy modules.
/etc/conf.d/apache2 to add
-D PROXY and remove
-D PHP from
Edit the Apache configuration to tie specific directory locations to specific instances of PHP-FPM.
There are many ways to handle this depending on your specific Apache configuration. I decided to edit the
<Directory> entry associated with my web root so that the default PHP handler was version 7.2 by adding:
SetHandler "proxy:fcgi://127.0.0.1:9972" # <-- Note port num.
With PHP 5.6 used only by exception, I added
<Directory> directives for each application that needed to use the old version of PHP:
Sethandler "proxy:fcgi:/127.0.0.1:9956" # <-- Note diff port num.
index.php as a valid directory index file.
/etc/apache2/modules.d/70_mod_php.conf includes a directive to add
index.php as a directory index file in the same way
index.html usually is. Since we disabled mod_php in Step 9,
70_mod_php.conf no longer exists to set this up. To fix this, add
DirectoryIndex index.php to the Apache configuration. Otherwise, if you visit paths like
/oldapp/ you will get a 403 error.
# /etc/init.d/apache restart
- If you set-up specific configuration settings in your
php.ini file (e.g. max POST values, timezone, etc), you will need to set these in all of your
/etc/php/fpm-php*/php.ini files (for each version).
- PHP-FPM defaults to running as
group=nobody. You may need to change these (in
/etc/php/fpm-php*/php-fpm.conf) to match whatever your web server is running.
- To handle multiple virtual hosts, perform Steps 10 and 11 for each.