This quick guide explains the steps needed to be able to run different versions of PHP on the same server (different virtual hosts or even different folders within the same site).
Updated after the release of PHP 8.3 in November 2023 (8.3 is now the version installed from Ondrej’s repository)
Prepare
If the ‘add-apt-repository’ command is missing, you need to install the package “software-properties-common” first:
apt install -y software-properties-common
Add the ondrej/php repository to your system:
add-apt-repository ppa:ondrej/php
apt update, upgrade:
apt update apt upgrade apt autoremove
Note: after these steps you will have both PHP 8.1 and 8.3 installed, and most likely PHP 8.1 active for Apache. When you follow the hint on removing packages no longer needed (php 8.1 packages), PHP 8.1 Apache will also stop working. This will be remedied in the section below, or by changing Apache to use PHP 8.3 instead:
a2enmod php8.3
Install Apache fastCGI module:
apt install -y libapache2-mod-fcgid
For each version of PHP
As of 1 Jan 2024, PHP versions 8.2 (php8.2) and 8.3 (php8.3) are those with active support and updates. PHP version 8.1 (php8.1) will continue to receive critical updates until 25 Nov 2024. See Supported PHP Versions.
Install required packages
apt install -y php8.2 php8.2-fpm php8.2-cgi php8.2-mysql libapache2-mod-php8.2
Install other wanted modules for the same PHP version, for example these commonly used:
apt install -y php8.2-curl php8.2-gd php8.2-imagick php8.2-intl php8.2-mbstring php8.2-readline apt install -y php8.2-soap php8.2-xml php8.2-xmlrpc php8.2-zip
Start the php-fpm service:
systemctl start php8.2-fpm
Check that the service is running:
systemctl status php8.2-fpm
For each version, also any custom configuration in php.ini has to be duplicated. In Ubuntu the php.ini files are located in the subfolders of /etc/php/x.x/ (one subfolder for each run environment, “apache2”, “cgi”, “cli”, “fpm”).
With the understanding of the above, here are the needed commands for installing the required and extra packages for PHP 7.4, 8.0, 8.1, 8.2 and 8.3:
# # 7.4 # apt install -y php7.4 php7.4-fpm php7.4-cgi php7.4-mysql libapache2-mod-php7.4 apt install -y php7.4-curl php7.4-gd php7.4-imagick php7.4-intl php7.4-mbstring php7.4-readline php7.4-json apt install -y php7.4-soap php7.4-xml php7.4-xmlrpc php7.4-zip # # 8.0 # apt install -y php8.0 php8.0-fpm php8.0-cgi php8.0-mysql libapache2-mod-php8.0 apt install -y php8.0-curl php8.0-gd php8.0-imagick php8.0-intl php8.0-mbstring php8.0-readline apt install -y php8.0-soap php8.0-xml php8.0-xmlrpc php8.0-zip # # 8.1 # apt install -y php8.1 php8.1-fpm php8.1-cgi php8.1-mysql libapache2-mod-php8.1 apt install -y php8.1-curl php8.1-gd php8.1-imagick php8.1-intl php8.1-mbstring php8.1-readline apt install -y php8.1-soap php8.1-xml php8.1-xmlrpc php8.1-zip # # 8.2 # apt install -y php8.2 php8.2-fpm php8.2-cgi php8.2-mysql libapache2-mod-php8.2 apt install -y php8.2-curl php8.2-gd php8.2-imagick php8.2-intl php8.2-mbstring php8.2-readline apt install -y php8.2-soap php8.2-xml php8.2-xmlrpc php8.2-zip # # 8.3 # apt install -y php8.3 php8.3-fpm php8.3-cgi php8.3-mysql libapache2-mod-php8.3 apt install -y php8.3-curl php8.3-gd php8.3-imagick php8.3-intl php8.3-mbstring php8.3-readline apt install -y php8.3-soap php8.3-xml php8.3-xmlrpc php8.3-zip
Install only the versions you need/want. My suggestion is to (re)install whatever version that is current for the OS release you are running (as for this time Ubuntu 22.04 LTS = php 8.1), the version by default installed when updating with Ondrej’s repository (for now 8.2), the current release of PHP (8.3) and if really necessary the last ‘legacy’ version (7.4).
Set new default PHP version used by Apache
To set the default PHP version to use when not overridden by SetHandler below, use the commands a2dismod and a2enmod.
Set default to PHP 8.3
a2dismod php8.1 a2enmod php8.3 systemctl restart apache2
Set default to PHP 7.4
a2dismod php8.3 a2enmod php7.4 systemctl restart apache2
Configuring PHP version for virtual host or subfolder
Activate necessary Apache modules and restart Apache:
a2enmod actions fcgid alias proxy_fcgi systemctl restart apache2
Use FilesMatch directive to set the PHP version:
FilesMatch is valid in both the virtualhost configuration and inside a Directory section.
To set PHP version globally for a virtual host, use it outside a Directory section.
<FilesMatch \.php$> SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost" </FilesMatch>
The default PHP version can be set using ‘a2enmod php8.2’ (or any other version)
Check the configuration for errors:
apachectl configtest
If result is “Syntax OK”, restart Apache:
systemctl restart apache2
Overriding PHP version using .htaccess
For this to work, “AllowOverride FileInfo” must be present for the directory (or above) in which the .htaccess file will be used to set the PHP version.
For the default virtual host, the DocumentRoot is set to /var/www/html, so to allow PHP version to be set by .htaccess at that level or below, the following must be present in the vhost configuration:
<Directory /var/www/html> AllowOverride FileInfo </Directory>
When this has been set, FilesMatch and SetHandler (as described above) can be used within the .htaccess file. The .htaccess method have higher priority than what is set for the virtualhost, or the subfolder within the DocumentRoot of the virtual host.
Testing
Create a file named ‘i.php’ in the locations with the different PHP versions (can be different virtualhosts or folders)
<?php phpversion(); ?>
Access these locations on the virtualhosts or their directory locations to verify that they are using different PHP versions.
See also Securing Apache HTTPd and PHP sites by running under user accounts
References
Most useful resource for this guide
How To Run Multiple PHP Versions on One Server Using Apache and PHP-FPM on Ubuntu 18.04 (DigitalOcean Community)