How to Use Separate PHP-FPM Pools for Hosting Multiple Sites on Nginx

As modern server hardware becomes increasingly powerful and resource-efficient, hosting multiple sites on a single Nginx instance has become a practical standard. For improved speed, better isolation, and enhanced security, it’s wise to assign individual PHP-FPM pools to each site. This guide walks you through setting up distinct PHP-FPM pools on an Ubuntu 20.04 LTS cloud server with PHP 7.4 and Nginx, allowing multiple virtual hosts to run on a single system.

Prerequisites

  • Establish a sudo-enabled user without root privileges.
  • Ensure your Ubuntu system is fully updated.
  • Install a complete LEMP stack on Ubuntu 20.04 LTS.
  • Create two “A” DNS records pointing to the same IP address, but with different hostnames — for example, site1.example.com and site2.example.com.

1. Delete the Default Nginx Site

Nginx ships with a default virtual host, which is unnecessary for our setup. Remove it by logging in as your sudo user and executing:

$ sudo rm /etc/nginx/sites-enabled/default

2. Set Up Dedicated Site Users

To enforce security boundaries, assign each site its own Unix user. These users should be isolated and without login rights. You’ll also add the web server user to each group:

$ sudo useradd site1
$ sudo useradd site2
$ usermod -a -G site1 www-data
$ usermod -a -G site2 www-data

3. Define Folder Permissions

Create directories for both websites and restrict access accordingly to prevent cross-site access:

$ sudo mkdir /var/www/site1
$ sudo chown -R site1:site1 /var/www/site1
$ sudo mkdir /var/www/site2
$ sudo chown -R site2:site2 /var/www/site2
$ sudo chmod 770 /var/www/site2

These permissions (770) give full access to the owner and group but restrict all others, ensuring separation between the two environments.

4. Duplicate the PHP-FPM Configuration

Use the default pool as a base and copy it for each individual site. Then, eliminate the original:

$ sudo cp /etc/php/7.4/fpm/pool.d/www.conf /etc/php/7.4/fpm/pool.d/fpm-site1.conf
$ sudo cp /etc/php/7.4/fpm/pool.d/www.conf /etc/php/7.4/fpm/pool.d/fpm-site2.conf
$ sudo rm /etc/php/7.4/fpm/pool.d/www.conf

5. Customize the First PHP-FPM Pool

Edit the configuration file for site1’s pool and modify these four parameters:

$ sudo nano /etc/php/7.4/fpm/pool.d/fpm-site1.conf

  • Change [www] to [site1].
  • Update user = www-data to user = site1.
  • Update group = www-data to group = site1.
  • Replace listen = /var/run/php/php7.4-fpm.sock with listen = /var/run/php/php7.4-site1-fpm.sock.

6. Customize the Second PHP-FPM Pool

Repeat the editing steps for site2’s pool configuration:

$ sudo nano /etc/php/7.4/fpm/pool.d/fpm-site2.conf

  • Change [www] to [site2].
  • Update user = www-data to user = site2.
  • Update group = www-data to group = site2.
  • Replace listen = /var/run/php/php7.4-fpm.sock with listen = /var/run/php/php7.4-site2-fpm.sock.

7. Restart PHP-FPM

Apply all the changes by restarting the PHP-FPM service:

$ sudo service php7.4-fpm restart

Confirm that the pools are running independently:

$ sudo service php7.4-fpm status

You should see separate processes for each configured pool in the output, similar to:

CGroup: /system.slice/php7.4-fpm.service
        ├─70796 php-fpm: master process (/etc/php/7.4/fpm/php-fpm.conf)
        ├─70807 php-fpm: pool site1
        ├─70808 php-fpm: pool site1
        ├─70809 php-fpm: pool site2
        └─70810 php-fpm: pool site2

Note: Process IDs will vary depending on your system’s runtime state.

8. Configure Nginx to Use the Dedicated PHP-FPM Pools

To ensure each website uses its corresponding PHP-FPM pool, you must define separate server configurations for each domain in Nginx.

Create Configuration for site1

Begin by creating a new Nginx site configuration file:

$ sudo nano /etc/nginx/sites-available/site1

Add the following configuration:

server {
    server_name site1.example.com;

    access_log /var/log/nginx/site1.access.log;
    error_log /var/log/nginx/site1.error.log;

    root /var/www/site1;

    index index.php;

    try_files $uri $uri/ /index.php?$query_string;

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php7.4-fpm-site1.sock;
        include snippets/fastcgi-php.conf;
    }
}

Explanation of the main directives:

  • server_name: Defines the domain name for the virtual host.
  • access_log: Specifies the file to store access logs.
  • error_log: Sets the file path for error logs.
  • root: Indicates the document root for site files.
  • fastcgi_pass: Points to the PHP-FPM socket defined in the site’s pool.

Create Configuration for site2

Repeat the process for the second domain:

$ sudo nano /etc/nginx/sites-available/site2

Insert this configuration:

server {
    server_name site2.example.com;

    access_log /var/log/nginx/site2.access.log;
    error_log /var/log/nginx/site2.error.log;

    root /var/www/site2;

    index index.php;

    try_files $uri $uri/ /index.php?$query_string;

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php7.4-fpm-site2.sock;
        include snippets/fastcgi-php.conf;
    }
}

Enable the New Site Configurations

Activate both configurations by creating symbolic links:

$ sudo ln -s /etc/nginx/sites-available/site1 /etc/nginx/sites-enabled/site1
$ sudo ln -s /etc/nginx/sites-available/site2 /etc/nginx/sites-enabled/site2

Reload Nginx to apply the changes:

$ sudo service nginx restart

9. Verify Site Isolation and Configuration

To ensure the setup works as expected, create a test PHP file for each site that outputs the PHP environment.

Create a PHP Info File for site1

$ nano /var/www/site1/index.php

Insert the following code:

Create a PHP Info File for site2

$ nano /var/www/site2/index.php

Paste the same content:

Visit http://site1.example.com and http://site2.example.com in a web browser to confirm that both domains serve their respective PHP-FPM pools. Check the PHP info output — under the PHP Variables section, the $_SERVER['USER'] value should be site1 for site1 and site2 for site2.

Conclusion

By allocating a unique PHP-FPM pool for every hosted domain, you enhance both security and performance. This also simplifies issue tracking and tuning of individual websites. All settings are stored within each pool’s file under /etc/php/7.4/fpm/pool.d. One commonly modified setting is pm, which controls how PHP-FPM manages child processes. You can configure this parameter with modes like dynamic, static, or ondemand depending on your server’s resource usage. Refer to the official PHP-FPM documentation for further details on pool configuration.

Source: vultr.com

Create a Free Account

Register now and get access to our Cloud Services.

Posts you might be interested in:

Moderne Hosting Services mit Cloud Server, Managed Server und skalierbarem Cloud Hosting für professionelle IT-Infrastrukturen

Deploy Jenkins with Docker Compose on Ubuntu

Docker, Tutorial
Installing Jenkins on a Ubuntu Server Using Docker Compose Jenkins, a widely used open-source application developed in Java, is ideal for creating continuous integration and continuous deployment (CI/CD) pipelines, accelerating…