Upgrade PHP 7.4 to PHP 8.0 on Ubuntu 20.04 with Nginx
Introduction
PHP 8.0 is a significant update of the PHP language that contains many new features and optimizations. However, Ubuntu 20.04 LTS only includes PHP 7.4 in its official repositories. This guide explains how to upgrade PHP to version 8.0 and configure Nginx to use it.
Prerequisites
- An existing website running with Nginx and PHP 7.4 on an Ubuntu 20.04 server.
- Follow Vultr's best practices guides to create a sudo user and update the Ubuntu server.
- Review the migration guide in the PHP Manual to ensure your website source code is compatible with PHP 8.0.
While you can directly apply this guide on your production server, it is best to test it first by restoring a snapshot of your production server to a test instance. Read the Snapshots Quickstart Guide for more details on creating snapshots and deploying new servers from them.
1. List Installed PHP 7.4 Packages
Log in to the server as a non-root sudo user via SSH.
List all the PHP 7.4 packages installed on your system.
$ dpkg -l | grep php7.4
The output looks like this.
ii php7.4-cli 7.4.3-4ubuntu2.6 amd64 command-line interpreter for the PHP scripting language ii php7.4-common 7.4.3-4ubuntu2.6 amd64 documentation, examples and common module for PHP ii php7.4-curl 7.4.3-4ubuntu2.6 amd64 CURL module for PHP ii php7.4-fpm 7.4.3-4ubuntu2.6 amd64 server-side, HTML-embedded scripting language (FPM-CGI binary) ii php7.4-gd 7.4.3-4ubuntu2.6 amd64 GD module for PHP ii php7.4-json 7.4.3-4ubuntu2.6 amd64 JSON module for PHP ii php7.4-mbstring 7.4.3-4ubuntu2.6 amd64 MBSTRING module for PHP ii php7.4-mysql 7.4.3-4ubuntu2.6 amd64 MySQL module for PHP ii php7.4-opcache 7.4.3-4ubuntu2.6 amd64 Zend OpCache module for PHP
The second column contains the names of the installed packages.
Pipe the above output into the
cut
,xargs
, andsed
commands, respectively, to generate a list of corresponding PHP 8.0 packages.$ dpkg -l | grep php7.4 | cut -f3 -d' ' | xargs | sed 's/7.4/8.0/g'
The result looks like this:
php8.0-cli php8.0-common php8.0-curl php8.0-fpm php8.0-gd php8.0-json php8.0-mbstring php8.0-mysql php8.0-opcache
Use your output when installing PHP 8.0.
Save the list of existing PHP-FPM 7.4 modules into a file:
$ php-fpm7.4 -m > ~/php-fpm7.4.modules
You will use this file to confirm that no modules are missing after upgrading.
2. Install PHP 8.0 Packages
You can install PHP 8.0 from the ppa:ondrej/php repository developed by Ondřej Surý, a long-time Debian developer.
Add the
ppa:ondrej/php
repository.$ sudo LC_ALL=C.UTF-8 add-apt-repository -y ppa:ondrej/php
Update the package index.
$ sudo apt update
Simulate the installation of PHP 8.0 packages using the list generated in the earlier section.
$ sudo apt --simulate install php8.0-cli php8.0-common php8.0-curl php8.0-fpm php8.0-gd php8.0-json php8.0-mbstring php8.0-mysql php8.0-opcache
If you get an error like this:
E: Package 'php8.0-json' has no installation candidate
That means the packages list contains a virtual package named
php8.0-json
.You need to rerun the simulation command, but this time, remove the virtual
php8.0-json
package from the packages list. Repeat until the list has no virtual packages left.Install the PHP 8.0 packages with the refined list. Note that the installation command does not contain the "--simulate" option.
$ sudo apt -y install php8.0-cli php8.0-common php8.0-curl php8.0-fpm php8.0-gd php8.0-mbstring php8.0-mysql php8.0-opcache
Save the list of the current PHP-FPM 8.0 modules into a file.
$ php-fpm8.0 -m > ~/php-fpm8.0.modules
Compare the existing PHP-FPM 7.4 modules with the current PHP-FPM 8.0 modules.
$ diff ~/php-fpm7.4.modules ~/php-fpm8.0.modules
If you get an empty output, it means no modules are missing after upgrading.
Verify that the default version of PHP in command line mode is 8.0.
$ php -v
3. Configure Nginx
Nginx and PHP-FPM 7.4 communicate with each other via a socket created by PHP-FPM 7.4. Therefore, to switch to PHP-FPM 8.0, you need to configure a new socket for PHP-FPM 8.0 and reconfigure Nginx with that socket.
Find the socket created by PHP-FPM 7.4 and the Nginx configuration file that uses that socket.
$ sudo grep -R fastcgi_pass /etc/nginx/sites-enabled/ | grep -Ev '#\s+fastcgi_pass'
If it is a Unix socket, the output will look like this:
/etc/nginx/sites-enabled/default: fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
If it is a TCP socket, the output will look like this:
/etc/nginx/sites-enabled/default: fastcgi_pass 127.0.0.1:9000;
In both cases,
/etc/nginx/sites-enabled/default
is the Nginx configuration file that you need to edit, while/var/run/php/php7.4-fpm.sock
or127.0.0.1:9000
is the socket.You may have a different filename or more than one filename. Substitute
default
in the command that follows with the files found on your system.Create a backup folder to store the configuration file before editing.
$ sudo mkdir /etc/nginx/sites-backup
Copy all configuration files to the backup folder.
$ sudo cp -L /etc/nginx/sites-enabled/* /etc/nginx/sites-backup
Edit the configuration file by substituting the new socket for the old one.
If the old socket is
/var/run/php/php7.4-fpm.sock
, the new one should be/var/run/php/php8.0-fpm.sock
.$ sudo sed -i --follow-symlinks \ 's|php7.4-fpm.sock|php8.0-fpm.sock|g' \ /etc/nginx/sites-enabled/default
If the old socket is
127.0.0.1:9000
, the new one should be127.0.0.1:9001
.$ sudo sed -i --follow-symlinks \ 's|127.0.0.1:9000|127.0.0.1:9001|g' \ /etc/nginx/sites-enabled/default
Check the new configuration.
$ sudo nginx -t
Before applying the new configuration, you need to follow the next section to configure PHP 8.0.
4. Configure PHP 8.0
Delete the default PHP 8.0 worker pool configuration.
$ sudo rm /etc/php/8.0/fpm/pool.d/*
Copy the configuration from PHP-FPM 7.4 to PHP-FPM 8.0.
$ sudo cp -rL /etc/php/7.4/fpm/pool.d/* /etc/php/8.0/fpm/pool.d/
Locate the configuration file that contains the definition of the old socket.
If the old socket is
/var/run/php/php7.4-fpm.sock
:$ sudo grep -rl 'php7.4-fpm.sock' /etc/php/8.0/fpm/pool.d
If the old socket is
127.0.0.1:9000
:$ sudo grep -rl '127.0.0.1:9000' /etc/php/8.0/fpm/pool.d
In both cases, the results are the same, similar to this:
/etc/php/8.0/fpm/pool.d/www.conf
Edit the configuration file by substituting the new socket for the old one.
If the old socket is
/var/run/php/php7.4-fpm.sock
:$ sudo sed -i 's|php7.4-fpm.sock|php8.0-fpm.sock|g' /etc/php/8.0/fpm/pool.d/www.conf
If the old socket is
127.0.0.1:9000
:$ sudo sed -i 's|127.0.0.1:9000|127.0.0.1:9001|g' /etc/php/8.0/fpm/pool.d/www.conf
You may also need to customize some settings in the main PHP 8.0 configuration file to meet your website requirements. The common settings for most PHP websites are:
max_execution_time memory_limit post_max_size upload_max_filesize date.timezone
You can find the required settings in the main PHP 7.4 configuration file
/etc/php/7.4/fpm/php.ini
, then copy those settings to the main PHP 8.0 configuration file/etc/php/8.0/fpm/php.ini
.Check the new configuration.
$ sudo php-fpm8.0 -t
Reload the PHP-FPM 8.0 service to apply the changes.
$ sudo systemctl reload php8.0-fpm.service
Reload the Nginx service so that your website runs with PHP 8.0 instead of 7.4.
$ sudo systemctl reload nginx.service
Disable the PHP-FPM 7.4 service.
$ sudo systemctl disable --now php7.4-fpm.service
5. Verify the Setup
Open your website in your browser. Test and make sure all features are working as expected.
If you decide to remove PHP 7.4, do the following:
Delete the Nginx backup folder.
$ sudo rm -fr /etc/nginx/sites-backup
Uninstall all the PHP 7.4 packages.
$ sudo apt -y purge php7.4*
More Information
See more information about the new features of PHP 8.