Chat on WhatsApp
Upgrades & Patches 9 min read

How to Find Every PHP Version Running on Your Server (Before You Patch)

php -v shows one PHP, but most servers run several at once: CLI, a PHP-FPM service per version, Docker containers and control panel builds. Here is how I found all of them on my own VPS before the 21 October 2026 PHP security release.

How to Find Every PHP Version Running on Your Server (Before You Patch)

The quick answer to "how do I check the PHP version on my server" is: you check all of them. Run ls /etc/php to see installed versions, systemctl list-units 'php*-fpm*' to see which PHP-FPM versions are running, follow nginx or Apache config to see which one each website really uses, and run docker exec into every container that ships its own PHP. php -v alone shows you one binary out of many.

I did this on my own VPS this morning, 21 October 2026, because the PHP security team announced a critical release for today. The result surprised me a little, and it is the reason I am writing this before anyone patches anything.

10PHP-FPM versions running on my VPS
1host PHP version actually serving sites
3Docker containers with their own PHP
15local PHP containers on my Mac

Why does this matter today?

On 20 October 2026 php.net posted advance notice of a security release scheduled for Wednesday 21 October 2026 at 14:00 UTC. It fixes two critical vulnerabilities, both rated CVSS v4.0 9.2. The release came out on 21 October: PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35. What the bugs are and how to update is in my php2shell write-up.

Huntress wrote up the leaked details under the informal name php2shell (CVE-2026-109618 and CVE-2026-109619). Their first recommendation is the same thing this post is about: inventory every PHP install, including the ones bundled with control panels and vendor software. They also say it is not yet confirmed which PHP setups (FPM, CGI, Apache module and so on) are exposed. Until that is clear, I treat every PHP binary on a box as in scope.

Also look at php.net's supported versions page. Today only 8.2, 8.3, 8.4 and 8.5 get fixes. 8.2 and 8.3 are security-only, and 8.2 security support ends 31 Dec 2026. Anything older will not get a patch from php.net at all.

Why php -v lies to you (a little)

A single Linux server can run PHP in four different ways at the same time:

  • CLI: the php command you type, plus cron jobs and scripts. php -v shows this one only.
  • PHP-FPM: one service per version (php8.3-fpm, php8.4-fpm), each with its own pools. This is what nginx talks to.
  • Apache mod_php: PHP loaded inside Apache itself. No separate service to see.
  • Docker: every container brings its own PHP build, completely separate from the host packages.

Patching the CLI does nothing for FPM if they are different versions, and patching the host does nothing for containers. That is the whole trap.

How to check the PHP version on a server: installed versions

On Debian and Ubuntu, start with the config folder. Each version you have ever installed leaves a folder here:

ls /etc/php
# then ask each binary directly
for v in /usr/bin/php[0-9]*; do echo -n "$v: "; $v -r 'echo PHP_VERSION, PHP_EOL;'; done
which php && php -v
update-alternatives --display php

On my Ubuntu 24.04 box with CloudPanel, ls /etc/php showed ten versions: 7.1, 7.2, 7.3, 7.4, 8.0, 8.1, 8.2, 8.3, 8.4 and 8.5.

The package manager gives you the exact package versions:

apt list --installed 'php*' 2>/dev/null | grep -E 'cli|fpm|common'
# RHEL, Alma, Rocky
rpm -qa | grep -i php

Which PHP-FPM versions are running?

Installed is one thing. Running is what attackers can reach. List the FPM services and ask each FPM binary for its version:

systemctl list-units --type=service 'php*-fpm*'
php-fpm8.4 -v
php-fpm8.3 -v
# see which FPM masters are actually alive
ps -eo pid,user,cmd | grep '[p]hp-fpm: master'

On my VPS all ten FPM services were running. Every one of them. That is CloudPanel's default: it installs and starts every version so you can pick one per site in the UI.

Which PHP version does my site use?

This is the question that really matters, and you answer it from the web server config, not from PHP. With nginx, find the fastcgi_pass lines:

grep -Rn "fastcgi_pass" /etc/nginx/
# example output: fastcgi_pass 127.0.0.1:18004;   or   unix:/run/php/php8.4-fpm.sock

Then match that port or socket to a pool's listen = line:

