Applying a PHP security patch on Ubuntu is usually a two-minute job: refresh the package index, upgrade the PHP packages, restart whatever serves PHP to the web, and then verify the patched version from both the command line and the live site. The step most administrators skip is the last one—the version reported by php -v is not necessarily the version your website is running, so a patch can appear "installed" while your site still executes the vulnerable interpreter.
Why verification has two layers
On a typical Ubuntu server, PHP exists in two places: the CLI binary you invoke in a shell, and the SAPI that handles web requests, which is either an Apache module (mod_php) or a PHP-FPM pool behind Nginx or Apache's proxy. Upgrading packages replaces files on disk, but a running process keeps its old code in memory until it is restarted. This is why a patch can be fully installed yet ineffective for web traffic—restarts are not optional, they are part of the fix.
A second complication: servers managed by tools like Ondřej Surý's PPA, cPanel, or multiple phpX.Y packages side by side can have several interpreters installed at once. Patching one does not patch the others, and the one your site uses may not be the one you check first.
Applying the update
For standard Ubuntu repositories, the update arrives through the normal package channel once the distribution publishes its security notice:
sudo apt update
sudo apt upgrade
If the machine is enrolled in Ubuntu Pro, the pro client offers a targeted alternative that patches a specific CVE and reports exactly what it changed:
sudo pro fix CVE-XXXX-NNNNN
A useful detail: pro fix works without an active Pro subscription as a diagnostic—it will tell you which packages are affected and whether a fix is available, it just won't apply the fix on systems without coverage. If several PHP versions are installed (say php7.4 alongside php8.3), the output lists each one separately, which is invaluable for catching legacy interpreters that the standard apt upgrade may not touch because no fixed build exists for that old release.
Restarting the right service
After packages are upgraded, restart the component that serves web requests:
- Apache with mod_php:
sudo systemctl restart apache2 - PHP-FPM (Apache or Nginx): restart the pool matching your version, e.g.
sudo systemctl restart php8.3-fpm. Find the exact name withsystemctl list-units 'php*-fpm*'. - Nginx without FPM changes: Nginx itself doesn't execute PHP, so restarting it alone changes nothing—the FPM pool is what needs the reload.
If you're unsure which mechanism your site uses, a phpinfo() page or the Server API line will tell you (look for FPM/FastCGI versus Apache 2.0 Handler).
Confirming the patch is actually in use
Verify at three levels:
- Package level:
apt-cache policy php8.3(or your version) shows the installed version versus the candidate. A patched Ubuntu build follows the pattern8.3.6-0ubuntu0.24.04.NN, where a higher build number after the Ubuntu suffix indicates the security update.dpkg -l | grep phpgives the full inventory, useful when multiple versions coexist. - CLI level:
php -vshows what/usr/bin/phpresolves to. Note that with theupdate-alternativessystem this may point at a different version than the web uses. - Web runtime level: drop a temporary file containing
<?php phpinfo();into the webroot, load it in a browser, and compare the version andLoaded Configuration Fileshown there against the CLI output. Delete the file immediately afterward—it leaks configuration details.
If the web version lags behind the CLI version after a restart, your FPM pool or Apache module is loading binaries from a different install prefix (a PPA, a custom build, or a secondary version)—that path is the one that needs patching.
When the update isn't available yet
During a coordinated disclosure window, the distribution may publish the fix some hours after the upstream release. Before improvising:
- Check that your
/etc/apt/sources.liststill points atsecurity.ubuntu.comor a healthy mirror; stale or regional mirrors can lag by hours. - Run
apt updateagain rather than assuming the list is current. - Resist installing PHP from a third-party source just to get the fix faster—mixing repositories often creates version conflicts that outlast the emergency.
Prevention: be ready before the next patch drop
- Inventory every PHP version on each server (
dpkg -l | grep php) and retire anything you don't actively serve. Dead versions are the most common reason a fix "doesn't apply." - Document which service each vhost depends on so the restart step is never guesswork.
- Test
pro fixor your upgrade playbook on a staging host so the production run is mechanical.
Frequently Asked Questions
Does apt upgrade restart PHP-FPM for me?
On Ubuntu, the PHP-FPM package restarts its own service on upgrade, but Apache and other pools on the box are not restarted. If your site runs through any FPM pool other than the default one for the newest version, restart it explicitly.
Why does php -v show a patched version but my site's phpinfo shows an old one?
The CLI binary and the web SAPI are separate interpreters. Your site is likely served by a different PHP installation (another version, a PPA build, or a custom prefix). Identify the binary your FPM pool or Apache module loads and update that one.
Is pro fix useless without an Ubuntu Pro subscription?
No—it still audits the machine and reports per-package affected status for the given CVE, which makes it a solid verification tool even on unenrolled systems. It only applies fixes when the entitlement covers them.
How do I check multiple PHP versions at once?
dpkg -l | grep php lists every installed PHP package, and pro fix <CVE> evaluates each installed source package independently, flagging any that remain vulnerable.
The mirror doesn't have the update yet—what now?
Wait and retry apt update; mirror synchronization typically completes within hours. Switching to the official archive URLs directly is safer than pulling PHP from an unofficial repository under time pressure.