Easy PHP version switching on Ubuntu (allows for running multiple versions at the same time)

This article assumes you're using PHP FPM, we'll also show you how to switch PHP versions on the command line at the bottom as well.

You'll need to install the different PHP versions and make sure modules and config matches up.

If you already have php7.4 installed and you're looking to install 8.3 you could add 8.3 in while leaving 7.4 by installing it by version number with your OS package manager, e.g. with apt on Ubuntu:

sudo apt install php8.3-{cli,fpm}  

However, before installing the new version, you'll need to make sure your PHP pools don't reference a central/single sock file as installing the new fpm may auto switch it to the new version. E.g.

sudo vim /etc/php/7.4/fpm/pool.d/www.conf  

Check if it references /var/run/php/php-fpm.sock and update it to the version it's on like /var/run/php/php7.4-fpm.sock.

You'll then also need to make this update in your nginx or apache file and reload php-fpm first, then nginx or apache.

Once you've installed your new PHP versions, check both php fpm versions are running with:

systemctl status php7.4-fpm  
systemctl status php8.3-fpm  

To help compare config files you could use a tool like meld, vimdiff or diff, e.g.:

sudo meld /etc/php/7.4/cli/php.ini /etc/php/8.3/cli/php.ini  

Make sure to compare both the cli and fpm config files.

Also to help compare PHP modules you can use meld, vimdiff or diff again like so:

meld <(php7.4 -m) <(php8.3 -m)  

Then install missing ones, for example if you spot gd, gmp, intl, xml, curl and bcmath missing you could install them with:

sudo apt install php8.3-{gd,gmp,intl,xml,curl,bcmath}  

Then compare the modules again.

Using PHP FPM you can switch PHP version easily by switching which /var/run/php/php7.4-fpm.sock (this may also be /run/php/php7.4-fpm.sock) you reference in either the Apache or Nginx config (or whichever system you use to host.

E.g. in Nginx it's this line:

fastcgi_pass unix:/var/run/php7.4-fpm.sock  

Or Apache:

SetHandler "proxy:unix:/run/php/php7.4-fpm.sock|fcgi://localhost"  

Your line here may be a little different, the above assumes it's the default version number based sock files but there are alternatives.

Here's 3 additional examples you may find:

  • A single /var/run/php-fpm.sock instead of specific version. If that's the case, it will likely be that your php fpm pool for that version points to that single sock file. Your pool will be configured by a file in /etc/php/VERSION/fpm/pool.d/ e.g. /etc/php/7.4/fpm/pool.d/www.conf

    You can either, leave the current one pointing here and make sure your new PHP version has the specific version number in the sock file name and update the reference to it in the nginx/apache config. Or, you could swap which php version uses that sock file by editing the current one to have the version in the file name and the new one to this main sock file. Then restart both versions of PHP FPM.

  • Multiple pools, one per site. If you have multiple sites on the server you may have created a php pool for each of them to isolate them. If so, you'll need to copy over these configs to the new version (or at least the ones you want on the new version, maybe test with one first) so if it was /etc/php/7.4/fpm/pool.d/site.com.conf and you're switching to php8.3 then copy to /etc/php/8.3/fpm/pool.d/site.com.conf

    SetHandler "proxy:unix:/run/php/php7.4-fpm-site.com.sock|fcgi://localhost" and update the version number in the sock file if it had one, or add one in so it doesn't clash with the other.

  • Listing to a port instead of a sock file. listen = 127.0.0.1:7401 In this example you have ports instead of files but they can be updated mostly the same as the sock files. You'll just need to remember or note down which ports relate to which versions & update your nginx/apache configs as needed.

Remember to reload nginx/apache after editing the configs and if you updated your php-fpm configs or pools, reload php-fpm for the versions you updated.

Then for the CLI you can switch with:

sudo update-alternatives --set php /usr/bin/php8.3  

To make this easier, I added a bash function so I can call php-version 7.4 or php-version 8.3 to switch between them, and call php-version to have it list the php-versions I have available:

# switch php version for CLI
function php-version {  
    if [[ "$1" == "" ]]; then
        echo "Available versions:"
        currentVersion=$(php -v | grep -oP '(?<=PHP )\d+.\d+')
        availableVersions=$(ls /usr/bin/php* | grep -oP '(?<=/php)(\d+\.\d+)')
        echo $availableVersions | sed "s/$currentVersion/$currentVersion *current/"
        echo "Set default for cli with: php-version $currentVersion"
    else
        echo "Setting default php cli version to $1"
        sudo update-alternatives --set php /usr/bin/php$1
        echo "php -v:"
        php -v
    fi
}

Side note, you can also use sudo update-alternatives --config php to have it interactively show you php versions available and switch that way.

You may also want to switch the php version phar files use as well, you can do this with by running both the following commands:

sudo update-alternatives --set phar /usr/bin/phar8.3  
sudo update-alternatives --set phar.phar /usr/bin/phar.phar8.3