Install Multiple PHP Versions with Apache or NGINX on Ubuntu

Bonjour,

Before following this tutorial, you need a root account on Ubuntu 22.04 OS running on your remote server. If you need a virtual private server (VPS) / a virtual computer with 1 IP public that is online --and can serve– 24/7/365.


I recommend HostHatch which has excellent features like:

  • KVM based with AMD EPYC Milan CPU
  • DDR4 RAM servers
  • NVMe storage
  • Generous monthly bandwidth
  • Multiple data centers worldwide, including Amsterdam, Stockholm, United States (Los Angeles, Chicago, New York, Vienna, Oslo, London, Zurich, Warsaw, Madrid, Milan, Hongkong, Singapore, Tokyo, and Sydney.
  • Starts from $4/Month

In this tutorial, I'm going to Install Multiple PHP Versions on Ubuntu with a PPA repository called Ondrej.

Who is Ondřej Surý? get closer about him on his site https://deb.sury.org/

What PHP versions am I want to install? Nowadays (in early 2023), the stable version of PHP is PHP8.x, but some applications still can run on PHP 7.4.

🦉
I'm going to install multiple PHP versions: PHP7.4 together with PHP8.0, PHP8.1 and PHP8.2 in a Ubuntu VPS

Step 1: Add Repository ppa:ondrej/php

Install software-properties-common with

sudo apt install software-properties-common

And then add an apt repository Ondrej

sudo add-apt-repository ppa:ondrej/php -y

Output:

sudo add-apt-repository ppa:ondrej/php -y

PPA publishes dbgsym, you may need to include 'main/debug' component
Repository: 'deb https://ppa.launchpadcontent.net/ondrej/php/ubuntu/ jammy main'
Description:
Co-installable PHP versions: PHP 5.6, PHP 7.x, PHP 8.x and most requested extensions are included. Only Supported Versions of PHP (http://php.net/supported-versions.php) for Supported Ubuntu Releases (https://wiki.ubuntu.com/Releases) are provided. Don't ask for end-of-life PHP versions or Ubuntu release, they won't be provided.

Debian oldstable and stable packages are provided as well: https://deb.sury.org/#debian-dpa

You can get more information about the packages at https://deb.sury.org

IMPORTANT: The <foo>-backports is now required on older Ubuntu releases.

BUGS&FEATURES: This PPA now has a issue tracker:
https://deb.sury.org/#bug-reporting

CAVEATS:
1. If you are using php-gearman, you need to add ppa:ondrej/pkg-gearman
2. If you are using apache2, you are advised to add ppa:ondrej/apache2
3. If you are using nginx, you are advised to add ppa:ondrej/nginx-mainline
   or ppa:ondrej/nginx

PLEASE READ: If you like my work and want to give me a little motivation, please consider donating regularly: https://donate.sury.org/

WARNING: add-apt-repository is broken with non-UTF-8 locales, see
https://github.com/oerdnj/deb.sury.org/issues/56 for workaround:

# LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php
More info: https://launchpad.net/~ondrej/+archive/ubuntu/php
Adding repository.
Adding deb entry to /etc/apt/sources.list.d/ondrej-ubuntu-php-jammy.list
Adding disabled deb-src entry to /etc/apt/sources.list.d/ondrej-ubuntu-php-jammy.list
Adding key to /etc/apt/trusted.gpg.d/ondrej-ubuntu-php.gpg with fingerprint 14AA40EC0831756756D7F66C4F4EA0AAE5267A6C
Hit:1 http://archive.ubuntu.com/ubuntu jammy InRelease
Get:2 http://security.ubuntu.com/ubuntu jammy-security InRelease [110 kB]
Get:3 http://archive.ubuntu.com/ubuntu jammy-updates InRelease [119 kB]
Hit:4 http://nginx.org/packages/ubuntu jammy InRelease
Get:5 http://archive.ubuntu.com/ubuntu jammy-backports InRelease [107 kB]
Get:6 https://ppa.launchpadcontent.net/ondrej/php/ubuntu jammy InRelease [23.9 kB]
Get:7 https://ppa.launchpadcontent.net/ondrej/php/ubuntu jammy/main amd64 Packages [110 kB]
Get:8 https://ppa.launchpadcontent.net/ondrej/php/ubuntu jammy/main Translation-en [34.2 kB]
Fetched 510 kB in 3s (189 kB/s)
Reading package lists... Done

and update the Ubuntu system package with the following command:

sudo apt update

After the update is completed, you can proceed:

Step 2: Install PHP

You may choose what PHP versions you like to install.

Install PHP 7.4

Install PHP7.4 version with run the following command:

sudo apt install php7.4-{fpm,mysql,common,cli,json,opcache,readline,mbstring,xml,gd,curl,zip}
💡
This command will install php7.4-fpm and php7.4 popular extensions to ensure that your CMS runs correctly and smoothly.

Install PHP 8.0

Install the PHP8.0 version with run the following command:

sudo apt install php8.0-{fpm,mysql,common,cli,opcache,readline,mbstring,xml,gd,curl,zip}
💡
This command will install php8.0-fpm and php8.0 popular extensions to ensure that your CMS runs correctly and smoothly.

You may notice there is no php8.0-json extension because the JSON extension is a core PHP extension, so it is always enabled (source).

Install PHP 8.1

Install the PHP8.1 version with run the following command:

sudo apt install php8.1-{fpm,mysql,common,cli,opcache,readline,mbstring,xml,gd,curl,zip}
💡
This command will install php8.1-fpm and php8.0 popular extensions to ensure that your CMS runs correctly and smoothly.

After the installation of PHP7.4, PHP8.0, and PHP8.1 was completed, verify that all services are active (running):

root@ariq01:~# sudo systemctl status php7.4-fpm
● php7.4-fpm.service - The PHP 7.4 FastCGI Process Manager
     Loaded: loaded (/lib/systemd/system/php7.4-fpm.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2023-02-15 18:15:43 UTC; 16h ago
       Docs: man:php-fpm7.4(8)
   Main PID: 595 (php-fpm7.4)
     Status: "Processes active: 0, idle: 2, Requests: 0, slow: 0, Traffic: 0req/sec"
      Tasks: 3 (limit: 1116)
     Memory: 11.0M
        CPU: 2.535s
     CGroup: /system.slice/php7.4-fpm.service
             ├─ 595 "php-fpm: master process (/etc/php/7.4/fpm/php-fpm.conf)"
             ├─1011 "php-fpm: pool www"
             └─1012 "php-fpm: pool www"

Feb 15 18:15:34 ariq01 systemd[1]: Starting The PHP 7.4 FastCGI Process Manager...
Feb 15 18:15:43 ariq01 systemd[1]: Started The PHP 7.4 FastCGI Process Manager.
PHP7.4 service is active (running)
root@ariq01:~# sudo systemctl status php8.0-fpm
● php8.0-fpm.service - The PHP 8.0 FastCGI Process Manager
     Loaded: loaded (/lib/systemd/system/php8.0-fpm.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2023-02-15 18:15:43 UTC; 16h ago
       Docs: man:php-fpm8.0(8)
   Main PID: 597 (php-fpm8.0)
     Status: "Processes active: 0, idle: 2, Requests: 0, slow: 0, Traffic: 0req/sec"
      Tasks: 3 (limit: 1116)
     Memory: 11.2M
        CPU: 2.539s
     CGroup: /system.slice/php8.0-fpm.service
             ├─ 597 "php-fpm: master process (/etc/php/8.0/fpm/php-fpm.conf)"
             ├─1005 "php-fpm: pool www"
             └─1006 "php-fpm: pool www"

Feb 15 18:15:34 ariq01 systemd[1]: Starting The PHP 8.0 FastCGI Process Manager...
Feb 15 18:15:43 ariq01 systemd[1]: Started The PHP 8.0 FastCGI Process Manager.
PHP8.0 service active (running)
root@ariq01:~# sudo systemctl status php8.1-fpm
● php8.1-fpm.service - The PHP 8.1 FastCGI Process Manager
     Loaded: loaded (/lib/systemd/system/php8.1-fpm.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2023-02-15 18:15:43 UTC; 16h ago
       Docs: man:php-fpm8.1(8)
   Main PID: 599 (php-fpm8.1)
     Status: "Processes active: 0, idle: 2, Requests: 0, slow: 0, Traffic: 0req/sec"
      Tasks: 3 (limit: 1116)
     Memory: 11.4M
        CPU: 2.657s
     CGroup: /system.slice/php8.1-fpm.service
             ├─ 599 "php-fpm: master process (/etc/php/8.1/fpm/php-fpm.conf)"
             ├─1002 "php-fpm: pool www"
             └─1003 "php-fpm: pool www"

Feb 15 18:15:34 ariq01 systemd[1]: Starting The PHP 8.1 FastCGI Process Manager...
Feb 15 18:15:43 ariq01 systemd[1]: Started The PHP 8.1 FastCGI Process Manager.
PHP8.1 service active (running)

Step 3A: Configure Apache

If you want to install Apache2 rather than NGINX, install Apache with:

apt install apache2 libapache2-mod-fcgid php php-fpm php-cli libapache2-mod-php

Now, You need to enable some of the Apache modules that are required for the FastCGI configuration.

You can enable the required module by running the command:

a2enmod actions fcgid alias proxy_fcgi

Output:

root@ariq01:~# a2enmod actions fcgid alias proxy_fcgi
Enabling module actions.
Module fcgid already enabled
Module alias already enabled
Considering dependency proxy for proxy_fcgi:
Enabling module proxy.
Enabling module proxy_fcgi.
To activate the new configuration, you need to run:
  systemctl restart apache2
systemctl restart apache2
Restart the apache2

And then configures Apache Virtual Host to run with FPM/FastCGI. For this tutorial, we can create a new configuration file or you can make changes on default files. In this case, I create a new vhost.conf configuration file

sudo nano /etc/apache2/sites-available/vhost.conf
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/html
 
    <Directory /var/www/html>
        Options -Indexes +FollowSymLinks +MultiViews
        AllowOverride All
        Require all granted
    </Directory>
 
    <FilesMatch \.php$>
        # 2.4.10+ can proxy to unix socket
        SetHandler "proxy:unix:/var/run/php/php7.4-fpm.sock|fcgi://localhost"
    </FilesMatch>
 
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Apache virtualhost configuration for php7.4

Save your changes with CTRL+x and Y for Yes.

The difference between using php7.4 or php8.0 or php8.1 is

PHP7.4
---------------------------------------
<FilesMatch \.php$>
# 2.4.10+ can proxy to unix socket
        SetHandler "proxy:unix:/var/run/php/php7.4-fpm.sock|fcgi://localhost"
</FilesMatch>
---------------------------------------
PHP8.0
---------------------------------------
<FilesMatch \.php$>
# 2.4.10+ can proxy to unix socket
        SetHandler "proxy:unix:/var/run/php/php8.0-fpm.sock|fcgi://localhost"
</FilesMatch>
---------------------------------------
PHP8.1
---------------------------------------
<FilesMatch \.php$>
# 2.4.10+ can proxy to unix socket
        SetHandler "proxy:unix:/var/run/php/php8.1-fpm.sock|fcgi://localhost"
</FilesMatch>

Check and test your Apache configuration before restart the apache2 with:

#apachectl configtest
Syntax OK

and then make it a new vhost.conf we created earlier usable with apache, run:

a2ensite vhost

Output:

root@ariq01:~# a2ensite vhost
Enabling site vhost.
To activate the new configuration, you need to run:
  systemctl reload apache2

Now restart apache2 to reload the changes.

systemctl restart apache2

Step 3B: Configure NGINX

If you prefer to use NGINX instead of Apache, follow this tutorial to install NGINX stable latest based on the nginx repository.

Install the prerequisites:

sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring

Import an official nginx signing key so apt could verify the authenticity of the package. Fetch the key:

curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \ | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null

To set up the apt repository for stable nginx packages, run the following command:

echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
    | sudo tee /etc/apt/sources.list.d/nginx.list

Set up repository pinning to prefer our packages over distribution-provided ones:

echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
    | sudo tee /etc/apt/preferences.d/99nginx

To install nginx, run the following commands:

sudo apt update
sudo apt install nginx

To check whether nginx is successfully installed or not, run the following command:

nginx -v

Output:

root@ariq01:~# nginx -v
nginx version: nginx/1.22.1

Start and Enable NGINX service to ensure it's automatically starting at boot time.

systemctl start nginx && systemctl enable nginx

Now check out its status:

sudo systemctl status nginx

Output:

root@ariq01:~# systemctl status nginx
● nginx.service - nginx - high performance web server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2023-02-08 04:34:44 UTC; 3h 9min ago
       Docs: https://nginx.org/en/docs/
   Main PID: 622 (nginx)
      Tasks: 2 (limit: 1116)
     Memory: 3.3M
        CPU: 8ms
     CGroup: /system.slice/nginx.service
             ├─622 "nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf"
             └─623 "nginx: worker process
Press ctrl+c to close this systemctl status command

And then in order for to NGINX serve a web server, we need to create an NGINX server block first, and open /etc/nginx/conf.d directory.

cd /etc/nginx/conf.d

create a new conf by using your favorite text editor:

nano /etc/nginx/conf.d/mydomain.conf

Paste the following text into the file:

server {
  listen 80;
  listen [::]:80;
  server_name _;
  root /var/www/html/;
  index index.php index.html;

  location / {
    try_files $uri $uri/ /index.php;
  }

	location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
	add_header X-Cache $upstream_cache_status;
    }


 # A long browser cache lifetime can speed up repeat visits to your page
  location ~* \.(jpg|jpeg|gif|png|webp|svg|woff|woff2|ttf|css|js|ico|xml)$ {
       access_log        off;
       log_not_found     off;
       expires           360d;
  }

  # disable access to hidden files
  location ~ /\.ht {
      access_log off;
      log_not_found off;
      deny all;
  }
}

Save and close the file by pressing CTRL + X and Y for Yes.

The difference between using php7.4 or php8.0 or php8.1 is

PHP 7.4
--------------------------------------------
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
--------------------------------------------
PHP 8.0
--------------------------------------------
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
--------------------------------------------
PHP 8.1
--------------------------------------------
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
--------------------------------------------

Don't forget to always test nginx configuration with

nginx -t

If the syntax is ok, then reload NGINX by

systemctl reload nginx

That's it, thank you for reading!

Au Revoir.