How to upgrade from PHP 7.x to 8.1 on Ubuntu 20.04 for LibreNMS

As I am using LibreNMS to monitor my customer's networks, I like to keep everything updated as much as possible. LibreNMS stopped updating itself, requiring PHP 8, ideally PHP 8.1. This upgrade is a simple task. However, to record how to do it, in case I need it in the future, here is the how-to.

Intro

I used this how-to on Ubuntu 20.04. With Ubuntu 22.04, there is no need to add Ondrej's repository.

Prerequisites

Have a BACKUP of your server/data. You can't reverse these commands. If you are doing this in a cloud hosting like DigitalOcean, take a snapshot of your machine before proceeding further!

Check the version of PHP running on your server:

php -v

You can proceed with this how-to if you are running PHP 7, as I do.

Step 1: Check your installed PHP packages

During the installation, you do not only upgrade PHP core packages but all of the used extensions as well. For example, if you use a PHP zip extension, you will install this at the end of this how-to.

At the end of this how-to, there is a standard list of commonly used extensions. However, it is wise to check what you are currently using and ensure you reinstall all the 7.4 extensions after the upgrade.

dpkg -l | grep php | tee packages.txt

The result will list all the PHP packages in the system:

ii  php-common                            2:75                              all          Common files for PHP packages
ii  php-composer-ca-bundle                1.2.6-1                           all          utility library to find a path to the system CA bundle
ii  php-composer-semver                   1.5.1-1                           all          utilities, version constraint parsing and validation
ii  php-composer-spdx-licenses            1.5.3-1                           all          SPDX licenses list and validation library
ii  php-composer-xdebug-handler           1.4.0-1                           all          Restarts a process without Xdebug
ii  php-igbinary                          3.1.2+2.0.8-1build1               amd64        igbinary PHP serializer
ii  php-json-schema                       5.2.9-1                           all          implementation of JSON schema
ii  php-memcached                         3.1.4+2.2.0-1                     amd64        memcached extension module for PHP, uses libmemcached
ii  php-msgpack                           2.1.0beta1-0ubuntu2               amd64        PHP extension for interfacing with MessagePack
ii  php-psr-container                     1.0.0-2                           all          Common Container Interface (PHP FIG PSR-11)
ii  php-psr-log                           1.1.2-1                           all          common interface for logging libraries
ii  php-symfony-console                   4.3.8+dfsg-1ubuntu1               all          run tasks from the command line
ii  php-symfony-filesystem                 4.3.8+dfsg-1ubuntu1               all          basic filesystem utilities
ii  php-symfony-finder                     4.3.8+dfsg-1ubuntu1               all          find files and directories
ii  php-symfony-process                   4.3.8+dfsg-1ubuntu1               all          execute commands in sub-processes
ii  php-symfony-service-contracts         1.1.8-1                           all          Generic abstractions related to writing services
ii  php7.4-cli                            7.4.3-4ubuntu2.13                 amd64        command-line interpreter for the PHP scripting language
ii  php7.4-common                         7.4.3-4ubuntu2.13                 amd64        documentation, examples and common module for PHP
ii  php7.4-curl                           7.4.3-4ubuntu2.13                 amd64        CURL module for PHP
ii  php7.4-fpm                            7.4.3-4ubuntu2.13                 amd64        server-side, HTML-embedded scripting language (FPM-CGI binary)
ii  php7.4-gd                             7.4.3-4ubuntu2.13                 amd64        GD module for PHP
ii  php7.4-gmp                            7.4.3-4ubuntu2.13                 amd64        GMP module for PHP
ii  php7.4-json                           7.4.3-4ubuntu2.13                 amd64        JSON module for PHP
ii  php7.4-mbstring                       7.4.3-4ubuntu2.13                 amd64        MBSTRING module for PHP
ii  php7.4-mysql                          7.4.3-4ubuntu2.13                 amd64        MySQL module for PHP
ii  php7.4-opcache                        7.4.3-4ubuntu2.13                 amd64        Zend OpCache module for PHP
ii  php7.4-readline                       7.4.3-4ubuntu2.13                 amd64        readline module for PHP
ii  php7.4-snmp                           7.4.3-4ubuntu2.13                 amd64        SNMP module for PHP
ii  php7.4-xml                            7.4.3-4ubuntu2.13                 amd64        DOM, SimpleXML, XML, and XSL module for PHP
ii  php7.4-zip                            7.4.3-4ubuntu2.13                 amd64        Zip module for PHP

The output above lists all my extensions. You can see that I am running PHP 7.4.3 before upgrading to 8.1. Keep your output safe for reference.

Step 2: Uninstall PHP 7.x and all its extensions

Run the command below to uninstall PHP 7 and all its extensions.

sudo apt purge php7.*

