PHP
June 29, 2026

How to Switch PHP Versions for a Single Website

8 min read
Author
CloudStick Team
DevOps Engineer
Share this article
How to Switch PHP Versions for a Single Website
CloudStick
Switch PHP
Version Per Site

Why Switch PHP Per Site?

Modern web servers routinely host a mix of applications that have different PHP version requirements. A legacy e-commerce platform may depend on PHP 7.4 for compatibility with older extensions, while a freshly deployed WordPress site performs best on PHP 8.3 and a custom Laravel application requires the strict typing features introduced in PHP 8.1. If every site on the server shared a single global PHP version, upgrading one application would risk breaking another.

PHP-FPM (FastCGI Process Manager) solves this elegantly. Each PHP version you install gets its own set of worker pools, and each pool listens on a unique Unix socket or TCP port. Nginx (or Apache) can then direct traffic from different virtual hosts to completely independent PHP processes — meaning site A runs PHP 8.3 while site B stays on PHP 7.4, with no interaction between them.

This guide walks you through the complete process on Ubuntu 22.04 or 24.04: installing multiple PHP versions side by side, creating an isolated PHP-FPM pool for the target site, updating the Nginx virtual host to use that pool, and verifying the change went through cleanly. The same pattern applies whether you are upgrading from PHP 8.1 to 8.3 or downgrading a site that broke after an unplanned update.

Install Multiple PHP Versions Side by Side

Ubuntu's default repositories only ship one PHP version, so you need the Ondrej Sury PPA — the de-facto standard for multi-version PHP on Debian-based systems. Once the PPA is added, you can install any combination of PHP versions without them conflicting.

Prerequisite

You need root or sudo access on the server and Nginx already configured as the web server. If you manage servers through CloudStick, PHP version management is available directly from the website settings panel under EasyPHP — no manual commands required. The steps below are for those managing servers directly via SSH.

Add the Ondrej PPA and install the PHP versions you need — in this example PHP 8.1 (currently installed) alongside PHP 8.3 (the target version for the new site):

# Add the Ondrej Sury PPA
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
# Install PHP 8.3 and its FPM service
sudo apt install php8.3 php8.3-fpm php8.3-cli php8.3-common \
php8.3-mysql php8.3-xml php8.3-mbstring php8.3-curl \
php8.3-zip php8.3-intl php8.3-bcmath php8.3-imagick -y
# Start and enable the PHP 8.3 FPM service
sudo systemctl enable php8.3-fpm
sudo systemctl start php8.3-fpm
# Verify both versions are running
sudo systemctl status php8.1-fpm php8.3-fpm --no-pager

After running the status command you should see both services listed as active (running). The extension list above covers the most common requirements for WordPress, Laravel, and general PHP applications — add or remove packages to match your application's composer.json requirements.

Configure a Dedicated PHP-FPM Pool for the Site

Each installed PHP-FPM version ships with a default pool named www, which listens on /run/php/phpX.Y-fpm.sock. While you could point your site directly at this default socket, the cleanest approach is to create a dedicated pool for each site. This gives you per-site process isolation, independent resource limits, and a unique socket path that cannot accidentally be reused by another virtual host.

PHP-FPM pool configuration files live in /etc/php/8.3/fpm/pool.d/. Create a new file named after your site — for example example.com.conf:

# /etc/php/8.3/fpm/pool.d/example.com.conf
[example.com]
user = www-data
group = www-data
; Unique socket path for this site
listen = /run/php/php8.3-fpm-example.com.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
; Process manager settings
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 8
; Logging (optional but recommended)
access.log = /var/log/php/example.com.access.log
php_admin_value[error_log] = /var/log/php/example.com.error.log
php_admin_flag[log_errors] = on

Create the log directory and reload PHP-FPM to activate the new pool:

sudo mkdir -p /var/log/php
sudo chown www-data:www-data /var/log/php
sudo php-fpm8.3 --test # dry-run syntax check
sudo systemctl reload php8.3-fpm
# Confirm the socket was created
ls -la /run/php/php8.3-fpm-example.com.sock

