A PHP version out of support still runs perfectly and stops receiving security fixes. Nothing appears to be wrong, which is why sites sit on it for years - and it is why an old PHP version is one of the first things an attacker checks for.

Two different upgrades

  • Patch releases - 8.3.10 to 8.3.11. Security and bug fixes only, no behaviour change. Apply these automatically.
  • Major versions - 8.2 to 8.3. Can remove deprecated behaviour your code relies on. These need a check first.

Automate the patch releases

sudo apt-get install -y unattended-upgrades\nsudo dpkg-reconfigure --priority=low unattended-upgrades\ngrep -A5 "Allowed-Origins" /etc/apt/apt.conf.d/50unattended-upgrades

Prepare a major version properly

  1. Find out what breaks, staticallyvendor/bin/rector process --dry-run or phpcs --standard=PHPCompatibility --runtime-set testVersion 8.3
  2. Install the new version alongside the old — both can be present; only the pool decides which runs.
  3. Point staging at it and exercise the site — checkout, uploads, mail, the cron jobs.
  4. Switch the production pool, keep the old version installed — so going back is one line and a reload.
sudo apt-get install -y php8.3-fpm php8.3-mysql php8.3-mbstring php8.3-curl php8.3-xml\n# nginx\nfastcgi_pass unix:/run/php/php8.3-fpm.sock;\nsudo nginx -t && sudo systemctl reload nginx

Then check what is loaded, not what is installed

php -v                       # the CLI version\ncurl -sSI https://yourdomain.com | grep -i x-powered-by\nphp -m | sort                # the modules the site actually has
The CLI version and the web version are separate. A cron job can be running PHP 8.1 while the site runs 8.3, and the mismatch shows up as a failure that only ever happens at night.
On EGPHP hosting the version is a dropdown and patch releases are applied for you, with the previous version kept available. See upgrading your PHP version.