grep -Rn "^listen =" /etc/php/*/fpm/pool.d/*.conf
ss -ltnp | grep php-fpm

The folder in the matching path (/etc/php/8.4/fpm/pool.d/) tells you the PHP version for that site. Do it for every server block.

When I did this, only the 8.4 pools were serving websites. The other nine versions had just CloudPanel's default pools listening on 127.0.0.1, and no nginx config pointed at them. Not public, but still running and still something to patch or switch off. My sister post on disabling end-of-life PHP versions on a server covers how I handle those.

For Apache, check what is loaded:

apachectl -M 2>/dev/null | grep -i php
ls /etc/apache2/mods-enabled/ | grep -i php
grep -Rn "SetHandler.*proxy:" /etc/apache2/

A php_module line means mod_php. A SetHandler "proxy:unix:..." line means Apache hands PHP to FPM, so follow the socket like above.

Sites behind a reverse proxy to Docker

If nginx uses proxy_pass instead of fastcgi_pass, the PHP lives somewhere else, often in a container:

grep -Rn "proxy_pass" /etc/nginx/
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Ports}}'
docker exec <container> php -v
# all containers in one go
for c in $(docker ps --format '{{.Names}}'); do echo -n "$c: "; docker exec "$c" php -r 'echo PHP_VERSION, PHP_EOL;' 2>/dev/null || echo "no php"; done

This is exactly how kishansavaliya.com runs. It does not use the host PHP at all. nginx proxies to a Docker container running PHP 8.4.21 on the official php:8.4-fpm base image. Two more containers on the same box run their own PHP 8.3 builds, one WordPress image and one php:8.3-apache image. Patching the host packages would fix none of these three. You fix containers by pulling a newer base image and rebuilding, then recreating the container.

My Mac is the same story. There is no host PHP. php is a shell function that runs PHP inside each project's container, and I have 15 local PHP containers ranging from 8.2.30 to 8.4.22.

Control panels ship their own PHP

  • CloudPanel ships its own PHP packages with a +clp-noble suffix on Ubuntu 24.04. Check them with apt list --installed 'php*' | grep clp. Updates come through CloudPanel's own apt repository.
  • cPanel uses EasyApache 4 builds named ea-php plus the version (for example ea-php84), installed under /opt/cpanel/. Check rpm -qa | grep ea-php or dpkg -l | grep ea-php.
  • Plesk keeps its PHP handlers under /opt/plesk/php/. ls /opt/plesk/php shows the versions.

The point is the same each time: the panel's PHP is not the same package as the distro's PHP, so updating one does not touch the other.

Is a PHP update waiting? Run apt-get update first

This one caught me. I ran apt list --upgradable and saw no PHP updates at all. Then I ran apt-get update to refresh the package lists, asked again, and it listed 8.2.34, 8.3.35, 8.4.26 and 8.5.11 packages waiting.

sudo apt-get update
apt list --upgradable 2>/dev/null | grep -i php

apt only compares against the lists it last downloaded. Without the refresh, "nothing to upgrade" just means "nothing you know about yet". Those four versions were already out before today's release, so they are not the php2shell fixes. Refresh again now and look for 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or your vendor's patched build of them.

Magento: CLI, cron and storefront can run different PHP

Magento is a good example of why one php -v is not enough:

  • bin/magento runs with whatever CLI PHP is called (the one in PATH, or the full path you type).
  • Cron also uses CLI PHP, and the crontab line often has a hard-coded path like /usr/bin/php8.3. Check with crontab -l -u <site-user>.
  • The storefront and admin run on PHP-FPM (or inside a container), picked by the web server config.
crontab -l -u <site-user> | grep -i php
sudo -u <site-user> php -v
# which PHP-FPM serves the storefront: follow fastcgi_pass to the pool
grep -h fastcgi_pass /etc/nginx/sites-enabled/your-store.conf
grep -l "listen = 127.0.0.1:9001" /etc/php/*/fpm/pool.d/*.conf

Nothing forces these three to match, so check each one instead of assuming. If you are moving a store up, my notes on PHP 8.4 and Magento compatibility cover the deprecation that bites most. And PHP is only half of the patching job, so also check for missing Magento security patches while you are on the box.

A simple PHP inventory table to fill in

Copy this into a spreadsheet and fill one row per PHP you find. If a row has no site, ask yourself why it is running.

WhereType (CLI, FPM, mod_php, Docker, panel)VersionUsed by (site, cron, nothing)How you update itPatched?
Host /usr/bin/php8.4CLIapt
php8.4-fpmFPMapt
php8.3-fpmFPMapt or disable
Container nameDockerpull image, rebuild
Panel PHPPanel bundlepanel updates

Once the inventory is done and patches are in, the next question is whether anything got in before you patched. That is the subject of my sister post on checking a Magento server for PHP RCE compromise.

If you would rather have someone do this inventory and the patching on your server, hire me or message me on WhatsApp. It is usually a short job.

FAQ

How do I check the PHP version on my server?

Run php -v for the CLI, ls /etc/php for installed versions, systemctl list-units 'php*-fpm*' for running FPM versions, and docker exec <container> php -v for each container. One command is not enough because each of these can be a different version.

Which PHP version does my website actually use?

Look at the web server config. In nginx, the fastcgi_pass port or socket matches a pool's listen = line in /etc/php/X/fpm/pool.d/, and X is your version. If nginx uses proxy_pass, follow the port to docker ps and ask that container.

Why does php -v show a different version than my website?

Because php -v shows the CLI binary in your PATH, while the website runs on PHP-FPM, Apache mod_php or a container. They are separate installs and can be different versions.

How do I check the php-fpm version?

Call the FPM binary directly, for example php-fpm8.4 -v, or php-fpm -v on systems with one version. systemctl list-units 'php*-fpm*' shows which FPM services are running.

Why does apt list --upgradable show no PHP updates?

Usually because the package lists are old. Run sudo apt-get update first. On my VPS the list was empty before the refresh and showed four PHP versions waiting after it.

Does updating host PHP packages update PHP in Docker?

No. Each container has its own PHP from its base image. Pull the newer image, rebuild, and recreate the container, then confirm with docker exec <container> php -v.

Which PHP versions get the 21 October 2026 security fixes?

The fixed releases are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, published on 21 October 2026. Its supported versions page lists 8.2, 8.3, 8.4 and 8.5 as the branches still receiving security fixes.

Does Magento cron use the same PHP as the storefront?

Not always. Cron and bin/magento use CLI PHP, often with a full path in the crontab, while the storefront uses PHP-FPM or a container. Check both and patch both.