Skip to content

$ cat upgrade-php-74-to-80-on-ubuntu.md

Upgrade PHP 7.4 to 8.0 on Ubuntu

A self-hosted indie developer walks through upgrading PHP 7.4 to 8.0 on Ubuntu 18.04 without Laravel Forge, covering PPA setup, installing PHP 8.0 and extensions, purging old versions, and switching Nginx FastCGI sockets. The guide also flags pitfalls encountered along the way, including Composer install errors after the upgrade.

chasingcode.dev05 Mar 2021 · 8 min read · summary
Read on chasingcode.dev ↗
I host several websites on a Linode VPS, originally provisioned with Laravel Forge. I have long since canceled my Forge subscription, and I do my own maintenance, manually. I may not be the quickest to upgrade to the latest version of anything, but I will do it eventually. As an indie maker with zero revenue from my side projects, it wasn't making financial sense to pay for Forge. The biggest value Forge brought me was the initial provisioning of the instance. Afterwards, I continued to deploy code manually (how hard can git pull be?), and do my own basic server maintenance. I've been doing this successfully for the better part of the last 2 years. This guide is about upgrading from PHP 7.4 to 8.0 on Ubuntu 18.04. As of this writing, I have yet to upgrade to Ubuntu 20.04, but it will happen soon(ish). The instructions are partly based on this excellent article, but I've added many specifics, details, and pitfalls I encountered in my own situation. It wasn't exactly smooth sailing, as you'll see. Prep SSH into the instance, then... # Check PHP version php -v PHP 7.4.15 (cli) (built: Feb 23 2021 15:12:05) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies with Zend OPcache v7.4.15, Copyright (c), by Zend Technologies # List all PHP packages dpkg -l | grep php | tee packages.txt # List ii php-common 2:81+ubuntu18.04.1+deb.sury.org+1 all Common files for PHP packages ii php-igbinary 3.2.1+2.0.8-6+ubuntu18.04.1+deb.sury.org+1 amd64 igbinary PHP serializer ii php-memcached 3.1.5+2.2.0-9+ubuntu18.04.1+deb.sury.org+1 amd64 memcached extension module for PHP, uses libmemcached ii php-msgpack 2.1.2+0.5.7-6+ubuntu18.04.1+deb.sury.org+1 amd64 PHP extension for interfacing with MessagePack ii php-pear 1:1.10.12+submodules+notgz+20210212-1+ubuntu18.04.1+deb.sury.org+1 all PEAR Base System ii php7.4-bcmath 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 Bcmath module for PHP ii php7.4-cli 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 command-line interpreter for the PHP scripting language ii php7.4-common 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 documentation, examples and common module for PHP ii php7.4-curl 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 CURL module for PHP ii php7.4-dev 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 Files for PHP7.4 module development ii php7.4-fpm 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 server-side, HTML-embedded scripting language (FPM-CGI binary) ii php7.4-gd 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 GD module for PHP ii php7.4-igbinary 3.2.1+2.0.8-6+ubuntu18.04.1+deb.sury.org+1 amd64 igbinary PHP serializer ii php7.4-imap 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 IMAP module for PHP ii php7.4-intl 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 Internationalisation module for PHP ii php7.4-json 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 JSON module for PHP ii php7.4-mbstring 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 MBSTRING module for PHP rc php7.4-memcached 3.1.5+2.2.0-9+ubuntu18.04.1+deb.sury.org+1 amd64 memcached extension module for PHP, uses libmemcached ii php7.4-msgpack 2.1.2+0.5.7-6+ubuntu18.04.1+deb.sury.org+1 amd64 PHP extension for interfacing with MessagePack ii php7.4-mysql 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 MySQL module for PHP ii php7.4-opcache 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 Zend OpCache module for PHP ii php7.4-pgsql 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 PostgreSQL module for PHP ii php7.4-readline 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 readline module for PHP ii php7.4-soap 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 SOAP module for PHP ii php7.4-sqlite3 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 SQLite3 module for PHP ii php7.4-xml 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 DOM, SimpleXML, XML, and XSL module for PHP ii php7.4-zip 7.4.15-7+ubuntu18.04.1+deb.sury.org+1 amd64 Zip module for PHP ii php8.0-common 8.0.2-7+ubuntu18.04.1+deb.sury.org+1 amd64 documentation, examples and common module for PHP ii php8.0-igbinary 3.2.1+2.0.8-6+ubuntu18.04.1+deb.sury.org+1 amd64 igbinary PHP serializer ii php8.0-memcached 3.1.5+2.2.0-9+ubuntu18.04.1+deb.sury.org+1 amd64 memcached extension module for PHP, uses libmemcached ii php8.0-msgpack 2.1.2+0.5.7-6+ubuntu18.04.1+deb.sury.org+1 amd64 PHP extension for interfacing with MessagePack ii pkg-php-tools 1.35ubuntu1 all various packaging tools and scripts for PHP packages Add PPAs # Add ondrej/php PPA sudo add-apt-repository ppa:ondrej/php # Press enter when prompted. # 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 sudo add-apt-repository ppa:ondrej/nginx # Remove a repository (not needed here, listed for reference) # sudo add-apt-repository --remove ppa:ondrej/nginx # Check if PPA was added - should see a number of entries grep ^ /etc/apt/sources.list /etc/apt/sources.list.d/* | grep ondrej/php grep ^ /etc/apt/sources.list /etc/apt/sources.list.d/* | grep ondrej/nginx sudo apt-get update Install PHP 8.0 sudo apt install php8.0-common php8.0-cli -y # Check version php -v PHP 8.0.2 (cli) (built: Feb 23 2021 15:13:59) ( NTS ) Copyright (c) The PHP Group Zend Engine v4.0.2, Copyright (c) Zend Technologies with Zend OPcache v8.0.2, Copyright (c), by Zend Technologies # Check modules (each will appear on its own line, listed on a single line here for brevity) php -m [PHP Modules] calendar Core ctype date exif FFI fileinfo filter ftp gettext hash iconv igbinary json libxml memcached msgpack openssl pcntl pcre PDO Phar posix readline Reflection session shmop sockets sodium SPL standard sysvmsg sysvsem sysvshm tokenizer Zend OPcache zlib [Zend Modules] Zend OPcache # Install additional extensions that were present in 7.4 # Note: no need to install php8.0-json; it's already provided by other packages sudo apt install php8.0-{bcmath,curl,dev,fpm,gd,igbinary,imap,intl,mbstring,memcached,msgpack,mysql,opcache,pgsql,readline,soap,sqlite3,xml,zip} Cleanup Since I won't be using old versions of PHP (< 7.4), now is a good time to remove them. # Purge old packages, in my case from PHP 5.6 thru 7.3 sudo apt purge '^php5.6.*' sudo apt purge '^php7.0.*' sudo apt purge '^php7.1.*' sudo apt purge '^php7.2.*' sudo apt purge '^php7.3.*' Update Nginx config for each site This is for Nginx servers only. Sorry, I can't help you with Apache. Repeat the procedure for each site. There's a way to automate it, probably with sed but I don't do this often enough to warrant the sudo vi /etc/nginx/sites-enabled/example.com # Look for the following block location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # change to php8.0-fpm.sock or even better to php8.0-fpm.sock fastcgi_index index.php; include fastcgi_params; } # Test Nginx config sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful # Restart PHP FPM & Nginx sudo service php8.0-fpm restart sudo service nginx restart Note The reason I recommend using the generic php-fpm.sock instead of php8.0-fpm.sock is because, on my server at least, php-fpm.sock is actually aliased to php8.0-fpm.sock. Run these commands to find out: ls -al /var/run/php/php-fpm.sock # /var/run/php/php-fpm.sock -> /etc/alternatives/php-fpm.sock ls -al /etc/alternatives/php-fpm.sock # /etc/alternatives/php-fpm.sock -> /run/php/php8.0-fpm.sock I don't know the specifics of why it is so, but I assume it was done as part of the PHP 8 upgrade, which works really well for me as I don't have to worry about changing the Nginx config the next time I upgrade PHP. Composer install errors? Let's say that, after upgrading PHP to the shiny new 8.0, you want to run composer install --no-interaction --prefer-dist --optimize-autoloader in your Laravel project, and see the following errors: Deprecation Notice: Required parameter $path follows optional parameter $schema in phar:///usr/local/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php:62 Deprecation Notice: Required parameter $path follows optional parameter $schema in phar:///usr/local/bin/composer/vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php:108 Deprecation Notice: Method ReflectionParameter::getClass() is deprecated in phar:///usr/local/bin/composer/src/Composer/Repository/RepositoryManager.php:130 Deprecation Notice: Method ReflectionParameter::getClass() is deprecated in phar:///usr/local/bin/composer/src/Composer/Repository/RepositoryManager.php:130 Loading composer repositories with package information Installing dependencies (including require-dev) from lock file PHP Fatal error: Uncaught ArgumentCountError: array_merge() does not accept unknown named parameters in phar:///usr/local/bin/composer/src/Composer/DependencyResolver/DefaultPolicy.php:84 Stack trace: #0 [internal function]: array_merge() #1 phar:///usr/local/bin/composer/src/Composer/DependencyResolver/DefaultPolicy.php(84): call_user_func_array() #2 phar:///usr/local/bin/composer/src/Composer/DependencyResolver/Solver.php(387): Composer\DependencyResolver\DefaultPolicy->selectPreferredPackages() #3 phar:///usr/local/bin/composer/src/Composer/DependencyResolver/Solver.php(740): Composer\DependencyResolver\Solver->selectAndInstall() #4 phar:///usr/local/bin/composer/src/Composer/DependencyResolver/Solver.php(231): Composer\DependencyResolver\Solver->runSat() #5 phar:///usr/local/bin/composer/src/Composer/Installer.php(489): Composer\DependencyResolver\Solver->solve() #6 phar:///usr/local/bin/composer/src/Composer/Installer.php(232): Composer\Installer->doInstall() #7 phar:///usr/local/bin/composer/src/Composer/Command/InstallCommand.php(122): Composer\Installer->run() #8 phar:///usr/local/bin/composer/v

source

This is a summary of an article first published by chasingcode.dev. The full piece is on their site.

Open original