Upgrade PHP on a Debian LAMP Stack

One of the core advantages of building a LAMP stack from a bare Debian OS image is that each component is managed independently through APT. When a new PHP version is released, upgrading in place is a matter of installing new packages and updating the Apache configuration. No instance replacement, no content migration, no waiting for a managed hosting provider to make the version available.

This guide covers upgrading PHP on a Debian LAMP stack running Apache with PHP-FPM. It also covers updating Apache and MariaDB through APT as part of the same maintenance pass. If your server was built following Install and Harden a Debian LAMP Stack on Amazon Lightsail, the steps here apply directly to that configuration.

The examples throughout use PHP 8.3 as the installed version and PHP 8.4 as the target. Substitute your own version numbers wherever they appear in commands and file paths. The process is the same regardless of which version pair is involved.

NOTE: This guide covers upgrading between PHP releases (for example, PHP 8.3 to PHP 8.4) while remaining on the same Debian release. A major Debian OS upgrade, such as from Debian 12 to Debian 13, involves significantly more risk and is better handled by provisioning a fresh instance and following the install guide rather than upgrading in place. The same applies to any upgrade where the underlying OS default PHP version changes or where significant package conflicts are expected.

When to Upgrade PHP

Each PHP version follows a three-stage lifecycle: active support, security-only patches, and end of life. Monitor PHP version support timelines as part of routine maintenance.

The right time to upgrade is when your current version exits active support, not when it reaches end of life. Waiting until end of life compresses the upgrade window and increases the risk of running unpatched code on a production server.

Before upgrading, confirm the target version has sufficient ecosystem support for your application. WordPress core typically adopts new PHP releases quickly, while plugins may take longer to declare compatibility. Check the WordPress hosting requirements and test your plugin stack against the target version before upgrading a production server.

Before You Begin

Check for Plugin Compatibility Issues

Each new PHP version enforces stricter handling of some patterns that were silently permitted in earlier versions. Before upgrading, check whether your installed plugins have known compatibility issues with the target PHP version. Check that your themes and plugins explicitly support the target PHP version. If desired, a compatibility scanner can help identify potential issues before upgrading.

For non-WordPress PHP applications, install the new PHP version first without switching Apache to use it, then review the application error log for deprecation notices and fatal errors. Each PHP version introduces deprecations for patterns that will become errors in the next major version. Catching them before the switch reduces the risk of unexpected failures.

Take a Snapshot

Take a snapshot of your instance before proceeding. A PHP upgrade is low-risk when following these steps, but having a restore point eliminates recovery time if something unexpected occurs.

In Lightsail, click the instance name, click the Snapshots tab, and click Create snapshot. Verify that the snapshot completed successfully before proceeding.

If you are using a different hosting provider, use whatever snapshot or backup mechanism is available before proceeding.

Update Apache and MariaDB

Before upgrading PHP, update Apache and MariaDB through APT. This ensures you are working with the latest security patches for both components before adding a new PHP version on top. Installing PHP 8.4 is a separate step because it is a new package rather than an in-place upgrade of PHP 8.3.

sudo apt update && sudo apt upgrade -y

Review the output for any notices about held packages or configuration file prompts. If APT prompts you about configuration files, press N to keep your existing version.

NOTE: This guide uses apt upgrade rather than apt full-upgrade. On a production server, apt upgrade is the safer choice for routine maintenance: it installs available updates but will not remove installed packages or introduce new dependencies that could disrupt the running stack. apt full-upgrade is more aggressive and is appropriate for major distribution upgrades, not routine patching.

Restart Apache and MariaDB if either was updated:

sudo systemctl restart mariadb
sudo apache2ctl configtest
sudo systemctl restart apache2

Verify both services are running:

sudo systemctl status apache2
sudo systemctl status mariadb

Install PHP 8.4

Since both PHP 8.3 and PHP 8.4 are available from the same Sury repository, no repository configuration changes are required. If the Sury repository is not already configured on your server, follow the Add the Sury PHP Repository section of the install guide before continuing.

Install PHP 8.4 with PHP-FPM and the same extensions used in the install guide:

sudo apt install -y php8.4 php8.4-{common,fpm,mysql,curl,igbinary,imagick,intl,mbstring,xml,zip}