Press y and ENTER when prompted.

Step 3: Autoclean and Autoremove

After uninstalling packages from Linux, it's advised to run these two commands.

sudo apt autoclean
sudo apt autoremove

Again, press y and ENTER when prompted.

Step 4: Add PHP repository

If you are running Ubuntu 18.04 or Ubuntu 20.04, PHP 8 is not available in Ubuntu repositories, and you need to add Ondrej Sury's repository to be able to install it.

sudo add-apt-repository ppa:ondrej/php

You will see a welcome message as follows‌:

Co-installable PHP versions: PHP 5.6, PHP 7.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 -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
Press [ENTER] to continue or Ctrl-c to cancel adding it.

Press ENTER to add the repository.

Step 5: Install PHP 8.1

As of the time of writing (October 2022), LibreNMS requires 8.1. Therefore I am going to install PHP version 8.1.

sudo apt udpate
sudo apt install php8.1

You will see this output:

Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  libapache2-mod-php8.1 libargon2-1 libpcre2-8-0 libsodium23 php-common php8.1-cli php8.1-common
  php8.1-opcache php8.1-readline
Suggested packages:
  php-pear
The following NEW packages will be installed:
  libapache2-mod-php8.1 libargon2-1 libpcre2-8-0 libsodium23 php-common php8.1 php8.1-cli php8.1-common
  php8.1-opcache php8.1-readline
0 upgraded, 10 newly installed, 0 to remove and 159 not upgraded.
Need to get 5035 kB of archives.
After this operation, 22.0 MB of additional disk space will be used.
Do you want to continue? [Y/n]

Press y and ENTERto continue the installation.

In my case, the installer also installed the apache2 package. I don't need it. Therefore I remove it.

sudo apt purge apache2

Press y and ENTERto continue the removal.

Step 6: Install the extensions

The command below installs the typical extensions required by the standard WordPress site.

sudo apt install php8.1-common php8.1-mysql php8.1-xml php8.1-xmlrpc php8.1-curl php8.1-gd php8.1-imagick php8.1-cli php8.1-dev php8.1-imap php8.1-mbstring php8.1-opcache php8.1-soap php8.1-zip php8.1-intl -y

However, I don't host a WordPress site but a LibreNMS monitoring server with slightly different requirements. Therefore my apt install is going to contain different extensions.

sudo apt install php8.1-cli php8.1-common php8.1-curl php8.1-fpm php8.1-gd php8.1-gmp php8.1-mbstring php8.1-mysql php8.1-opcache php8.1-readline php8.1-snmp php8.1-xml php8.1-zip php8.1-memcached -y

You should also check which extensions were installed before. There can be some differences, though - for example, php7.4-json doesn't have a php8.1-json counterpart as its functionality has been moved into the core code.

Step 7: Check the PHP version

Now it is time to verify the current version of PHP.

php -v

The output should be similar to this:

PHP 8.1.11 (cli) (built: Sep 29 2022 22:28:49) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.11, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.11, Copyright (c), by Zend Technologies

PHP 8 is now installed and running. For use with NGINX, you will need to adjust couple more things.

Step 8: Adjusting php.ini and NGINX (optional, depending on the case)

In my installation, I need to have the timezones aligned between PHP and MariaDB database. For this, I need to update also php.ini file, which is now located in /etc/php/8.1/cli and /etc/php/8.1/fpm folders. I am using nano. Feel free to use whatever editor suits you best.

sudo nano /etc/php/8.1/cli/php.ini

Here search for this line:

;date.timezone = UTC

Uncomment the line and adjust the timezone to your need.

date.timezone = Europe/Prague

Then do the same for /etc/php/8.1/fpm/php.ini.

Then you should head to the NGINX configuration file for the server. In my case, it is located here: /etc/nginx/conf.d/librenms.conf, but typically this would be in /etc/nginx/sites-available/default or some other file in that folder.

sudo nano /etc/nginx/conf.d/librenms.conf

In this file, look for the server location which handles .php files. It should look like this:

server {
# ... OUTPUT OMITTED FOR BREWITY ...
 location ~ \.php {
  include fastcgi.conf;
  fastcgi_split_path_info ^(.+\.php)(/.+)$;
  fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;

The server still uses the old version of PHP and probably isn't able to run the PHP code at all. We need to change it to the existing php8.1. Like this:

server {
# ... OUTPUT OMITTED FOR BREWITY ...
 location ~ \.php {
  include fastcgi.conf;
  fastcgi_split_path_info ^(.+\.php)(/.+)$;
  fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;

After this change, we need the server to use the new configuration of PHP and NGINX:

sudo systemctl restart php8.1-fpm
sudo systemctl restart nginx

And that's it. The server is now running NGINX with PHP 8.1.