Upgrade PHP 7.4 to PHP 8.0 on Ubuntu 20.04 with Nginx

Updated on November 21, 2023
Upgrade PHP 7.4 to PHP 8.0 on Ubuntu 20.04 with Nginx header image

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

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

  1. Log in to the server as a non-root sudo user via SSH.

  2. 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.

  3. Pipe the above output into the cut, xargs, and sed 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.

  4. 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.

  1. Add the ppa:ondrej/php repository.

     $ sudo LC_ALL=C.UTF-8 add-apt-repository -y ppa:ondrej/php
  2. Update the package index.

     $ sudo apt update
  3. 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.

  4. 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
  5. Save the list of the current PHP-FPM 8.0 modules into a file.

     $ php-fpm8.0 -m > ~/php-fpm8.0.modules
  6. 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.

  7. 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.

  1. 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 or 127.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.

  2. Create a backup folder to store the configuration file before editing.

     $ sudo mkdir /etc/nginx/sites-backup
  3. Copy all configuration files to the backup folder.

     $ sudo cp -L /etc/nginx/sites-enabled/* /etc/nginx/sites-backup
  4. 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 be 127.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
  5. 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

  1. Delete the default PHP 8.0 worker pool configuration.

     $ sudo rm /etc/php/8.0/fpm/pool.d/*
  2. 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/
  3. 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
  4. 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
  5. 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.

  6. Check the new configuration.

     $ sudo php-fpm8.0 -t
  7. Reload the PHP-FPM 8.0 service to apply the changes.

     $ sudo systemctl reload php8.0-fpm.service
  8. Reload the Nginx service so that your website runs with PHP 8.0 instead of 7.4.

     $ sudo systemctl reload nginx.service
  9. 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:

  1. Delete the Nginx backup folder.

     $ sudo rm -fr /etc/nginx/sites-backup
  2. 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.