PHP 8.0 has been end of life upstream since 26 November 2023, and php.net ships no new 8.0 releases. The patched builds you can still install on Ubuntu come from Ondřej Surý’s PPA, which backports security fixes and keeps the version at 8.0.30. Use it to keep a legacy application running on Ubuntu 24.04 or 22.04 while you port it, and put new servers on PHP 8.4 on Ubuntu or 8.5.
You install PHP 8.0 and its extensions, then prove the build carries the PHP2Shell fix, which on this PPA means package 1:8.0.30-25 or later. Every command below except the reboot, the PHP-FPM reload and the extension name template was run as a sudo user on a fresh Ubuntu 24.04 test system in October 2026, including an upgrade from the pre-fix build, with the install and PHP2Shell checks repeated on Ubuntu 22.04.
Update the Ubuntu system
Bring all system packages up to date first. You want PHP to land on current libraries rather than on ones the next upgrade is about to replace.
sudo apt update && sudo apt -y upgrade
Reboot when the upgrade pulled in a new kernel or core libraries such as glibc, because running services keep the old copies in memory until they restart. Ubuntu flags that case with /var/run/reboot-required, so this line reboots only when the file exists and does nothing otherwise.
[ -f /var/run/reboot-required ] && sudo systemctl reboot
If it rebooted, log in again once the server is back and carry on with the repository.
Add the Ondřej Surý PPA
Ubuntu’s own archive carries PHP 8.3 on 24.04 and PHP 8.1 on 22.04, never 8.0, so PHP 8.0 comes from the Ondřej Surý PPA. Install the tools add-apt-repository needs, then add the PPA.
sudo apt install lsb-release ca-certificates apt-transport-https software-properties-common -y
sudo add-apt-repository ppa:ondrej/php
Press Enter at the prompt to add the repository. The command refreshes the package index on its own; we piped Enter in, so in our capture the refresh lines print ahead of the PPA description. That description says the PPA is being merged into packages.sury.org while Jammy and Noble can keep using it, so expect to switch this server to a new repository line later.
Get:1 https://ppa.launchpadcontent.net/ondrej/php/ubuntu noble InRelease [24.3 kB]
Hit:2 http://security.ubuntu.com/ubuntu noble-security InRelease
Hit:3 http://archive.ubuntu.com/ubuntu noble InRelease
Get:4 https://ppa.launchpadcontent.net/ondrej/php/ubuntu noble/main amd64 Packages [317 kB]
Get:5 http://security.ubuntu.com/ubuntu noble-security/main amd64 Components [59.1 kB]
Hit:6 http://archive.ubuntu.com/ubuntu noble-updates InRelease
Hit:7 http://archive.ubuntu.com/ubuntu noble-backports InRelease
Get:8 http://archive.ubuntu.com/ubuntu noble/main amd64 Components [665 kB]
Get:9 http://security.ubuntu.com/ubuntu noble-security/universe amd64 Components [97.3 kB]
Get:10 http://security.ubuntu.com/ubuntu noble-security/restricted amd64 Components [157 B]
Get:11 http://security.ubuntu.com/ubuntu noble-security/multiverse amd64 Components [158 B]
Get:12 http://archive.ubuntu.com/ubuntu noble/universe amd64 Components [5943 kB]
Get:13 http://archive.ubuntu.com/ubuntu noble/multiverse amd64 Components [41.9 kB]
Get:14 http://archive.ubuntu.com/ubuntu noble-updates/main amd64 Components [242 kB]
Get:15 http://archive.ubuntu.com/ubuntu noble-updates/universe amd64 Components [537 kB]
Get:16 http://archive.ubuntu.com/ubuntu noble-updates/restricted amd64 Components [159 B]
Get:17 http://archive.ubuntu.com/ubuntu noble-updates/multiverse amd64 Components [887 B]
Get:18 http://archive.ubuntu.com/ubuntu noble-backports/main amd64 Components [6348 B]
Get:19 http://archive.ubuntu.com/ubuntu noble-backports/universe amd64 Components [13.6 kB]
Get:20 http://archive.ubuntu.com/ubuntu noble-backports/restricted amd64 Components [160 B]
Get:21 http://archive.ubuntu.com/ubuntu noble-backports/multiverse amd64 Components [161 B]
Fetched 7948 kB in 3s (2914 kB/s)
Reading package lists...
PPA publishes dbgsym, you may need to include 'main/debug' component
Repository: 'Types: deb
URIs: https://ppa.launchpadcontent.net/ondrej/php/ubuntu/
Suites: noble
Components: main
'
Description:
This repository is in process of being merged into https://packages.sury.org/php/;
For Ubuntu Resolute, https://packages.sury.org/php/ is the canonical way of getting PHP packages, for previous releases, I will provide a simple way how to migrate to the new repositories in upcoming weeks, you can still use this repository for Ubuntu Jammy and Ubuntu Noble.
More info: https://launchpad.net/~ondrej/+archive/ubuntu/php
Adding repository.
Before installing, confirm which PHP 8.0 build apt will pick, because that version decides whether you are patched against PHP2Shell.
apt-cache policy php8.0-common
The candidate on 24.04 is 1:8.0.30-25 with an Ubuntu suffix, and 22.04 gets the same build with ubuntu22.04.1 in the suffix. The PPA keeps only its newest build, so a single line is normal.
php8.0-common:
Installed: (none)
Candidate: 1:8.0.30-25+ubuntu24.04.1+deb.sury.org+1
Version table:
1:8.0.30-25+ubuntu24.04.1+deb.sury.org+1 500
500 https://ppa.launchpadcontent.net/ondrej/php/ubuntu noble/main amd64 Packages
Ubuntu 20.04 and 26.04 are outside this guide. The PPA’s focal index is empty, so 20.04 can no longer get PHP 8.0 from it at all, and the only PHP2Shell fix for Ubuntu’s own php7.4 there ships through Ubuntu Pro. The PPA has no resolute build either, and Ubuntu 26.04 carries PHP 8.5 in its own archive, so a new 26.04 server follows the PHP 8.5 setup on Ubuntu 26.04 instead.
Install PHP 8.0 on Ubuntu
The php8.0 metapackage installs the CLI and the Apache module, and it pulls in Apache itself. Apache is enabled and started on port 80 straight away, serving PHP through mod_php, so if you planned Nginx on this host, stop and disable Apache before Nginx needs the port. Install the metapackage.
sudo apt install php8.0
Hit the y key to start installation. On Ubuntu 24.04 the list shows Apache and libapache2-mod-php8.0 coming along with the PHP packages.
The following additional packages will be installed:
apache2 apache2-bin apache2-data apache2-utils libapache2-mod-php8.0
libapr1t64 libaprutil1-dbd-sqlite3 libaprutil1-ldap libaprutil1t64 libbsd0
libedit2 libgdbm-compat4t64 libgdbm6t64 libjansson4 liblua5.4-0
libperl5.38t64 libsodium23 perl perl-modules-5.38 php-common php8.0-cli
php8.0-common php8.0-opcache php8.0-readline psmisc ssl-cert
Suggested packages:
apache2-doc apache2-suexec-pristine | apache2-suexec-custom www-browser ufw
php-pear gdbm-l10n perl-doc libterm-readline-gnu-perl
| libterm-readline-perl-perl make libtap-harness-archive-perl
The following NEW packages will be installed:
apache2 apache2-bin apache2-data apache2-utils libapache2-mod-php8.0
libapr1t64 libaprutil1-dbd-sqlite3 libaprutil1-ldap libaprutil1t64 libbsd0
libedit2 libgdbm-compat4t64 libgdbm6t64 libjansson4 liblua5.4-0
libperl5.38t64 libsodium23 perl perl-modules-5.38 php-common php8.0
php8.0-cli php8.0-common php8.0-opcache php8.0-readline psmisc ssl-cert
0 upgraded, 27 newly installed, 0 to remove and 0 not upgraded.
Need to get 15.3 MB of archives.
After this operation, 80.0 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
Confirm the PHP version on the server. You will see why this number alone isn’t enough in a moment.
php -v
The CLI reports 8.0.30, and it will keep reporting 8.0.30 for as long as the PPA ships 8.0, because every fix since then is a backport inside the same upstream version.
PHP 8.0.30 (cli) (built: Oct 21 2026 14:25:38) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.30, Copyright (c) Zend Technologies
with Zend OPcache v8.0.30, Copyright (c), by Zend Technologies
So php -v can’t tell you whether you are patched, and the build date proves nothing on its own either. The package checks in the next section can.
Check PHP 8.0 for PHP2Shell (CVE-2026-109618, CVE-2026-109619)
PHP2Shell is a pair of critical remote code execution bugs in PHP itself, CVE-2026-109618 and CVE-2026-109619, scored CVSS v4.0 9.2 in php.net’s 20 October pre-announcement. PHP fixed them on 21 October 2026 in 8.5.12, 8.4.27, 8.3.36 and 8.2.35 and released nothing for 8.0, only minimal source backports for 7.4, 8.0 and 8.1 aimed at people who build PHP themselves. The PPA backported the fix from 8.2.35 into 1:8.0.30-25, as its changelog says, for both Ubuntu 24.04 and 22.04, so a fresh install from this guide is already patched. The PHP security advisory has the details.
The package changelog names the CVEs a build fixes, which makes it the reliable check on any server with PHP 8.0 from the PPA. You can run it before or after an upgrade.
zgrep -E 'CVE-2026-10961[89]' /usr/share/doc/php8.0-common/changelog.Debian.gz
A patched build prints this line. No output means the installed package is older than 1:8.0.30-25.
+ [CVE-2026-109618, CVE-2026-109619]: Avoid state corruption via
Minimized Ubuntu images strip /usr/share/doc, and then there is no changelog to read. This version comparison works without it. Keep the 1: epoch in the threshold, since dpkg compares it first and you would get a false result without it.
dpkg --compare-versions "$(dpkg-query -W -f='${Version}' php8.0-common)" ge 1:8.0.30-25 && echo patched || echo VULNERABLE
It printed VULNERABLE on our test server while the previous PPA build, 1:8.0.30-24, was installed, and this after the upgrade.
patched
A fresh install can stop here and move on to the extensions. On an existing server where either check fails, upgrade every PHP 8.0 package. The Apache module and the embed library start with lib, so the glob misses them and they’re named explicitly. APT skips any name that isn’t installed.
sudo apt update
sudo apt install -y --only-upgrade 'php8.0*' libapache2-mod-php8.0 libphp8.0-embed
When we ran the upgrade, the packages restarted Apache and PHP-FPM on their own. Restart them yourself anyway so no worker keeps the old code in memory. A mod_php server restarts Apache, and a server that also has php8.0-fpm (the extensions step installs it) restarts both:
sudo systemctl restart apache2 php8.0-fpm
Drop php8.0-fpm from that line if it is not installed, or drop apache2 on an Nginx server. Long-running PHP CLI processes, such as queue workers kept alive by supervisor or a systemd unit, hold the old code too, so restart those as well. Next, find when the PHP 8.0 packages were last upgraded, including entries in rotated logs.
zgrep -hE ' (install|upgrade) php8.0-(common|fpm):' /var/log/dpkg.log* | sort | tail -1
Our test server shows the jump from the pre-fix build to the fixed one. Your line will carry your own date and versions.
2026-10-22 19:56:16 upgrade php8.0-fpm:amd64 1:8.0.30-24+ubuntu24.04.1+deb.sury.org+1 1:8.0.30-25+ubuntu24.04.1+deb.sury.org+1
Compare that with the moment each restarted service came up, because a service that started before the upgrade is still running the old code, whatever the package database says.
systemctl show -p ActiveEnterTimestamp apache2 php8.0-fpm
Both timestamps must be later than the dpkg line, and here they are. If yours are earlier, you skipped the restart.
ActiveEnterTimestamp=Thu 2026-10-22 19:56:44 UTC
ActiveEnterTimestamp=Thu 2026-10-22 19:56:45 UTC
Don’t rely on a PHP_VERSION test page for this. Like Ubuntu 24.04’s own php8.3, the PPA build reports a bare 8.0.30 through Apache before and after the fix, so a test page confirms which SAPI answers but can’t prove which code it runs. The package version plus a service start time later than the upgrade is the proof.
Install PHP 8.0 extensions
Every PHP 8.0 extension is a separate package named php8.0- followed by the extension. The general form you type is below.
sudo apt install php8.0-<extension>
List the extension packages the PPA actually offers before you build an install line, because names differ between the PPA and Ubuntu’s archive.
apt-cache pkgnames php8.0- | sort | paste - - - - -
On Ubuntu 24.04 the PPA carries these, and you pick from this list.
php8.0-amqp php8.0-apcu php8.0-ast php8.0-bcmath php8.0-bz2
php8.0-cgi php8.0-cli php8.0-common php8.0-curl php8.0-dba
php8.0-decimal php8.0-dev php8.0-dio php8.0-ds php8.0-enchant
php8.0-excimer php8.0-fpm php8.0-gd php8.0-gearman php8.0-gmagick
php8.0-gmp php8.0-gnupg php8.0-grpc php8.0-http php8.0-igbinary
php8.0-imagick php8.0-imap php8.0-inotify php8.0-interbase php8.0-intl
php8.0-ldap php8.0-libvirt-php php8.0-litespeed php8.0-lz4 php8.0-mailparse
php8.0-maxminddb php8.0-mbstring php8.0-mcrypt php8.0-memcache php8.0-memcached
php8.0-mongodb php8.0-msgpack php8.0-mysql php8.0-oauth php8.0-odbc
php8.0-opcache php8.0-opentelemetry php8.0-pcov php8.0-pgsql php8.0-phalcon
php8.0-phalcon5 php8.0-phpdbg php8.0-pinba php8.0-pq php8.0-protobuf
php8.0-ps php8.0-pspell php8.0-psr php8.0-raphf php8.0-rdkafka
php8.0-readline php8.0-redis php8.0-rrd php8.0-smbclient php8.0-snmp
php8.0-soap php8.0-solr php8.0-sqlite3 php8.0-ssh2 php8.0-stomp
php8.0-swoole php8.0-sybase php8.0-tideways php8.0-tidy php8.0-uopz
php8.0-uploadprogress php8.0-uuid php8.0-vips php8.0-xdebug php8.0-xhprof
php8.0-xlswriter php8.0-xml php8.0-xmlrpc php8.0-xsl php8.0-yac
php8.0-yaml php8.0-zip php8.0-zmq php8.0-zstd
Bash expands the braces below into nine package names, including PHP-FPM, which Nginx needs. Trim the list to what your application asks for, because every extra module is code loaded into each PHP worker.
sudo apt install php8.0-{cli,common,fpm,imap,redis,snmp,xml,zip,mbstring}
The FPM package prints a notice that it isn’t enabling itself in Apache. That is expected: Apache keeps serving PHP through mod_php, and PHP-FPM runs alongside it until you point a web server at its socket. If you want to list all PHP 8.0 loaded modules, use the command below.
php -m
Nginx has no PHP module, so with Nginx every PHP request goes to PHP-FPM, and the service has to be running before the site works. Check it now, since a failed start only shows up later as a 502 from Nginx and points you at the wrong component.
systemctl status php*-fpm.service
The package enables and starts the service on install, so you should see active (running).
● php8.0-fpm.service - The PHP 8.0 FastCGI Process Manager
Loaded: loaded (/usr/lib/systemd/system/php8.0-fpm.service; enabled; preset: enabled)
Active: active (running) since Thu 2026-10-22 19:55:01 UTC; 5s ago
Docs: man:php-fpm8.0(8)
Process: 13580 ExecStartPost=/usr/lib/php/php-fpm-socket-helper install /run/php/php-fpm.sock /etc/php/8.0/fpm/pool.d/www.conf 80 (code=exited, status=0/SUCCESS)
Main PID: 13577 (php-fpm8.0)
Status: "Ready to handle connections"
Tasks: 3 (limit: 1204)
Memory: 8.8M (peak: 9.9M)
CPU: 91ms
Same format is used to install other extensions. Reload the service with sudo systemctl reload php8.0-fpm after any change under /etc/php/8.0/fpm/, so the workers pick it up.
Reference:
If 8.0 is only a stopgap for one application, the PHP 8.2 guide for 24.04 and 22.04 is the smallest jump, though 8.2 itself reaches end of life on 31 December 2026, and the PHP 8.5 install with Nginx and PHP-FPM on 24.04 is where new work should land.
Helped. Thanks)
Nice welcome!
Nice to read a tutorial that actually works! Thanks
Ondřej Surý PPA repository no longer works on ubuntu 22.04 ?
ServerNotFoundError: Unable to find the server at api.launchpad.net