A great security feature of Php FastCGI Process Manager (Php-fpm) is its ability to run Php scripts with different users. This in addition to its other merits such as performance and many fine grained options for tuning makes it the best choice for running Php sites.

Before anything else, I must admit that Nginx with Php-fpm is preferred than Apache with Php-fpm for performance reasons mostly. There are fine articles such as this one explaining how to accomplish exactly the same as the current topic with Nginx and not with Apache. The setup for Php-fpm with Apache is similar but there are some Apache specifics which are important and on which the current article stresses.

You might wonder why would anyone run Apache with Php-fpm instead of Nginx with Php-fpm if the latter is generally preferred. One good reason is that you might have a ton of Apache specific rewrite rules and virtual hosts configurations. It might not be so easy to rewrite them and may be even not worth it depending on what you expect to gain from running Nginx instead of Apache.

Once you are convinced that you want to go for Apache with Php-fpm you can continue reading. Not only the basic setup is covered but you will also find out how to run different Php-fpm pools with different users and configure the Apache virtual hosts to use those different pools.

Prerequisites

This article is about Ubuntu 16.04 LTS, Apache 2.4 and Php7-fpm. Though, it should be very similar for other Linux distributions, Apache versions and Php-fpm versions.

Installation of Apache, Php-fpm and mod_fastcgi

For the perfect Apache - Php-fpm setup you will have to install the following packages with apt-get:

apt-get -y install apache2 libapache2-mod-fastcgi php7.0-fpm php7.0

If you wonder why the installation of Apache's mod_fastgi (libapache2-mod-fastcgi) is needed, it is because it will be used for the connection between Apache and Php-fpm.

Once everything needed is installed, make sure the necessary Apache modules are enabled:

a2enmod actions fastcgi alias proxy proxy_http proxy_fcgi

Finally, for the latter settings to take effect, restart Apache with:

service apache2 restart

Configuring Php-fpm

The default configuration of Php-fpm is good enough for the start so you can leave it as is. There is one default Php-fpm pool
/etc/php/7.0/fpm/pool.d/www.conf that comes with the installation. It has the following distinct settings:

; pool name
[www]
...
; Unix user/group of processes
; will be used.
user = www-data
group = www-data
...
; Socket to which the Apache will connect
listen = /run/php/php7.0-fpm.sock

For every new Php-fpm pool, you must have all these four parameters different. For example, let's create another pool called siteA. Make sure that beforehand you create the user and group that will be used by the new pool. To continue the example with siteA, let's run this pool under user sitea and group sitea. Create them with the commands:

groupadd sitea
useradd -g sitea sitea

Then, copy the default pool file /etc/php/7.0/fpm/pool.d/www.conf to /etc/php/7.0/fpm/pool.d/sitea.conf. In the latter file adapt the four parameters:

; pool name
[sitea]
...
; Unix user/group of processes
; will be used.
user = sitea
group = sitea
...
; Socket to which the Apache will connect
listen = /run/php/php7.0-fpm-sitea.sock

After that restart Php-fpm with:

service php7.0-fpm restart

To make sure the new pool works fine, check if its socket exists (/run/php/php7.0-fpm-sitea.sock) on the filesystem. Each pool has such a socket to which Apache will be connecting.

Configuring Apache vhosts to work with different Php-fpm pools

To accomplish isolation between different web sites or even parts of one site (e.g. blog, forum, etc), each entity should use different Php-fpm pools. Let's take an example with a different Vhost - siteA (with DNS www.example.com). Create a sample Vhost in Apache containing something similar to this:


ServerName www.example.com ServerAdmin webmaster@localhost DocumentRoot /var/www/sitea ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined # Start of Php handling with Php-fpm Require all granted AddHandler php7-fcgi .php Action php7-fcgi /php7-fcgi virtual Alias /php7-fcgi /usr/lib/cgi-bin/php7-fcgi FastCgiExternalServer /usr/lib/cgi-bin/php7-fcgi -socket /run/php/php7.0-fpm-sitea.sock -pass-header Authorization # End of Php handling with Php-fpm

Before reloading Apache for the new Vhost to take effect, make sure that you create the directory specified as DocumentRoot for the vhost - /var/www/sitea in this case. This must be owned by the user sitea and group sitea.

Testing

To test everything so far, create a new test.php file containing phpinfo() and open it in your browser. In the newly opened page search for the Environment variables:

Environment

Variable Value
USER usera

The above proves that the test.php file was executed with the user usera. Have this test for each new Vhost - Php-fpm you create to make sure you have completed all steps properly.

Setting the Vhost permissions

Having Php scripts in your Vhosts run with dedicated users (such as usera) is beneficial because you can set individual access permissions (and also resource limits which is another topic). The simplest way to restrict these dedicated users is with files permissions.

There are three steps in setting the permissions:

  1. Change recursively the ownership of the Vhost directory (Apache's DocumentRoot) to the dedicated user and the www-data user group. Example: chown usera:www-data /var/www/sitea
  2. Set some not-so-restrictive permissions recursively to this directory such as 740. This ensures that your dedicated user can read, write and execute files while www-data (the web server) else can just read and execute them. It's important that the group www-data is able to read the files because Apache must have read access to static files such as images, javascripts, css, etc. Otherwise, your site will not work in most cases.
  3. You can additionally change the permissions of the Php files with sensitive information to 600 so that only your dedicated user can read them. Such sensitive files are usually those containing credentials to log in databases which you don't want anyone but the dedicated user to be able to read.

Setting the above permissions is the essence of this article and the whole idea behind running securely different Vhosts with Php-fpm.

Conclusion

By completing the steps in this article you will have isolated web sites in Apache. If one site is compromised the others will not suffer - their files cannot be read, changed, nor the sensitive information stolen. And all of these comes with great performance provided by Php-fpm running on the good old Apache.