After installation, confirm the PHP 8.4 packages are present:

php8.4 -v

The output may already show PHP 8.4. If it still reports PHP 8.3, that is expected on some systems; the CLI default is updated in a later step.

Configure PHP 8.4 for Production

The PHP 8.4 configuration file at /etc/php/8.4/fpm/php.ini contains default values that are too conservative for most WordPress installations. Apply the same production settings used during the initial installation:

sudo sed -i 's/^memory_limit = .*/memory_limit = 256M/' /etc/php/8.4/fpm/php.ini
sudo sed -i 's/^upload_max_filesize = .*/upload_max_filesize = 64M/' /etc/php/8.4/fpm/php.ini
sudo sed -i 's/^post_max_size = .*/post_max_size = 64M/' /etc/php/8.4/fpm/php.ini
sudo sed -i 's/^max_execution_time = .*/max_execution_time = 120/' /etc/php/8.4/fpm/php.ini
sudo sed -i 's/^expose_php = .*/expose_php = Off/' /etc/php/8.4/fpm/php.ini

If you applied disable_functions on your PHP 8.3 installation, apply it to PHP 8.4 as well:

sudo sed -i 's/^disable_functions = .*/disable_functions = exec,passthru,shell_exec,system,proc_open,popen/' /etc/php/8.4/fpm/php.ini

If you made any other customizations to /etc/php/8.3/fpm/php.ini, compare both files before continuing:

diff /etc/php/8.3/fpm/php.ini /etc/php/8.4/fpm/php.ini

Review the diff output and port any intentional customizations from the 8.3 file to the 8.4 file. Ignore differences in version-specific default values; focus only on lines you changed deliberately.

Update the Apache PHP-FPM Configuration

Apache must be switched from the PHP 8.3 FPM configuration to PHP 8.4. This involves disabling the old FPM configuration, enabling the new one, and restarting both services.

Disable the PHP 8.3 FPM configuration for Apache:

sudo a2disconf php8.3-fpm

Enable the PHP 8.4 FPM configuration:

sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.4-fpm

Enable the PHP 8.4 FPM service so it starts automatically at boot:

sudo systemctl enable php8.4-fpm

Restart PHP-FPM first so the socket is ready before Apache attempts to connect to it:

sudo systemctl restart php8.4-fpm
sudo apache2ctl configtest
sudo systemctl restart apache2

Confirm the PHP 8.4 FPM socket exists:

ls /run/php/php8.4-fpm.sock

NOTE: If this command returns No such file or directory, PHP 8.4 FPM is not running or failed to start. Run sudo systemctl status php8.4-fpm to see the reason. A missing socket will cause Apache to return a 503 error for all PHP requests.

Verify the Upgrade

PHP CLI Version

php -v

The output should now report PHP 8.4. If it still shows 8.3, the system’s default CLI version has not been updated. This happens when multiple PHP versions are installed simultaneously; the alternatives system controls which binary the php command resolves to. Update it explicitly:

sudo update-alternatives --set php /usr/bin/php8.4

This affects only the CLI binary. Apache serves PHP through the PHP-FPM socket, not the CLI binary, so the version Apache uses is determined by the FPM configuration updated in the previous step, not by the alternatives setting. WP-CLI and any cron jobs that invoke php directly are affected by the alternatives setting and will use whichever version the php command resolves to.

PHP-FPM Status

sudo systemctl status php8.4-fpm

Confirm PHP-FPM is being used by Apache by creating a temporary info file:

echo "<?php phpinfo(); ?>" | sudo tee /www/example-com/public_html/phpinfo.php

Navigate to https://www.example.com/phpinfo.php in a browser and confirm that the Server API line reads FPM/FastCGI and the PHP version shows 8.4. Remove the file immediately after confirming:

sudo rm /www/example-com/public_html/phpinfo.php

Apache Configuration Syntax Check

sudo apache2ctl configtest

The output should end with Syntax OK.

MariaDB Status

sudo systemctl status mariadb

Test a PHP database connection by logging in to your application and confirming it is functioning as expected. WordPress will display a database connection error on the front end if the PDO or MySQLi extension is missing or misconfigured, which is the most common post-upgrade issue.

