PHP 8.0 lost upstream security support on 26 November 2023, and no current Debian release ships it. Debian 13 defaults to PHP 8.4 and Debian 12 to PHP 8.2, so to install PHP 8.0 on Debian today you need OndΕej SurΓ½’s repository, which still builds the branch and keeps backporting security fixes into its 8.0.30 packages, the PHP2Shell fixes of 21 October 2026 included. Use it to keep an application you haven’t ported yet running, because that’s all an end-of-life branch is good for. For anything new, start on a supported branch with the current PHP guide for Debian, which installs Debian’s own PHP 8.4.
Below we add the Sury repository, install PHP 8.0 and its extensions, and prove the installed build is patched against PHP2Shell. Every command in this guide was run on fresh Debian 13 and Debian 12 systems in October 2026 against Sury’s patched PHP 8.0 build, and the output blocks come from those runs.
The official release of PHP 8 is November 26, 2020. This major release of PHP came with lots of new features and performance improvements. It also brought breaking changes, which meant some code needed modifications to run on PHP 8. Some of the nice set of new features that came with PHP 8 were the JIT compiler, named arguments, union types, attributes, and many more. On Ubuntu, the PHP 8.0 guide for Ubuntu uses OndΕej’s PPA instead.
Update the system
Before you start installation of PHP 8 on Debian update your system to the latest release. The Sury packages link against current Debian libraries, so a stale system is where dependency errors come from.
sudo apt update && sudo apt -y upgrade
Since there could be kernel updates consider system reboot after the upgrade.
[ -e /var/run/reboot-required ] && sudo reboot
If the file isn’t there, the line does nothing and you can carry on with the repository. A minimal install may never write that file, so compare the running kernel from uname -r with the newest installed kernel package from dpkg -l 'linux-image-*' | grep ^ii, and reboot if they differ.
Add the SurΓ½ APT repository
PHP 8 packages for Debian are available on the DEB.SURY.ORG repository, which publishes every PHP branch from 5.6 to 8.5 side by side. The old version of this guide installed software-properties-common and gnupg2 here. On a fresh Debian 13 system that line now stops with Error: Unable to locate package software-properties-common, because trixie dropped the package, and neither tool is needed any more. Install the three small tools the setup really uses:
sudo apt install -y lsb-release ca-certificates curl
Sury ships its signing key as a small Debian package. It drops the keyring into /usr/share/keyrings/ and keeps it current when the key rotates, so you never manage key files by hand:
curl -sSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb
sudo dpkg -i /tmp/debsuryorg-archive-keyring.deb
Add the repository signed by that keyring, with the keyring path and file name from Sury’s own README. lsb_release -sc fills in your release codename, trixie or bookworm, so the same line serves both releases. Once it is in place, the next apt upgrade also moves Debian’s own php-common and any Debian PHP packages you already have to Sury’s builds.
echo "deb [signed-by=/usr/share/keyrings/debsuryorg-archive-keyring.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/php.list
Perform package index update to confirm the repository has been added:
sudo apt update
You should see two packages.sury.org lines, the release file and the package list. This is Debian 13, and Debian 12 shows bookworm in the same places. A signature error here means the keyring package did not install, so rerun the dpkg -i line before going further.
Hit:1 http://deb.debian.org/debian trixie InRelease
Hit:2 http://deb.debian.org/debian trixie-updates InRelease
Hit:3 http://deb.debian.org/debian-security trixie-security InRelease
Get:4 https://packages.sury.org/php trixie InRelease [6129 B]
Get:5 https://packages.sury.org/php trixie/main amd64 Packages [287 kB]
Fetched 293 kB in 0s (1251 kB/s)
Confirm that apt will take PHP 8.0 from Sury before you install anything. The version string keeps the 1: epoch and carries the 21 October 2026 snapshot date, which you’ll need for the PHP2Shell check later.
apt-cache policy php8.0
On Debian 13 the candidate reads like this, and Debian 12 shows the same release with debian12 in the suffix:
php8.0:
Installed: (none)
Candidate: 1:8.0.30-25+0~20261021.88+debian13~1.gbpabebea
Version table:
1:8.0.30-25+0~20261021.88+debian13~1.gbpabebea 500
500 https://packages.sury.org/php trixie/main amd64 Packages
Older releases are a different story. Debian 10 (buster) has no Sury repository at all any more, so it gets no PHP 8.0 updates from anyone. Sury still publishes the same patched 8.0.30 build for Debian 11 (bullseye), but Debian 11 is out of support, and the free archive has no fix for Debian’s own PHP 7.4 there. Only Freexian’s paid ELTS covers bullseye, with php7.4 7.4.33-1+deb11u14 (ELA-1853-1). A patched PHP does not make the rest of a dead release safe, so move those servers up one release at a time, because Debian supports upgrades only from the previous release: start with the buster to bullseye upgrade, then 11 to 12 and 12 to 13.
Install PHP 8.0 on Debian
With the repository added you can begin the installation of PHP 8.0 on Debian Linux OS. On a fresh server the php8.0 package pulls in Apache with libapache2-mod-php8.0 and starts Apache straight away, so expect a web server on port 80 when it finishes:
sudo apt install -y php8.0
Debian 13’s apt prints the new summary format, with apache2 and the Apache module in the dependency list. Debian 12 installed 38 packages for the same command:
Installing:
php8.0
Installing dependencies:
adduser libgdbm6t64 perl
apache2 libgpm2 perl-modules-5.40
apache2-bin libjansson4 php-common
apache2-data liblua5.4-0 php8.0-cli
apache2-utils libncursesw6 php8.0-common
libapache2-mod-php8.0 libperl5.40 php8.0-opcache
libapr1t64 libproc2-0 php8.0-readline
libaprutil1-dbd-sqlite3 libsodium23 procps
libaprutil1-ldap libtext-charwidth-perl psmisc
libaprutil1t64 libtext-wrapi18n-perl sensible-utils
libargon2-1 libxml2 ssl-cert
libedit2 media-types ucf
libgdbm-compat4t64 netbase
Summary:
Upgrading: 0, Installing: 39, Removing: 0, Not Upgrading: 0
Download size: 17.0 MB
Confirm the default PHP version on the server. If you run several branches side by side, php points at whichever one Debian’s alternatives system picked, so this also tells you what your scripts and cron jobs will use.
php -v
Debian 13 printed this, and Debian 12 the same release with a build time of 08:20:50:
PHP 8.0.30 (cli) (built: Oct 21 2026 08:21:48) ( 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
Every PHP 8.0 build has said 8.0.30 since 2023, the vulnerable ones and the patched ones alike, so the version line cannot tell you whether you are safe. The next check reads the package instead.
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, which php.net scored CVSS v4.0 9.2 in its 20 October pre-announcement. Upstream fixed both on 21 October 2026 in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. PHP 8.0 got no release because the branch is end of life, but Sury backported both fixes from 8.2.35 into 1:8.0.30-25 for trixie, bookworm and bullseye, so a server installed from this repository on or after 21 October is covered. The full write-up is in the PHP security advisory.
The changelog is the reliable check, because Sury names the CVEs in the entry that fixes them:
zgrep -E 'CVE-2026-10961[89]' /usr/share/doc/php8.0-common/changelog.Debian.gz
Both Debian 13 and Debian 12 printed this line. It sits in the 1:8.0.30-25 entry dated 21 October 2026, while the previous build, 1:8.0.30-24 from July 2026, has no such line, so empty output means your build is older than 1:8.0.30-25:
+ [CVE-2026-109618, CVE-2026-109619]: Avoid state corruption via
Minimal and container images often strip /usr/share/doc, so there is no changelog to read. This line compares the installed version with the fixed one and needs no documentation files. Keep the 1: epoch in it, and run it only where php8.0-common is installed, since a missing package falls through to a misleading VULNERABLE:
dpkg --compare-versions "$(dpkg-query -W -f='${Version}' php8.0-common)" ge 1:8.0.30-25 && echo patched || echo VULNERABLE
Both fresh installs answered with the good result.
patched
A fresh install from this guide can stop here and move on to the extensions. On an existing server that came back VULNERABLE, upgrade every PHP 8.0 package. The Apache module and the embed library start with lib, which the glob misses, so they are named explicitly, and apt skips any that aren’t installed:
sudo apt update
sudo apt install -y --only-upgrade 'php8.0*' libapache2-mod-php8.0 libphp8.0-embed
The new files on disk do not help until the processes holding the old library restart. Sury’s archive only carries the current build, so we could not replay an upgrade from 1:8.0.30-24 and watch what the packages restart on their own. Restart the PHP services yourself either way. With PHP-FPM, restart the FPM service:
sudo systemctl restart php8.0-fpm
With mod_php, which is what the php8.0 package sets up, restart Apache. If both are installed, run both lines. Long-running PHP CLI workers, such as queue consumers under supervisor or in their own systemd unit, keep the old code in memory too, so restart those as well:
sudo systemctl restart apache2
Now prove the running service is newer than the package on disk. This prints the last time PHP 8.0 was installed or upgraded, rotated logs included:
zgrep -hE ' (install|upgrade) php8.0-(common|fpm):' /var/log/dpkg.log* | sort | tail -1
Our Debian 13 system had only ever installed the patched build, so the line records that install. On an upgraded server it reads upgrade followed by the old and new versions:
2026-10-22 19:59:23 install php8.0-fpm:amd64 <none> 1:8.0.30-25+0~20261021.88+debian13~1.gbpabebea
Compare it with the moment the restarted service came up. Swap apache2 for php8.0-fpm on an FPM server:
systemctl show -p ActiveEnterTimestamp apache2
The timestamp has to be later than the dpkg line, as it is here. If it is earlier, the service is still running the old build, so restart it again:
ActiveEnterTimestamp=Thu 2026-10-22 19:59:41 UTC
To see which handler actually serves your PHP, and therefore which service the restart has to cover, put a two-line test page in Apache’s default document root:
echo '<?php echo PHP_VERSION, " ", PHP_SAPI, "\n";' | sudo tee /var/www/html/info.php
Request it through Apache.
curl -s http://127.0.0.1/info.php
Both systems answered with mod_php, which means apache2 is the service to restart. A site behind PHP-FPM answers fpm-fcgi instead:
8.0.30 apache2handler
Delete the page with sudo rm /var/www/html/info.php once you have read it, because it tells anyone who finds it which PHP build you run. For the full patch walkthrough across Debian’s own PHP packages as well, see patching PHP2Shell on Debian 13 and 12.
Install PHP 8.0 extensions
To install PHP 8 extensions on Debian use the following command syntax:
sudo apt install -y php8.0-<extension>
Replace <extension> with the actual extension name. Each extension is its own package, so you install only what your application needs, and the bundled extensions share the core’s 8.0.30 build. PECL extensions such as redis or imagick carry their own versions (6.3.0 and 3.8.1 on Debian 13 in October 2026). To see what the repository offers for PHP 8.0, list the package names and leave out the debug symbol packages.
apt-cache pkgnames php8.0- | grep -v dbgsym | sort | pr -4 -t -w 96
Sury carried 88 of them on Debian 13 in October 2026.
php8.0-amqp php8.0-grpc php8.0-odbc php8.0-solr
php8.0-apcu php8.0-http php8.0-opcache php8.0-sqlite3
php8.0-ast php8.0-igbinary php8.0-opentelemetry php8.0-ssh2
php8.0-bcmath php8.0-imagick php8.0-pcov php8.0-stomp
php8.0-bz2 php8.0-imap php8.0-pgsql php8.0-sybase
php8.0-cgi php8.0-inotify php8.0-phalcon php8.0-tideways
php8.0-cli php8.0-interbase php8.0-phalcon5 php8.0-tidy
php8.0-common php8.0-intl php8.0-phpdbg php8.0-uopz
php8.0-curl php8.0-ldap php8.0-pinba php8.0-uploadprogress
php8.0-dba php8.0-libvirt-php php8.0-pq php8.0-uuid
php8.0-decimal php8.0-litespeed php8.0-protobuf php8.0-vips
php8.0-dev php8.0-lz4 php8.0-ps php8.0-xdebug
php8.0-dio php8.0-mailparse php8.0-pspell php8.0-xhprof
php8.0-ds php8.0-maxminddb php8.0-psr php8.0-xlswriter
php8.0-enchant php8.0-mbstring php8.0-raphf php8.0-xml
php8.0-excimer php8.0-mcrypt php8.0-rdkafka php8.0-xmlrpc
php8.0-fpm php8.0-memcache php8.0-readline php8.0-xsl
php8.0-gd php8.0-memcached php8.0-redis php8.0-yac
php8.0-gearman php8.0-mongodb php8.0-rrd php8.0-yaml
php8.0-gmagick php8.0-msgpack php8.0-smbclient php8.0-zip
php8.0-gmp php8.0-mysql php8.0-snmp php8.0-zmq
php8.0-gnupg php8.0-oauth php8.0-soap php8.0-zstd
This example installs the modules most database-backed applications need, plus FPM.
sudo apt install -y php8.0-{mysql,cli,common,imap,ldap,xml,fpm,curl,mbstring,zip}
Debian 13 installed eight new extension packages plus their libraries. Debian 12 reported 14 newly installed packages for the same line:
Installing:
php8.0-curl php8.0-imap php8.0-mbstring php8.0-xml
php8.0-fpm php8.0-ldap php8.0-mysql php8.0-zip
Installing dependencies:
libc-client2007e libgpg-error-l10n libonig5 libzip5
libgcrypt20 libgpg-error0 libxslt1.1 mlock
Suggested packages:
uw-mailutils rng-tools php-pear
Summary:
Upgrading: 0, Installing: 16, Removing: 0, Not Upgrading: 0
The php8.0-fpm package starts its own service but prints NOTICE: Not enabling PHP 8.0 FPM by default. when Apache is present. Apache keeps answering through mod_php until you enable proxy_fcgi and the php8.0-fpm configuration, which is why the PHP2Shell restart above covers both services. Use the same installation format for all other PHP extensions available in the repository. To check loaded PHP modules use the command:
php -m
Each extension you installed shows up as a module name in that list, for example imap, ldap, mysqli and zip after the line above.
Recommended books to read:
it helped me a lot. thanks
Thanks and welcome
Thanks! I got helped.
I got massage “apt-key is deprecated. Manage keyring files in trusted.gpg.d instead” in step2.
So I also referred “https://packages.sury.org/php/README.txt”.
Doesn’t seem to work in Debian 9 (Stretch):
$ sudo apt update
Ign:1 http://ftp.de.debian.org/debian stretch InRelease
Hit:2 http://ftp.de.debian.org/debian-security stretch/updates InRelease
Ign:3 https://packages.sury.org/php stretch InRelease
Hit:4 http://ftp.de.debian.org/debian stretch-updates InRelease
Err:5 https://packages.sury.org/php stretch Release
403 Forbidden
Hit:6 http://ftp.de.debian.org/debian stretch-backports InRelease
Hit:7 http://ftp.de.debian.org/debian stretch Release
Reading package lists… Done
E: The repository ‘https://packages.sury.org/php stretch Release’ does not have a Release file.
N: Updating from such a repository can’t be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.
Excellent! Thank you very much
Welcome and thanks for visiting our website
Not working:
Err:13 https://packages.sury.org/php focal Release
404 Not Found [IP: 84.17.46.54 443]
Thanks for your help with my php installation solution
Great happy to learn it was helpful.