Multiple PHP Versions Configuration: Complete Production Guide
Introduction
Running multiple PHP versions simultaneously on a single server is a common requirement in modern web hosting environments. Different applications often require different PHP versions - legacy applications may need PHP 7.4, while newer projects might require PHP 8.1 or 8.2. This guide provides comprehensive instructions for configuring multiple PHP versions side-by-side, allowing you to serve different applications with their optimal PHP version.
What You'll Learn
- Installing multiple PHP versions on Ubuntu/Debian and CentOS/Rocky Linux
- Configuring PHP-FPM pools for different PHP versions
- Switching between PHP versions per virtual host in Nginx
- Switching between PHP versions per virtual host in Apache
- Managing PHP configurations across versions
- Command-line PHP version switching
- Performance optimization for multiple PHP versions
- Troubleshooting common issues
Use Cases
- Hosting multiple client websites with different PHP requirements
- Migrating applications between PHP versions gradually
- Testing applications against newer PHP versions before production upgrade
- Supporting both legacy and modern applications on the same server
- Development environments requiring multiple PHP versions
Prerequisites
- Ubuntu 20.04/22.04, Debian 10/11, CentOS 8, or Rocky Linux 8/9
- Root or sudo access
- Web server installed (Nginx or Apache)
- At least 2GB RAM (4GB+ recommended for production)
- Basic understanding of PHP and web server configuration
Installation
Ubuntu/Debian: Installing Multiple PHP Versions
Step 1: Add Ondřej Surý's PHP Repository
# Install software-properties-common
sudo apt install -y software-properties-common
# Add Ondřej's PHP repository
sudo add-apt-repository ppa:ondrej/php -y
# Update package list
sudo apt update
Step 2: Install Multiple PHP Versions
# Install PHP 7.4 and PHP 8.1 and PHP 8.2 with common extensions
sudo apt install -y \
php7.4 php7.4-fpm php7.4-cli php7.4-common php7.4-mysql php7.4-xml \
php7.4-curl php7.4-gd php7.4-mbstring php7.4-zip php7.4-bcmath \
php7.4-json php7.4-opcache php7.4-readline \
php8.1 php8.1-fpm php8.1-cli php8.1-common php8.1-mysql php8.1-xml \
php8.1-curl php8.1-gd php8.1-mbstring php8.1-zip php8.1-bcmath \
php8.1-opcache php8.1-readline \
php8.2 php8.2-fpm php8.2-cli php8.2-common php8.2-mysql php8.2-xml \
php8.2-curl php8.2-gd php8.2-mbstring php8.2-zip php8.2-bcmath \
php8.2-opcache php8.2-readline
# Enable all PHP-FPM services
sudo systemctl enable php7.4-fpm
sudo systemctl enable php8.1-fpm
sudo systemctl enable php8.2-fpm
# Start all PHP-FPM services
sudo systemctl start php7.4-fpm
sudo systemctl start php8.1-fpm
sudo systemctl start php8.2-fpm
# Verify all services are running
sudo systemctl status php7.4-fpm
sudo systemctl status php8.1-fpm
sudo systemctl status php8.2-fpm
Step 3: Verify Installations
# Check installed PHP versions
php7.4 -v
php8.1 -v
php8.2 -v
# Check socket locations
ls -la /var/run/php/
# You should see php7.4-fpm.sock, php8.1-fpm.sock, php8.2-fpm.sock
# Verify PHP-FPM is listening
sudo ss -pl | grep php
CentOS/Rocky Linux: Installing Multiple PHP Versions
Step 1: Install Remi Repository
# Install EPEL repository
sudo dnf install -y epel-release
# Install Remi repository
sudo dnf install -y https://rpms.remirepo.net/enterprise/remi-release-8.rpm
# List available PHP versions
sudo dnf module list php
Step 2: Install Multiple PHP Versions
# Install PHP 7.4
sudo dnf module reset php -y
sudo dnf module enable php:remi-7.4 -y
sudo dnf install -y php php-fpm php-mysqlnd php-gd php-xml php-mbstring php-opcache php-cli php-zip php-curl
# Rename PHP 7.4 binaries
sudo cp /usr/bin/php /usr/bin/php7.4
sudo cp /usr/sbin/php-fpm /usr/sbin/php7.4-fpm
# Install PHP 8.1
sudo dnf module reset php -y
sudo dnf module enable php:remi-8.1 -y
sudo dnf install -y php php-fpm php-mysqlnd php-gd php-xml php-mbstring php-opcache php-cli php-zip php-curl
# Rename PHP 8.1 binaries
sudo cp /usr/bin/php /usr/bin/php8.1
sudo cp /usr/sbin/php-fpm /usr/sbin/php8.1-fpm
# Note: CentOS/Rocky typically uses alternatives system for PHP version management
sudo alternatives --config php
Note: Managing multiple PHP versions on CentOS/Rocky is more complex. Consider using containers or dedicated servers for simpler management. This guide focuses primarily on Ubuntu/Debian for multiple PHP versions.
Configuration
Configure PHP-FPM Pools for Each Version
Each PHP version needs its own socket or port configuration.
PHP 7.4 Pool Configuration
# Edit PHP 7.4 pool configuration
sudo vim /etc/php/7.4/fpm/pool.d/www.conf
# Key settings:
[www]
user = www-data
group = www-data
listen = /var/run/php/php7.4-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
# Process manager settings
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500
PHP 8.1 Pool Configuration
# Edit PHP 8.1 pool configuration
sudo vim /etc/php/8.1/fpm/pool.d/www.conf
# Key settings:
[www]
user = www-data
group = www-data
listen = /var/run/php/php8.1-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
# Process manager settings
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500
PHP 8.2 Pool Configuration
# Edit PHP 8.2 pool configuration
sudo vim /etc/php/8.2/fpm/pool.d/www.conf
# Same configuration as above
# Key settings:
[www]
user = www-data
group = www-data
listen = /var/run/php/php8.2-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
# Process manager settings
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500
Restart All PHP-FPM Services
sudo systemctl restart php7.4-fpm
sudo systemctl restart php8.1-fpm
sudo systemctl restart php8.2-fpm
Nginx Configuration for Multiple PHP Versions
Configure different websites to use different PHP versions.
Site Using PHP 7.4
# Create configuration for legacy site
sudo bash -c 'cat > /etc/nginx/sites-available/legacy-site.com <<EOF
server {
listen 80;
server_name legacy-site.com www.legacy-site.com;
root /var/www/legacy-site.com/html;
index index.php index.html;
access_log /var/log/nginx/legacy-site-access.log;
error_log /var/log/nginx/legacy-site-error.log;
location / {
try_files \$uri \$uri/ /index.php?\$args;
}
# PHP 7.4 processing
location ~ \.php\$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
# Add header to show PHP version (optional, for testing)
add_header X-PHP-Version "7.4" always;
}
EOF'
# Enable site
sudo ln -s /etc/nginx/sites-available/legacy-site.com /etc/nginx/sites-enabled/
Site Using PHP 8.1
# Create configuration for modern site
sudo bash -c 'cat > /etc/nginx/sites-available/modern-site.com <<EOF
server {
listen 80;
server_name modern-site.com www.modern-site.com;
root /var/www/modern-site.com/html;
index index.php index.html;
access_log /var/log/nginx/modern-site-access.log;
error_log /var/log/nginx/modern-site-error.log;
location / {
try_files \$uri \$uri/ /index.php?\$args;
}
# PHP 8.1 processing
location ~ \.php\$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
# Add header to show PHP version (optional, for testing)
add_header X-PHP-Version "8.1" always;
}
EOF'
# Enable site
sudo ln -s /etc/nginx/sites-available/modern-site.com /etc/nginx/sites-enabled/
Site Using PHP 8.2
# Create configuration for newest site
sudo bash -c 'cat > /etc/nginx/sites-available/new-site.com <<EOF
server {
listen 80;
server_name new-site.com www.new-site.com;
root /var/www/new-site.com/html;
index index.php index.html;
access_log /var/log/nginx/new-site-access.log;
error_log /var/log/nginx/new-site-error.log;
location / {
try_files \$uri \$uri/ /index.php?\$args;
}
# PHP 8.2 processing
location ~ \.php\$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
# Add header to show PHP version (optional, for testing)
add_header X-PHP-Version "8.2" always;
}
EOF'
# Enable site
sudo ln -s /etc/nginx/sites-available/new-site.com /etc/nginx/sites-enabled/
Test and Reload Nginx
# Test configuration
sudo nginx -t
# Reload Nginx
sudo systemctl reload nginx
Apache Configuration for Multiple PHP Versions
If you're using Apache instead of Nginx:
Enable Required Apache Modules
# Enable proxy modules
sudo a2enmod proxy_fcgi setenvif rewrite
# Disable mod_php (if installed)
sudo a2dismod php7.4 php8.1 php8.2
# Restart Apache
sudo systemctl restart apache2
Site Using PHP 7.4 (Apache)
# Create virtual host
sudo bash -c 'cat > /etc/apache2/sites-available/legacy-site.com.conf <<EOF
<VirtualHost *:80>
ServerName legacy-site.com
ServerAlias www.legacy-site.com
DocumentRoot /var/www/legacy-site.com/html
<Directory /var/www/legacy-site.com/html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# PHP 7.4 via PHP-FPM
<FilesMatch \.php\$>
SetHandler "proxy:unix:/var/run/php/php7.4-fpm.sock|fcgi://localhost"
</FilesMatch>
ErrorLog \${APACHE_LOG_DIR}/legacy-site-error.log
CustomLog \${APACHE_LOG_DIR}/legacy-site-access.log combined
</VirtualHost>
EOF'
# Enable site
sudo a2ensite legacy-site.com.conf
Site Using PHP 8.1 (Apache)
# Create virtual host
sudo bash -c 'cat > /etc/apache2/sites-available/modern-site.com.conf <<EOF
<VirtualHost *:80>
ServerName modern-site.com
ServerAlias www.modern-site.com
DocumentRoot /var/www/modern-site.com/html
<Directory /var/www/modern-site.com/html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
# PHP 8.1 via PHP-FPM
<FilesMatch \.php\$>
SetHandler "proxy:unix:/var/run/php/php8.1-fpm.sock|fcgi://localhost"
</FilesMatch>
ErrorLog \${APACHE_LOG_DIR}/modern-site-error.log
CustomLog \${APACHE_LOG_DIR}/modern-site-access.log combined
</VirtualHost>
EOF'
# Enable site
sudo a2ensite modern-site.com.conf
Reload Apache
# Test configuration
sudo apache2ctl configtest
# Reload Apache
sudo systemctl reload apache2
Command Line PHP Version Switching
Switch the default PHP CLI version using update-alternatives:
# View available PHP versions
sudo update-alternatives --display php
# Set PHP 7.4 as default
sudo update-alternatives --set php /usr/bin/php7.4
# Set PHP 8.1 as default
sudo update-alternatives --set php /usr/bin/php8.1
# Set PHP 8.2 as default
sudo update-alternatives --set php /usr/bin/php8.2
# Interactive selection
sudo update-alternatives --config php
# Verify current version
php -v
Deployment
Test PHP Versions
Create test files for each site to verify PHP versions:
# Create test file for PHP 7.4 site
sudo bash -c 'cat > /var/www/legacy-site.com/html/phpinfo.php <<EOF
<?php
echo "<h1>PHP Version Info</h1>";
echo "PHP Version: " . phpversion() . "<br>";
echo "Server API: " . php_sapi_name() . "<br>";
phpinfo();
?>
EOF'
# Create test file for PHP 8.1 site
sudo bash -c 'cat > /var/www/modern-site.com/html/phpinfo.php <<EOF
<?php
echo "<h1>PHP Version Info</h1>";
echo "PHP Version: " . phpversion() . "<br>";
echo "Server API: " . php_sapi_name() . "<br>";
phpinfo();
?>
EOF'
# Create test file for PHP 8.2 site
sudo bash -c 'cat > /var/www/new-site.com/html/phpinfo.php <<EOF
<?php
echo "<h1>PHP Version Info</h1>";
echo "PHP Version: " . phpversion() . "<br>";
echo "Server API: " . php_sapi_name() . "<br>";
phpinfo();
?>
EOF'
Access these files in your browser:
http://legacy-site.com/phpinfo.php(should show PHP 7.4)http://modern-site.com/phpinfo.php(should show PHP 8.1)http://new-site.com/phpinfo.php(should show PHP 8.2)
Important: Delete these test files after verification for security:
sudo rm /var/www/*/html/phpinfo.php
Migrating Applications Between PHP Versions
When migrating an application to a newer PHP version:
Step 1: Create Test Environment
# Copy application to test directory
sudo cp -r /var/www/production-site.com /var/www/test-site.com
# Create test virtual host with new PHP version
# Point to new PHP-FPM socket
Step 2: Check Compatibility
# Run PHP compatibility checker
cd /var/www/test-site.com
composer require --dev phpcompatibility/php-compatibility
# Check for PHP 8.1 compatibility
vendor/bin/phpcs --standard=PHPCompatibility --runtime-set testVersion 8.1 /path/to/code
Step 3: Fix Deprecated Code
Common issues when upgrading:
- PHP 8.0+: Named arguments, match expressions
- PHP 8.1: Enums, readonly properties, fibers
- Deprecated functions and features
Step 4: Test Thoroughly
# Run application test suite
vendor/bin/phpunit
# Manual testing
# Browse site thoroughly
Step 5: Switch Production
# Update production virtual host to use new PHP version
sudo vim /etc/nginx/sites-available/production-site.com
# Change from:
# fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
# To:
# fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
# Reload web server
sudo systemctl reload nginx
Monitoring
Monitor All PHP-FPM Versions
# Check status of all PHP-FPM services
sudo systemctl status php7.4-fpm php8.1-fpm php8.2-fpm
# Monitor active processes
ps aux | grep php-fpm
# Check memory usage per version
ps aux | grep php7.4-fpm | awk '{sum+=$6} END {print "PHP 7.4 Memory: " sum/1024 " MB"}'
ps aux | grep php8.1-fpm | awk '{sum+=$6} END {print "PHP 8.1 Memory: " sum/1024 " MB"}'
ps aux | grep php8.2-fpm | awk '{sum+=$6} END {print "PHP 8.2 Memory: " sum/1024 " MB"}'
# Monitor logs
sudo tail -f /var/log/php7.4-fpm.log
sudo tail -f /var/log/php8.1-fpm.log
sudo tail -f /var/log/php8.2-fpm.log
Monitoring Script
sudo bash -c 'cat > /usr/local/bin/php-versions-monitor.sh <<'EOF'
#!/bin/bash
echo "======================================"
echo " PHP Versions Monitoring Report"
echo " $(date)"
echo "======================================"
echo ""
echo "=== PHP-FPM Services Status ==="
for version in 7.4 8.1 8.2; do
if systemctl is-active --quiet php${version}-fpm; then
echo "PHP ${version}-FPM: RUNNING"
processes=$(ps aux | grep php${version}-fpm | grep -v grep | wc -l)
echo " Active processes: $processes"
else
echo "PHP ${version}-FPM: STOPPED"
fi
done
echo ""
echo "=== Memory Usage ==="
for version in 7.4 8.1 8.2; do
mem=$(ps aux | grep php${version}-fpm | grep -v grep | awk '{sum+=$6} END {print sum/1024}')
if [ ! -z "$mem" ]; then
printf "PHP %s Memory: %.2f MB\n" "$version" "$mem"
fi
done
echo ""
echo "=== Socket Status ==="
ls -lah /var/run/php/ | grep sock
echo ""
echo "======================================"
EOF'
sudo chmod +x /usr/local/bin/php-versions-monitor.sh
# Run monitoring script
sudo /usr/local/bin/php-versions-monitor.sh
Troubleshooting
PHP Version Not Working
Issue: Website showing wrong PHP version or not processing PHP
Solutions:
- Check PHP-FPM service is running:
sudo systemctl status php7.4-fpm
sudo systemctl start php7.4-fpm
- Verify socket exists:
ls -la /var/run/php/php7.4-fpm.sock
- Check Nginx/Apache configuration:
# Nginx
sudo nginx -t
grep -r "php7.4-fpm.sock" /etc/nginx/sites-enabled/
# Apache
sudo apache2ctl configtest
grep -r "php7.4-fpm.sock" /etc/apache2/sites-enabled/
- Check socket permissions:
sudo chmod 666 /var/run/php/php7.4-fpm.sock
502 Bad Gateway Error
Issue: Nginx returns 502 error when accessing PHP pages
Solutions:
- Check PHP-FPM is running:
sudo systemctl restart php8.1-fpm
sudo systemctl status php8.1-fpm
- Check PHP-FPM error log:
sudo tail -50 /var/log/php8.1-fpm.log
- Verify socket path matches in both configs:
# Check PHP-FPM pool config
grep "listen = " /etc/php/8.1/fpm/pool.d/www.conf
# Check Nginx config
grep "fastcgi_pass" /etc/nginx/sites-enabled/your-site.com
- Increase PHP-FPM processes:
# Edit pool configuration
sudo vim /etc/php/8.1/fpm/pool.d/www.conf
# Increase max_children
pm.max_children = 50
sudo systemctl restart php8.1-fpm
Memory Issues with Multiple PHP Versions
Issue: Server running out of memory with multiple PHP-FPM versions
Solutions:
- Reduce processes per pool:
# Edit each pool configuration
pm = dynamic
pm.max_children = 10
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 5
- Use ondemand process manager:
pm = ondemand
pm.max_children = 15
pm.process_idle_timeout = 10s
- Disable unused PHP versions:
# Stop and disable PHP version not in use
sudo systemctl stop php7.4-fpm
sudo systemctl disable php7.4-fpm
Composer Using Wrong PHP Version
Issue: Composer uses wrong PHP version
Solutions:
- Specify PHP binary explicitly:
php8.1 /usr/local/bin/composer install
- Use update-alternatives:
sudo update-alternatives --set php /usr/bin/php8.1
composer install
- Set PHP version in composer.json:
{
"config": {
"platform": {
"php": "8.1.0"
}
}
}
Extension Not Available in Specific PHP Version
Issue: Extension works in one PHP version but not another
Solution:
# Check available extensions for each version
php7.4 -m
php8.1 -m
php8.2 -m
# Install missing extension
sudo apt install php8.1-extension-name
# Restart PHP-FPM
sudo systemctl restart php8.1-fpm
Security Best Practices
Per-Site User Isolation
Configure different pools with different users:
# Create dedicated user for site
sudo useradd -r -s /bin/false site1user
# Create dedicated pool
sudo bash -c 'cat > /etc/php/8.1/fpm/pool.d/site1.conf <<EOF
[site1]
user = site1user
group = site1user
listen = /var/run/php/php8.1-site1-fpm.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 10
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 5
php_admin_value[open_basedir] = /var/www/site1:/tmp
php_admin_value[disable_functions] = exec,passthru,shell_exec,system
EOF'
# Set ownership
sudo chown -R site1user:site1user /var/www/site1
# Restart PHP-FPM
sudo systemctl restart php8.1-fpm
Disable Dangerous Functions
# Edit php.ini for each version
sudo vim /etc/php/8.1/fpm/php.ini
# Add:
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
Update Regularly
# Update all PHP versions
sudo apt update
sudo apt upgrade php* -y
# Restart all PHP-FPM services
sudo systemctl restart php7.4-fpm php8.1-fpm php8.2-fpm
Performance Optimization
OPcache Configuration
Configure OPcache for each PHP version:
# Edit OPcache settings
sudo vim /etc/php/8.1/mods-available/opcache.ini
# Recommended settings:
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.revalidate_freq=60
opcache.fast_shutdown=1
opcache.enable_cli=0
Resource Allocation Strategy
Allocate resources based on usage:
# High-traffic site (PHP 8.1)
pm.max_children = 50
pm.start_servers = 10
# Low-traffic legacy site (PHP 7.4)
pm.max_children = 10
pm.start_servers = 3
# Staging site (PHP 8.2)
pm = ondemand
pm.max_children = 5
Conclusion
You've successfully configured multiple PHP versions on your server, enabling you to run legacy and modern applications side-by-side. This setup provides flexibility, easier migrations, and better resource management.
Key Takeaways
- Multiple PHP versions can coexist using separate PHP-FPM pools
- Each site can use its own PHP version via different sockets
- Command-line PHP version can be switched using update-alternatives
- Proper resource allocation prevents memory issues
- Per-site user isolation improves security
Best Practices
- Monitor Resource Usage: Keep track of memory and CPU for each PHP version
- Plan Migration Path: Gradually migrate applications to newer PHP versions
- Test Thoroughly: Always test in staging before production changes
- Keep Updated: Regularly update all PHP versions for security
- Document Configuration: Maintain documentation of which sites use which PHP version
Next Steps
- Set up automated monitoring for all PHP-FPM instances
- Create migration checklist for PHP version upgrades
- Implement automated testing for PHP compatibility
- Configure centralized logging
- Plan end-of-life strategy for older PHP versions
Running multiple PHP versions provides the flexibility needed in modern hosting environments while maintaining compatibility with legacy applications.
Happy deploying!


