Skip to content
SecurityPHP2Shell affects most WordPress sites. Am I affected? →
presscomet
Security

Update PHP on an Ubuntu or Debian server (2026)

On an unmanaged VPS, patching PHP is your job. Find the PHP-FPM version actually serving WordPress, apt upgrade it, handle the backport version-number trap, and restart php-fpm.

By the Presscomet teamPublished 11 min read

On this page
  1. On a VPS, patching is your job
  2. Find the PHP that serves the site
  3. The backport version-number trap
  4. Update the packages
  5. The restart everyone forgets
  6. Stuck on PHP 7.4, 8.0 or 8.1
  7. Verify you’re patched
  8. Automate it, or remove PHP

On a VPS, patching PHP is your job

If your WordPress site runs on an unmanaged VPS — a plain Ubuntu or Debian box from a provider like a GoDaddy VPS, Linode, DigitalOcean, Hetzner or an EC2 instance — then there is no host quietly patching PHP for you behind the scenes. That is the deal you signed up for: full control, full responsibility. When a runtime bug like the PHP2Shell vulnerabilities (CVE-2026-109618 and CVE-2026-109619) lands, nobody updates the server unless you do.

The good news is that on Debian and Ubuntu the update itself is three commands and a restart. The parts that trip people up are knowing which PHP to update (the one serving the web, not the one on your command line), understanding why the version number barely moves afterwards, and remembering the restart. This guide covers all three. If you want the vulnerability background first, read PHP2Shell and WordPress; for the bigger security picture, see our WordPress security guide.

Fixed upstream in
8.5.12 · 8.4.27 · 8.3.36 · 8.2.35
Debian 13 package
php8.4 8.4.27-1~deb13u1 (DSA-6574-1)
Debian 12 package
php8.2 8.2.35-1~deb12u1 (DLA-4848-1)
Ubuntu 24.04 package
php8.3 8.3.6-0ubuntu0.24.04.13 (USN-8948-1)

These are ordinary admin commands

Everything below is standard server maintenance — refreshing a package index, upgrading packages, restarting a service. None of it is exploit code, and running it is exactly what the PHP project and every security advisory asked server operators to do.

Find the PHP that actually serves the site

A server can have several PHP versions installed at once, and the one on your command line is often not the one serving WordPress. php -v shows the CLI binary (what cron jobs and WP-CLI use). Your site is served by a PHP-FPM pool, or occasionally by Apache’s mod_php. Check that one.

Which PHP serves the site?
# The CLI PHP — what WP-CLI and cron use (may differ from the web one)$ php -v# The FPM binary that serves the site — change the version to match yours$ php-fpm8.3 -v# Every installed PHP package and its exact build revision$ dpkg -l 'php*'# Which php-fpm services exist and which are running$ systemctl list-units 'php*-fpm*'

The dpkg -l 'php*' list is the one that matters: it shows the full package revision, which is how you will confirm the fix later. Cross-check it against wp-admin under Tools › Site Health › Info › Server, which reports the PHP that answers real web requests and the PHP SAPI (fpm-fcgi for PHP-FPM, apache2handler for mod_php). If Site Health and your command line disagree, Site Health wins — it’s measuring the live request path.

The backport version-number trap

This is the single most confusing thing about patching PHP on a stable Linux distribution, so it’s worth stating plainly: Debian and Ubuntu do not bump the three-number PHP version when they fix a security bug. They take the fix, apply it to the version they already ship, and increase the package revision — the bit after the dash.

So on an Ubuntu 24.04 box, the PHP2Shell-patched build still reports PHP 8.3.6, even though upstream’s fixed release is 8.3.36. The fix is there; the headline number just doesn’t show it. What changed is the package revision:

DistributionBranchFixed packageAdvisory
Debian 13php8.48.4.27-1~deb13u1DSA-6574-1
Debian 12php8.28.2.35-1~deb12u1DLA-4848-1
Ubuntu 24.04php8.38.3.6-0ubuntu0.24.04.13USN-8948-1
Ubuntu 22.04php8.18.1.2-1ubuntu2.28USN-8948-1
Ubuntu 26.04php8.58.5.4-0ubuntu1.5USN-8948-1

So how do you know you’re patched?

Compare the full package revision from dpkg -l 'php*' against the advisory string — not the short 8.3.6 number. If your revision is equal to or newer than the one in the table (for example 8.3.6-0ubuntu0.24.04.13), the fix is installed. A number lower than the upstream fixed release does not mean unpatched on a distribution that backports.

