Installing and Setting up Multiple Concurrent PHP-FPM versions (7.4, 8.1, 8.2, 8.3) on Ubuntu 24.04 LTS using PPA
Prerequisites and System Preparation
This guide assumes you have a clean Ubuntu 24.04 LTS (Noble Numbat) server with root or sudo privileges. Before proceeding, ensure your system is up-to-date to avoid potential dependency conflicts.
Execute the following commands to update your package lists and upgrade existing packages:
sudo apt update && sudo apt upgrade -y
It’s also prudent to install essential build tools and utilities that might be required for compiling PHP extensions or other system-level tasks.
sudo apt install -y software-properties-common ca-certificates apt-transport-https gnupg2 curl wget lsb-release git build-essential autoconf pkg-config
Adding the Ondřej Surý PPA for PHP Versions
The most reliable and widely used method for installing multiple PHP versions on Debian/Ubuntu systems is by leveraging the Personal Package Archives (PPAs) maintained by Ondřej Surý. This PPA provides up-to-date and well-maintained packages for various PHP versions.
First, add the GPG key for the repository:
sudo wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
Next, add the PPA to your system’s sources list:
echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/php.list
Finally, update your package list again to fetch the new package information from the added PPA:
sudo apt update
Installing Multiple PHP-FPM Versions
With the PPA added and the package list refreshed, you can now install the desired PHP versions and their corresponding FPM (FastCGI Process Manager) packages. We will install PHP 7.4, 8.1, 8.2, and 8.3, along with their FPM components.
Execute the following command to install all specified versions:
sudo apt install -y php7.4 php7.4-fpm php8.1 php8.1-fpm php8.2 php8.2-fpm php8.3 php8.3-fpm
This command will install the core PHP binaries, the FPM service, and a set of common extensions for each version. You can install additional extensions as needed for each specific PHP version by prefixing the extension name with the version number (e.g., php8.3-mysql, php7.4-redis).
Verifying PHP-FPM Installations
After the installation, it’s crucial to verify that each PHP-FPM service is running correctly. Each version will have its own systemd service unit.
Check the status of each FPM service:
sudo systemctl status php7.4-fpm sudo systemctl status php8.1-fpm sudo systemctl status php8.2-fpm sudo systemctl status php8.3-fpm
You should see output indicating that each service is “active (running)”. If any service is not running, you can attempt to start it with sudo systemctl start phpX.Y-fpm and investigate logs using sudo journalctl -u phpX.Y-fpm.
You can also verify the installed PHP versions from the command line:
php7.4 -v php8.1 -v php8.2 -v php8.3 -v
Configuring Web Server (Nginx Example)
To utilize multiple PHP-FPM versions concurrently, your web server needs to be configured to route requests to the appropriate FPM pool based on the domain or specific URL path. This example demonstrates how to configure Nginx.
Each PHP-FPM version installs its own default configuration file, typically located at /etc/php/X.Y/fpm/pool.d/www.conf. The default listen socket for each version is usually a Unix socket (e.g., /run/php/php7.4-fpm.sock) or a TCP port (e.g., 127.0.0.1:9074 for PHP 7.4, 127.0.0.1:9081 for PHP 8.1, etc.). It’s good practice to use distinct ports or sockets for each FPM version.
Let’s assume you have two websites, site1.example.com running on PHP 8.3 and site2.example.com running on PHP 8.1. You would configure your Nginx virtual host files accordingly.
Nginx configuration for site1.example.com (PHP 8.3):
server {
listen 80;
server_name site1.example.com;
root /var/www/site1.example.com/public_html;
index index.php index.html index.htm;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# Use the PHP 8.3 FPM socket
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
# Alternatively, if using TCP:
# fastcgi_pass 127.0.0.1:9083;
}
# Other configurations for site1...
}
Nginx configuration for site2.example.com (PHP 8.1):
server {
listen 80;
server_name site2.example.com;
root /var/www/site2.example.com/public_html;
index index.php index.html index.htm;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# Use the PHP 8.1 FPM socket
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
# Alternatively, if using TCP:
# fastcgi_pass 127.0.0.1:9081;
}
# Other configurations for site2...
}
After creating or modifying your Nginx configuration files (typically in /etc/nginx/sites-available/ and symlinked to /etc/nginx/sites-enabled/), test the Nginx configuration and reload the service:
sudo nginx -t sudo systemctl reload nginx
Customizing PHP-FPM Pool Configurations
For production environments, it’s highly recommended to create custom pool configurations for each PHP-FPM version and website rather than relying solely on the default www.conf. This allows for fine-grained control over process management, resource limits, and security settings.
To create a custom pool for site1.example.com using PHP 8.3, you would typically:
- Copy the default pool configuration:
sudo cp /etc/php/8.3/fpm/pool.d/www.conf /etc/php/8.3/fpm/pool.d/site1.conf - Edit the new configuration file:
sudo nano /etc/php/8.3/fpm/pool.d/site1.conf
Within site1.conf, you would modify parameters such as:
; Unique prefix for the pool ; This is important when running multiple pools on the same server ; and can help avoid conflicts with process management and logging. ; For example, if you have multiple pools, you might name them: ; [site1_php83] ; [site2_php81] ; Set the user and group that will execute PHP scripts ; It's best practice to run each site with its own dedicated user for security. user = www-data-site1 group = www-data-site1 ; Set the listen socket. This MUST be unique for each pool. ; If using Unix sockets, ensure the directory exists and has correct permissions. listen = /run/php/php8.3-fpm-site1.sock ; Process manager settings (dynamic, static, ondemand) ; For production, 'dynamic' or 'ondemand' are common. ; Adjust pm.max_children, pm.start_servers, etc., based on server resources and expected load. pm = dynamic pm.max_children = 50 pm.start_servers = 5 pm.min_spare_servers = 5 pm.max_spare_servers = 10 pm.max_requests = 500 ; Request termination timeout request_terminate_timeout = 120s ; Set environment variables for this pool ; env[MY_APP_ENV] = production ; env[DATABASE_URL] = mysql://user:pass@host:port/db
After creating and editing the custom pool configuration, you must restart the corresponding PHP-FPM service:
sudo systemctl restart php8.3-fpm
And update your Nginx configuration to point to the new socket:
# In Nginx virtual host for site1.example.com
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm-site1.sock;
}
Remember to create the dedicated user and group (e.g., www-data-site1) and ensure the web server (Nginx) has appropriate permissions to access the socket file.
Managing Default PHP CLI Version
When you run a PHP command directly from the terminal (e.g., php artisan migrate), it will use the version that is currently aliased as the default php command. You can manage this default using the update-alternatives system.
List available PHP alternatives:
sudo update-alternatives --config php
This command will present a list of installed PHP executables, allowing you to select which one should be the default. For example:
There are 4 choices for the alternative php (providing /usr/bin/php). Selection Path Priority Status ------------------------------------------------------------ * 0 /usr/bin/php8.3 83 auto mode 1 /usr/bin/php7.4 74 manual mode 2 /usr/bin/php8.1 81 manual mode 3 /usr/bin/php8.2 82 manual mode 4 /usr/bin/php8.3 83 manual mode Press <enter> to keep the current choice[*], or type selection number:
Enter the number corresponding to your desired default CLI version and press Enter. This is crucial for ensuring that command-line scripts use the correct PHP environment.
Troubleshooting Common Issues
Permissions Denied on Socket: If Nginx cannot connect to the PHP-FPM socket, check file permissions. The user running Nginx (typically www-data) must have read/write access to the socket file and its parent directory (/run/php/). Ensure the PHP-FPM pool configuration correctly specifies the user/group and that these users/groups exist and have appropriate permissions.
PHP Version Mismatch: Double-check that your Nginx configuration correctly points to the socket or port of the intended PHP-FPM version. Verify the fastcgi_pass directive. Also, ensure the CLI version set via update-alternatives matches your development expectations.
FPM Service Not Starting: Examine the systemd journal for detailed error messages: sudo journalctl -u phpX.Y-fpm. Common causes include syntax errors in pool configuration files, incorrect user/group settings, or port conflicts.
Missing Extensions: If your application encounters errors related to missing PHP extensions (e.g., Call to undefined function json_encode()), you need to install the corresponding extension for the specific PHP version. For example, to install the MySQL extension for PHP 8.3: sudo apt install php8.3-mysql. Remember to restart the relevant PHP-FPM service after installing new extensions.
By following these steps, you can establish a robust and flexible PHP environment on Ubuntu 24.04 LTS, capable of serving multiple applications with different PHP version requirements concurrently and efficiently.
Leave a Reply
You must be logged in to post a comment.