9/12/2022

Running PHP 7.x and 8.x in parallel - in Apache and CLI

 Running two versions of PHP on one machine - why would anyone want to do that? For me, the reason is that FreePBX still (!) only supports PHP 7.4, even though it will cease to receive security updates by the end of November.

You may have a different reason.

In any case, you want to run a web site on PHP 7 after November and it is internet-facing, I strongly recommend you stop right now.

Fortunately for me, the parts of FreePBX that require PHP (7) are only used on the internal network, so it is less of a risk. An no, it still is not "no risk" ...

So here is how I did it, and it works fine.

  • I have both packagaes, PHP 8.1 and PHP 7.4 installed.
  • I am running the Apache PHP 8.1 module, meaning that by default, web sites are running on 8.1
  • the FreePBX web site is running on php7.4-fpm, using Fast CGI
  • the account that is running Asterisk has a link to the PHP 7.4 binary, and it comes first in its path
  • the asterisk cron job has the same link in its path

Not too  complicated, right? Well, there were a few stumbling blocks, so I will describe the process in more detail.

After installing PHP 8,1 and 7.4, make sure that your default is to use 8.1:

a2dismod php.74
a2enmod php8.1
systemctl restart apache2

Install php7.4-fpm:

apt-get install php7.4-fpm libapache2-mod-php7.4 libapache2-mod-fcgid

At the end of the installation, it will ask you to enable the modules proxy_fcgi and setenvif as well as the configuration php7.4-fpm. Do not do that!

Instead, you will later adapt the virtual host configuration file of the site that you want to run under 7.4. This way, the 7.4 fpm will not be loaded for every site, you want to stick with 8.1 for these.

As my FreePBX site needs to run under a different account and requires a few extra PHP settings, I created a separate pool for it.

cp /etc/php/7.4/fpm/pool.d/www.conf /etc/php/7.4/fpm/pool.d/freepbx.conf

Edit the new file and adapt to your needs. The comments in the file a quite good. Make suire to change the name of the socket location in the listen setting. I used /run/php/freepbx.sock

Add the following line to your vhost config:

SetHandler "proxy:unix:/run/php/freepbx.sock|fcgi://localhost

Now load the new pool:

systemctl restart php7.4-fpm.service

Adapt the virtual host configuration file of the site that you want to run under 7.4 by adding these lines:

# instead of a2enmod proxy_fcgi setenvif
<IfModule !mod_setenvif.c>
  LoadModule setenvif_module /usr/lib/apache2/modules/mod_setenvif.so
</IfModule>
<IfModule !mod_proxy.c>
  LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
</IfModule>
<IfModule !mod_proxy_fcgi.c>
  LoadModule proxy_fcgi_module /usr/lib/apache2/modules/mod_proxy_fcgi.so
</IfModule>

# instead of a2enconf php8.1-fpm
Include conf-available/php7.4-fpm.conf
# then override with the appropriate pool
<FilesMatch ".+\.ph(ar|p|tml)$">
    SetHandler "proxy:unix:/run/php/freepbx.sock|fcgi://localhost"
</FilesMatch>

If, in the installation process you ever run apt autoremove, you may be missing a few important PHP 7.4 modules, as they become obsolete by installing 8.1. I guess that is what apt thinks, anyway. If this is the case, you need to install them again. For FreePBX these were php7.4-mysql,  php7.4-xml, and php7.4-mbstring.

Finally, if your web site contains .htaccess files, be advised that FPM does not support them! It reads them and rejects everything, as you may see in the error log of the web site.  You need to move everything to the vhost config and rename the .htaccess file to get rid of the errors in the log.

The web site should now be up and running, let us move on to CLI and cron:

I needed to run fwconsole, a part of FreePBX that also relies on PHP 7.4. I could have changed the path in the Shebang directive, but future updates may override that.

Instead, create a link in the user's bin directory (create if it does not exist)

ln -si /usr/bin/php7.4 ~user/bin/php

Add the following to the user's .profile script:

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
    PATH="$HOME/.local/bin:$PATH"
fi

Now any shell you run under the user's account will use PHP 7.4.

Last step: adapt crontab. Just prepend ~user/bin to the PATH directive.

This is it. A bit more complicated than anticipated but still manageable, don't you think?

Still, I hate the fact that there are products out there that still rely on soon-to-be-outdated versions of PHP.

No comments:

adaxas Web Directory