If you installed PHP from the popular third-party ondrej/php PPA (Ubuntu) or sury.org repository (Debian) instead of the distribution’s own packages, the same logic applies but the fix comes from that repository — so make sure its package is current when you upgrade.

Update the packages

Pick your platform. In every case it’s refresh the index, then upgrade. Take a snapshot or backup of the server first if your provider offers one — it makes a bad upgrade a two-minute rollback instead of a crisis.

Ubuntu’s security pocket carries the fix (USN-8948-1). Refresh and upgrade:

Ubuntu
$ sudo apt update# Upgrade everything, or target PHP only:$ sudo apt upgrade$ sudo apt install --only-upgrade 'php*'# Confirm the installed revision matches the advisory, e.g. 8.3.6-0ubuntu0.24.04.13$ dpkg -l 'php*' | grep -E 'php[0-9.]+-fpm|libapache2-mod-php'

On releases older than 22.04 the fix ships through Ubuntu Pro’s Expanded Security Maintenance (USN-8948-2), which is free for personal use — enable it with sudo pro attach if those packages don’t appear.

The restart everyone forgets

This is the step that turns “I ran the update” into “I’m actually patched.” apt replaces the PHP files on disk, but PHP-FPM and Apache keep the old code running in their worker processes until they restart. A server that was upgraded but never restarted is still serving the vulnerable runtime.

Restart whatever serves your site
# PHP-FPM (most WordPress VPS setups) — match your version number$ sudo systemctl restart php8.3-fpm# Apache with mod_php (instead of, or as well as, FPM)$ sudo systemctl restart apache2# If Nginx proxies to PHP-FPM, a reload is tidy but not strictly required$ sudo systemctl reload nginx# Confirm the service came back up$ systemctl status php8.3-fpm --no-pager

“apt restarted it for me” — did it?

On Debian and Ubuntu the package scripts usually restart php-fpm automatically, but automatic restarts can be held back (for example by needrestart in a non-interactive upgrade, or a disabled restart hook). Don’t assume. Restart it yourself, check systemctl status, then reload Tools › Site Health › Info › Server in wp-admin to confirm the live version changed.

Stuck on PHP 7.4, 8.0 or 8.1?

These branches are past upstream end of life, so the PHP project only published source-only backports for them — there’s no official binary release. What saves you is your distribution: Ubuntu 22.04 backported the fix to its PHP 8.1 (8.1.2-1ubuntu2.28), and distro-maintained 7.4/8.0 packages on supported releases got the same treatment. So if you’re on the distribution’s own packages and they’re current, you’re likely covered.

But treat that as breathing room, not a destination. An end-of-life branch gets security backports only while your distribution release is still supported, and only for the bugs they choose to backport. The durable fix is to move to PHP 8.3 or 8.4, which WordPress.org recommends and which get normal upstream updates. If you can’t patch or upgrade immediately and the box is internet-facing on an unsupported branch, follow the advice security agencies gave during PHP2Shell: take the site offline or behind network authentication until it’s on a fixed runtime.

  1. Step 1: Install the new version alongside the old one

    On Debian/Ubuntu with the ondrej/php PPA you can install, say, php8.4-fpm next to php8.1-fpm without removing anything.
  2. Step 2: Add the same extensions WordPress needs

    Install matching extensions for the new version: php8.4-mysql, -curl, -gd (or -imagick), -mbstring, -xml, -zip and -intl.
  3. Step 3: Point the web server at the new socket

    Update your Nginx fastcgi_pass or Apache handler to the new FPM socket (e.g. /run/php/php8.4-fpm.sock), then reload the web server.
  4. Step 4: Test, and keep the old version installed

    Click through the site and watch wp-content/debug.log for a day. The old FPM socket is one config line away if you need to switch back — but only onto a patched build.

The full compatibility-and-rollback walkthrough lives in how to check and update your PHP version in WordPress.

Verify you’re actually patched

Three checks close the loop: the running version in Site Health, the installed package revision against the advisory, and — if you want certainty — the changelog. Then answer the three questions in the checker below for a plain verdict.

Confirm the fix is installed and live
# Live web version (compare with wp-admin › Site Health)$ php-fpm8.3 -v# Installed revision vs the advisory string$ dpkg -l 'php*' | grep -E 'php[0-9.]+-(fpm|common)'# Debian/Ubuntu changelog should mention both CVEs$ zcat /usr/share/doc/php8.3-common/changelog.Debian.gz | grep -iE 'CVE-2026-10961[89]|109618|109619' | head

Interactive checker

Am I affected by PHP2Shell?

Runs in your browser · nothing is sent

  1. PHP version
  2. Server API
  3. Hosting
  4. Verdict