If the --test flag returns OK: configuration file is valid and the socket file is present, the pool is ready to accept connections.

Point the Nginx Virtual Host to the New Pool

With the PHP-FPM pool running, the last configuration step is telling Nginx to pass PHP requests for this specific site to the new socket. Open the virtual host config for your site — typically located at /etc/nginx/sites-available/example.com — and locate the fastcgi_pass directive inside the PHP location block.

Change the fastcgi_pass value from the old socket to the new one you created in the previous step:

# Before (PHP 8.1 default pool)
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
# After (PHP 8.3 dedicated pool for this site)
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm-example.com.sock;
}

After saving the file, test the Nginx configuration for syntax errors before applying it. An invalid config that is reloaded without testing will take your site offline immediately.

sudo nginx -t
# Expected: nginx: configuration file /etc/nginx/nginx.conf test is successful
sudo systemctl reload nginx

At this point your site is being served through the PHP 8.3 pool. All other virtual hosts on the server continue using their existing PHP-FPM sockets completely unchanged — only the configuration for example.com was modified.

Verify the PHP Version Change

Never assume the change worked — always confirm the running PHP version from the browser or via the CLI. The fastest browser-side check is to create a temporary phpinfo.php file, load it, confirm the version, and then delete it immediately. Leaving phpinfo pages publicly accessible is a security risk.

# Create a temporary info file in the site root
echo '<?php phpinfo();' | sudo tee /var/www/example.com/public/phpinfo.php
# Visit https://example.com/phpinfo.php in your browser
# Confirm the "PHP Version" header shows 8.3.x
# Delete the file immediately after confirming
sudo rm /var/www/example.com/public/phpinfo.php

For a server-side check without touching the web root, use the PHP-FPM status page or simply inspect which socket Nginx is actually connecting to via the access log:

# Check that the new socket shows traffic
sudo tail -f /var/log/php/example.com.access.log
# Or confirm the PHP CLI version (note: CLI != FPM, but shows install)
php8.3 -v

Check the site's error log at /var/log/php/example.com.error.log for any extension-not-found or class-not-found errors. PHP version upgrades frequently expose code that relied on deprecated functions or extensions that need to be separately installed for the new version.

TIP

If you run WordPress, install the Health Check & Troubleshooting plugin before upgrading PHP versions. It lets you switch the PHP version in a private browser session only, so you can test compatibility without affecting live visitors — a workflow nearly identical to how CloudStick's EasyPHP handles per-site PHP switching in its dashboard.

Rollback and Troubleshooting

Because each site has its own fastcgi_pass line, rolling back a PHP version change is a two-minute operation: edit the virtual host to point back to the previous socket, test, and reload Nginx. You do not need to uninstall any PHP version or touch any other site.

# Rollback: revert fastcgi_pass and reload
sudo nano /etc/nginx/sites-available/example.com
# Change fastcgi_pass back to php8.1-fpm.sock
sudo nginx -t && sudo systemctl reload nginx

The most common issues you will encounter after a PHP version switch are missing extensions, deprecated function calls, and strict type errors introduced in newer PHP versions. Here is a quick diagnostic checklist:

  • 502 Bad Gateway — the PHP-FPM socket does not exist or the pool failed to start. Run systemctl status php8.3-fpm and check /var/log/php8.3-fpm.log.
  • PHP Fatal error: Call to undefined function — a required extension is not installed for the new PHP version. Install the missing package with apt install php8.3-<extension>.
  • Deprecated warnings flood the log — enable error_reporting = E_ALL & ~E_DEPRECATED temporarily in the pool config while you audit the codebase, then re-enable full reporting.
  • Permission denied on socket — verify that listen.owner and listen.group in the pool config match the user Nginx runs as (typically www-data).

Once you have confirmed the site is stable on the new PHP version, you can optionally remove the old PHP version entirely with apt purge php8.1* — but only after verifying no other site on the server still references its socket. As a rule, keep the old version installed for at least one full week of production traffic before purging it. The disk footprint of an unused PHP-FPM installation is minimal (roughly 30–50 MB), so there is no urgency to remove it immediately.

Leave a comment
Full Name
Email Address
Message
Contents