2026年11月12日

2026年11月12日

Run Multiple PHP Versions on a VPS (Per-Site PHP-FPM)

This article is a localized edition of the Japanese original. Read the Japanese original

When you run several sites on one VPS, you may want new sites on a newer PHP while an older site only works on an older version. With PHP-FPM, each version runs as its own process, and the web server configuration chooses which version each site uses.

This article shows how to install PHP 8.2 and 8.4 on an Ubuntu 24.04 VPS and route each site to a version with Nginx or Apache (as of October 2026; the steps were tested in an Ubuntu 24.04 container).

Things to know first

How the routing works

  • PHP-FPM runs as a separate service for each version (php8.2-fpm, php8.4-fpm), and each listens on its own socket (/run/php/php8.2-fpm.sock and so on).
  • For each site, the web server is configured with the socket it should pass PHP requests to. That is how site A runs on 8.2 and site B on 8.4.
  • The command-line php (used by WP-CLI and cron) is switched separately from the web server.

Splitting versions by file extension (such as .php81) or switching with phpenv, a development tool, is not suitable for production websites.

Support periods for each PHP version

According to the official PHP site (Supported Versions on php.net), the support periods as of October 2026 are as follows.

Version Security fixes until
PHP 8.2 December 31, 2026
PHP 8.3 December 31, 2027
PHP 8.4 December 31, 2028
PHP 8.5 December 31, 2029

WordPress recommends PHP 8.3 or later (wordpress.org requirements page, as of October 2026). Treat running an old version alongside as a bridge until the old site moves to a newer version, and migrate before support ends.

Step 1: Install multiple PHP versions

Ubuntu 24.04's standard repositories include only PHP 8.3. Other versions are usually installed from the packages (PPA) distributed by Ondřej Surý. Use it with the understanding that it is an external repository, not an official Ubuntu one.

sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository ppa:ondrej/php
sudo apt update

On Debian, use packages.sury.org from the same maintainer. The setup steps are in https://packages.sury.org/php/README.txt. Note that, as of October 2026, the PPA page says the PPA is being merged into packages.sury.org, so check the current guidance when you set it up.

Install PHP-FPM for each version you need, plus the extensions WordPress commonly uses. Extensions must be installed separately for each version.

# PHP 8.4 (for new sites)
sudo apt install php8.4-fpm php8.4-mysql php8.4-curl php8.4-gd php8.4-intl \
  php8.4-mbstring php8.4-xml php8.4-zip

# PHP 8.2 (for old sites)
sudo apt install php8.2-fpm php8.2-mysql php8.2-curl php8.2-gd php8.2-intl \
  php8.2-mbstring php8.2-xml php8.2-zip

Confirm that both PHP-FPM services are running and their sockets exist.

systemctl status php8.2-fpm php8.4-fpm --no-pager
ls /run/php/
# Shows php8.2-fpm.sock, php8.4-fpm.sock, etc.

Configuration files are also separate per version (/etc/php/8.2/fpm/php.ini, /etc/php/8.4/fpm/php.ini, and so on). To change upload_max_filesize or memory_limit, edit the file for the version the site uses and restart that version's PHP-FPM.

Step 2a: Choose the version per site in Nginx

In Nginx, put the socket of the version you want in fastcgi_pass in each site's server block.

# /etc/nginx/sites-available/old.example.com (site running on PHP 8.2)
server {
    listen 80;
    server_name old.example.com;
    root /var/www/old;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    }
}

For a site on PHP 8.4, use fastcgi_pass unix:/run/php/php8.4-fpm.sock;. Enable the configuration, check the syntax, then reload.

sudo ln -s /etc/nginx/sites-available/old.example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Step 2b: Choose the version per site in Apache

In Apache, enable the modules that pass requests to PHP-FPM instead of mod_php, and specify the socket with SetHandler in each VirtualHost.

sudo a2enmod proxy_fcgi setenvif
# /etc/apache2/sites-available/old.example.com.conf (site running on PHP 8.2)
<VirtualHost *:80>
    ServerName old.example.com
    DocumentRoot /var/www/old

    <FilesMatch "\.php$">
        SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
    </FilesMatch>
</VirtualHost>

For a site on PHP 8.4, set the socket to /run/php/php8.4-fpm.sock. Enable the configuration, check the syntax, then reload.

sudo a2ensite old.example.com
sudo apache2ctl configtest
sudo systemctl reload apache2
  • Running a2enconf php8.4-fpm sets the server-wide default version. Sites with SetHandler inside their VirtualHost use that setting instead.
  • If libapache2-mod-php8.x (mod_php) is installed and enabled, requests may not reach PHP-FPM. Disable it, for example with a2dismod php8.3.

Step 3 (optional): Separate PHP-FPM pools per site

With the default www pool, every site runs as the same user (www-data). To run each site as its own user, add a pool.

; /etc/php/8.2/fpm/pool.d/oldsite.conf
[oldsite]
user = oldsite
group = oldsite
listen = /run/php/php8.2-oldsite.sock
listen.owner = www-data
listen.group = www-data
pm = ondemand
pm.max_children = 5

Create the oldsite user (sudo useradd -r oldsite) and make the site's files readable by that user. Then check the configuration with sudo php-fpm8.2 -t and apply it with sudo systemctl restart php8.2-fpm. Change the socket in the web server configuration to /run/php/php8.2-oldsite.sock.

Step 4: Versions for command-line php and WP-CLI

Which version the command-line php points to is decided by update-alternatives.

# List installed versions
update-alternatives --list php

# Make 8.4 the default php
sudo update-alternatives --set php /usr/bin/php8.4
php -v

# Run a specific version
php8.2 -v

To run WP-CLI (installed at /usr/local/bin/wp) with a specific version, run it through that version's php.

cd /var/www/old
php8.2 /usr/local/bin/wp core version

If cron runs WordPress commands or PHP scripts, write the version explicitly, such as php8.2, so changing the default version does not affect them.

Step 5: Check each site’s version

In the WordPress admin area, open "Site Health" under "Tools" (Tools → Site Health), go to the "Info" tab, and check the PHP version in the "Server" section. Confirm that each site runs on the version you intended.

If something does not work, check the following:

  • 502 Bad Gateway (Nginx) or 503 Service Unavailable (Apache): whether the socket path is correct and that version's PHP-FPM is running (ls /run/php/, systemctl status php8.2-fpm)
  • WordPress reports that the MySQL extension is unavailable, or images cannot be processed: whether you installed that version's extensions (for example php8.2-mysql, php8.2-gd)
  • PHP-FPM error log: /var/log/php8.2-fpm.log and similar

Removing old versions

After moving old sites to a newer version, remove the version you no longer use. First confirm that no site uses that version's socket.

grep -rn "php8.2" /etc/nginx/ /etc/apache2/ 2>/dev/null
sudo apt purge 'php8.2-*'
sudo apt autoremove

Summary

  • With several PHP-FPM versions installed, each version runs as its own service with its own socket
  • Specify the socket (version) per site with fastcgi_pass in Nginx or SetHandler inside the VirtualHost in Apache
  • Extensions and php.ini are separate per version. After changing settings, restart that version's PHP-FPM
  • Set the default command-line version with update-alternatives, and name the version explicitly, such as php8.2, for WP-CLI and cron
  • Security fixes for PHP 8.2 end on December 31, 2026. Use an old version alongside only as a bridge until migration

Related articles

Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