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 the new PHP packages alongside the existing version, updating the Apache configuration, and removing the old packages after verification. 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 the 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 the appropriate version numbers wherever they appear in commands and file paths. For a new upgrade, use the latest PHP branch supported by the application and available for the Debian release. The package and Apache configuration steps are generally the same for other supported PHP version upgrades, but always review the migration guide for the target PHP release for version-specific changes.
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.
- Active support means the version receives both bug fixes and security patches. This is the target stage.
- Security fixes only means active bug fix support has ended; the version still receives critical security patches but no other fixes.
- End of life means the version receives nothing and running it on a public-facing server is a security risk.
The upgrade should be planned before the current version reaches end of life, preferably before it enters security-only support. 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 the application. WordPress core typically adopts new PHP releases quickly, while plugins may take longer to declare compatibility. Check the WordPress hosting requirements and test the plugin stack against the target version before upgrading a production server.
Before Upgrading
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 the installed plugins have known compatibility issues with the target PHP version. Check that the installed 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 alongside the existing version and test the application against the new PHP runtime before switching production traffic to it. A staging environment is preferable for this testing. Reviewing the PHP migration guide and application logs can help identify deprecated or incompatible code before the production switch.
Take a Snapshot
Take a snapshot of the 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.
On 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 the server is running 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 about a configuration file, review the differences and retain the existing version if it contains intentional local customizations. Do not automatically replace a customized production configuration with the package maintainer’s version.
NOTE: This guide uses
apt upgraderather thanapt full-upgrade.apt upgradeis more conservative for routine maintenance because it does not remove installed packages to complete an upgrade. If an update requires removing an installed package, APT holds that package back.apt full-upgradeallows APT to make package removals and dependency changes when necessary to complete the upgrade.
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 the 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 the default values used by a new PHP installation. Apply the same production settings used in the original LAMP installation. These commands modify the existing directives in the default php.ini:
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 a disable_functions directive was applied to the 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 any other customizations were made 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 that were 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. Runsudo systemctl status php8.4-fpmto see the reason. A missing socket will cause Apache to return a 503 error for PHP requests handled by that FPM configuration.
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 the PHP version and FPM configuration. Do not leave a publicly accessible phpinfo.php file on a production server.
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 the application and confirming it is functioning as expected. WordPress will display a database connection error on the front end if the mysqli extension is missing or misconfigured.
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 the error log shows 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 stale or conflicting socket file.
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 that the mysqli extension is loaded under PHP 8.4:
php8.4 -m | grep mysqli
The mysqli extension should appear in the output. If it does not, install the PHP 8.4 MySQL package:
sudo apt install -y php8.4-mysql
sudo systemctl restart php8.4-fpm
If the extension is 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 can indicate code that is 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 the extensions available to PHP 8.4 from the CLI:
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 the 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 general process applies to future PHP version upgrades; substitute the relevant version numbers and review the migration guide for any version-specific changes. The troubleshooting section covers several common failure modes that can occur during a PHP version upgrade.