Find it in wp-admin under Tools › Site Health › Info › Server. Copy the whole number, e.g. 8.3.14.

Try:

Automate it — or take PHP out of the path

PHP2Shell won’t be the last PHP runtime bug, and on a self-managed box the response time is entirely on you. Two things make the next one far less stressful:

  • Turn on automatic security updates. Install unattended-upgrades so security pocket updates land without you watching — and configure it (or needrestart) to restart services, since an upgrade that doesn’t restart PHP-FPM leaves you exposed.
  • Put a CDN or WAF in front of the origin and make sure the box isn’t reachable by IP directly. It won’t fix a runtime bug, but it filters a lot of the early scanning while you patch.

There’s also a more structural answer: stop running PHP on every request. Presscomet reproduces the WordPress admin, block editor, URLs, feeds and REST API, but runs on Node.js with no PHP runtime — so PHP2Shell and the entire class of PHP-runtime vulnerabilities simply don’t apply, and there’s no php-fpm to update or restart at 2am. It is not “unhackable”: it has its own stack to keep patched (Node.js, its dependencies and the OS underneath), and it still needs the same server hygiene. Because it doesn’t execute PHP, your old PHP plugins don’t run — the common jobs are built in, and WooCommerce stores aren’t supported — so read can you run WordPress without PHP? before you decide.

If it fits your site, the migration only reads your existing server and reports what would move across — it never changes anything on your VPS — so it’s a safe thing to try.

Sources

Facts checked against these sources on October 24, 2026. Things change quickly; the vendor advisory always wins.

  1. [1]PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 security releases — PHP.net
  2. [2]USN-8948-1: PHP vulnerabilities — Ubuntu
  3. [3]Debian security tracker: CVE-2026-109618 — Debian
  4. [4]GHSA-w8hw-w9fx-j79w (CVE-2026-109618) — php-src on GitHub
  5. [5]GHSA-6wmf-4rv5-p3rp (CVE-2026-109619) — php-src on GitHub
  6. [6]Supported versions — PHP.net
  7. [7]Two critical PHP flaws: find, mitigate and patch PHP2Shell — Qualys

Frequently asked questions

How do I update PHP on Ubuntu or Debian?

Run sudo apt update to refresh the package list, then sudo apt upgrade to install the patched PHP packages. Afterwards you must restart the service that serves your site — sudo systemctl restart php8.3-fpm for PHP-FPM, plus sudo systemctl restart apache2 if you use Apache mod_php. Until the service restarts, the old PHP stays loaded in memory.

Why does my PHP version still look old after apt upgrade?

Debian and Ubuntu backport security fixes without changing the upstream version number; they bump the package revision instead. Ubuntu 24.04’s PHP2Shell-patched package still reports 8.3.6 (build 8.3.6-0ubuntu0.24.04.13). Compare the full package revision from dpkg -l against the advisory rather than the three-number version.

Do I need to restart PHP-FPM after updating?

Yes, always. apt replaces the files on disk, but PHP-FPM, Apache and LiteSpeed keep the old code running in their worker processes until they restart. Run sudo systemctl restart php8.3-fpm (match your version), and restart apache2 if you use mod_php. On many systems apt restarts php-fpm for you, but confirm it rather than assume.

How do I know which PHP version is actually serving WordPress?

Don’t trust php -v alone — that’s the command-line PHP and can differ from the web one. Check the FPM binary directly with php-fpm8.3 -v, list installed packages with dpkg -l 'php*', and confirm against wp-admin › Tools › Site Health › Info › Server, which reports the PHP that answers web requests.

I'm on PHP 8.1 (or 7.4/8.0) on Ubuntu 22.04. Am I patched?

If you use the distribution packages, yes — Ubuntu backported the PHP2Shell fix to 22.04’s PHP 8.1 (8.1.2-1ubuntu2.28, USN-8948-1) even though 8.1 is past upstream end of life. If you installed PHP from a third-party PPA like ondrej/php, you depend on that repository shipping a fix. Either way, plan a move to 8.3 or 8.4.

How do I update PHP in a Docker WordPress container?

Pin a fixed tag (for example php:8.4.27-fpm or wordpress:php8.4), then rebuild and recreate: docker compose build --pull and docker compose up -d --force-recreate. Pulling a new image changes nothing until the container is recreated. There are no maintained official tags for PHP 8.1 or older.

Run WordPress without a PHP runtime to patch.

Presscomet keeps your wp-admin, editor, URLs and content, and serves pages without PHP or MySQL. Check your site for free, then migrate in one click — your old site is only ever read.

Check my site