Nginx does not care which PHP version runs a site. It sends PHP requests to whatever socket the server block names in fastcgi_pass. So once several PHP-FPM versions are installed, choosing a version per site is a one-line change. This guide sets that up, adds a dedicated pool per site for cleaner separation, and shows a safe way to confirm which version each site uses.
Before you start
- A Linux VPS with Nginx and at least two PHP-FPM versions installed. On Ubuntu or Debian, follow Install multiple PHP versions on Ubuntu and Debian.
- Two sites with their own server blocks, for example
old.example.comandnew.example.com. If you have not split your sites yet, see Host multiple websites with Nginx server blocks. - A sudo user.
Paths below use Ubuntu and Debian. On AlmaLinux or Rocky Linux with Remi, extra versions have sockets like /var/opt/remi/php82/run/php-fpm/www.sock and pool files in /etc/opt/remi/php82/php-fpm.d/.
See which sockets you have
Each running PHP-FPM version creates its own socket:
ls -l /run/php/php8.2-fpm.sock
php8.4-fpm.sockIf a version is missing, start its service:
sudo systemctl enable --now php8.2-fpmPoint each server block at a socket
Open the first site's config:
sudo nano /etc/nginx/sites-available/old.example.comIn the PHP location, set fastcgi_pass to the PHP 8.2 socket:
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}Do the same for the second site, using PHP 8.4:
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
}The snippets/fastcgi-php.conf file ships with the Debian and Ubuntu Nginx packages. It sets SCRIPT_FILENAME and checks the file exists. Test and reload:
sudo nginx -t && sudo systemctl reload nginxThat is enough to run the two sites on different versions. The next section makes the setup cleaner.
Give each site its own pool
With the steps above, every site on the same version shares the default www pool. A dedicated pool per site lets you set separate worker limits, PHP settings and error logs, and later a separate Linux user.
Create a pool for new.example.com under PHP 8.4:
sudo nano /etc/php/8.4/fpm/pool.d/new.example.com.conf[new.example.com]
user = www-data
group = www-data
listen = /run/php/php8.4-fpm-new.example.com.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
php_admin_value[error_log] = /var/log/php/new.example.com-error.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 256MCreate the log folder, check the config and restart that version:
sudo mkdir -p /var/log/php
sudo chown www-data:www-data /var/log/php
sudo php-fpm8.4 -t
sudo systemctl restart php8.4-fpmThen point the site at the new socket:
fastcgi_pass unix:/run/php/php8.4-fpm-new.example.com.sock;sudo nginx -t && sudo systemctl reload nginxThe pm.max_children value above is a placeholder. Work out the right number for your RAM with Tune PHP-FPM pools (pm.max_children). To also run each site as its own Linux user, see Run each site in its own PHP-FPM pool and user.
Tip: Name sockets after the site and version. When you move a site to a newer PHP later, you copy its pool file to the new version's pool.d, rename the socket and update one fastcgi_pass line.
Use an upstream name for easier switching
If many server blocks share a version, define the sockets once in /etc/nginx/conf.d/php-upstreams.conf:
upstream php82 {
server unix:/run/php/php8.2-fpm.sock;
}
upstream php84 {
server unix:/run/php/php8.4-fpm.sock;
}Then each site uses a short name:
fastcgi_pass php84;Moving every PHP 8.2 site to a new socket is then a single edit.
Check the version safely
The quickest check is a tiny file that prints only the version, not the full phpinfo page, which reveals paths and settings useful to attackers. Use a hard-to-guess name and delete it straight after:
echo '<?php echo PHP_VERSION;' | sudo tee /var/www/new.example.com/v-7f3a.php
curl -s https://new.example.com/v-7f3a.php; echo
sudo rm /var/www/new.example.com/v-7f3a.phpThe output should be 8.4.x. Repeat for the other site and expect 8.2.x.
You can also confirm from the server side which pools are active:
ps -o user,cmd -C php-fpm8.4 | grep poolEach line shows the pool name and the user it runs as.
Troubleshooting
- 502 Bad Gateway: the socket in
fastcgi_passdoes not exist. Checkls /run/php/and that the PHP-FPM service for that version is running.sudo tail /var/log/nginx/error.logshows the exact path Nginx tried. - Site still shows the old version: you edited a file in
sites-availablethat is not linked insites-enabled, or you forgot to reload Nginx. - "Permission denied" connecting to the socket:
listen.ownerandlisten.groupin the pool must allow the Nginx user (www-dataon Ubuntu and Debian,nginxon AlmaLinux and Rocky). - PHP-FPM fails to restart after adding a pool: two pools use the same socket path or pool name. Run
php-fpm8.4 -tto see the error line.
Next steps
- Upgrade a site to a newer version once it is tested: Upgrade PHP to a newer version on your VPS.
- Running many sites with different needs? A bigger Linux VPS gives each pool room.