Troubleshooting

Apache Returns 503 for All PHP Requests

A 503 error after the upgrade almost always means the PHP-FPM socket is missing or PHP-FPM is not running. Check the Apache error log for the specific message:

sudo tail -n 50 /var/log/apache2/error.log

If you see AH02454: FCGI: attempt to connect to Unix domain socket /run/php/php8.4-fpm.sock failed, PHP-FPM is not running or the socket path does not match what Apache expects. Verify the socket exists:

ls /run/php/php8.4-fpm.sock

If it is missing, check the PHP-FPM service status and journal for the failure reason:

sudo systemctl status php8.4-fpm
sudo journalctl -u php8.4-fpm -n 50

Common causes include a configuration error in /etc/php/8.4/fpm/php.ini (check with sudo php-fpm8.4 -t) or a port conflict if another process is already using the socket path.

WordPress Shows a Database Connection Error

If WordPress loads but immediately shows a database connection error, the most likely cause is a missing or broken database extension. Verify the pdo_mysql and mysqli extensions are loaded under PHP 8.4:

php8.4 -m | grep -E 'pdo_mysql|mysqli'

Both should appear in the output. If either is missing, install the PHP 8.4 MySQL package:

sudo apt install -y php8.4-mysql
sudo systemctl restart php8.4-fpm

If the extensions are present and the error persists, check the WordPress wp-config.php file to confirm the database credentials are correct and the MariaDB service is running.

PHP Deprecation Notices or Fatal Errors in the Error Log

After upgrading, monitor the Apache error log for deprecation notices or fatal errors generated by PHP:

sudo tail -f /var/log/apache2/error.log

Deprecation notices indicate code that uses patterns the current PHP version has marked for removal in a future major release. They do not break functionality in the current version but should be treated as a warning that affected plugins or application code will need to be updated before the next major PHP upgrade. If the notice is in a plugin, check whether a newer version of the plugin addresses it.

Fatal errors are more serious and indicate code that is genuinely incompatible with the installed PHP version. The error log will identify the file and line number. If the error is in a plugin, update the plugin to a compatible version or temporarily disable it to restore site functionality while investigating.

PHP CLI Still Reports the Previous Version

If php -v still reports the previous version after running update-alternatives, confirm which binary the php command resolves to:

which php
ls -la $(which php)

If the symlink still points to the previous PHP binary, set it explicitly:

sudo update-alternatives --set php /usr/bin/php8.4

Verify all registered alternatives to see what versions are available:

sudo update-alternatives --list php

Extension Missing After Upgrade

If a PHP extension that was present under 8.3 is not available under 8.4, it was not included in the install command. List loaded extensions under PHP 8.4 to identify what is missing:

php8.4 -m

Compare against the extensions loaded under PHP 8.3:

php8.3 -m

Install any missing extensions by their PHP 8.4 package name:

sudo apt install -y php8.4-[extension-name]
sudo systemctl restart php8.4-fpm

Remove PHP 8.3

After confirming PHP 8.4 is working correctly and the application is functioning as expected, remove the PHP 8.3 packages. Running two PHP versions simultaneously is not inherently harmful, but it consumes disk space and leaves unused packages on the server that no longer serve a purpose once the upgrade is confirmed.

Stop and disable the PHP 8.3 FPM service before removing the packages:

sudo systemctl stop php8.3-fpm
sudo systemctl disable php8.3-fpm

Remove all PHP 8.3 packages:

sudo apt purge php8.3* -y
sudo apt autoremove -y

Confirm PHP 8.3 packages are gone:

dpkg -l | grep php8.3

The command should return no output. If any packages remain, run sudo apt purge with the specific package names listed in the output.

Summary

Upgrading PHP on a self-managed Debian LAMP stack is straightforward when the stack was built with PHP-FPM and the Sury repository. The process is: check plugin compatibility, take a snapshot, install the new PHP version and its extensions, port your php.ini customizations, switch the Apache PHP-FPM configuration from the old version to the new one, restart both services, verify the upgrade, and remove the old version.

The same process applies to future PHP version upgrades; substitute the relevant version numbers and follow the same sequence. The troubleshooting section covers the failure modes most likely to occur regardless of which version pair is involved.