Guide to combining Apache virtual hosts and PHP7 FPM

So, I recently decided to abandon my old directadmin server and migrate to a fresh Ubuntu server. The main reason for this was the long-awaited release of PHP 7.0.0. This meant I had a chance to start all over and create the fastest possible setup for my server.

This guide assumes you have PHP 7.0.* running on your server as well as Apache (with virtual hosts) on a Ubuntu server. Also, please do not try this on a production environment without having proper backups in place.

At first, I decided to just go with Apache using mod_php, since it was the easiest to setup.The downside of this is the increased memory usage of Apache, since every instance of it also includes a PHP instance. Even for static resources.

This is where PHP-FPM comes into play. PHP-FPM runs as a separate process from Apache and only get instantiated when necessary. This decreases the memory usage of each Apache instance, and thus, decreasing the load on the server.

On to the actual guide. First we’re going to make sure php7.0-fpm is installed on your system:

After it has been installed, you have to start the service if it hasn’t automatically:

That’s it, PHP-FPM is now running on your system. Apache does not know about it yet though and is still using mod_php.

To use PHP-FPM for each and every one of your virtual hosts, you will have to split it into multiple resource pools. One for every separate virtualhost user. Meaning if you have multiple hosts assigned to one user, you will only have to create one resource pool for that user.

The default location for the pool configuration for PHP-FPM is

To create a new configuration for one of your users, simply create a new .conf file. I used the user’s username as the name of the config file:

And use this as your configuration (replace “username” with the actual name of your user):

The first six lines are the most important. Make sure that they are the same as the Apache virtualhost user. The last five lines are the default settings for the process manager. I decided to leave them as is for the sake of simplicity, but you can change them to your likings. You can read more about these settings in the default config file located at

Now reload PHP-FPM to make sure your configuration is loaded:

Now that we have PHP-FPM set up for one of your users, the only thing remaining is telling Apache to use PHP-FPM instead of mod_php.

First, make sure you have both mod_actions and mod_fastcgi enabled:

And restart Apache to have the changes take effect:

Now it’s time to add the PHP-FPM fastcgi handler to Apache. You will have to do this for every user that you want to be able to user PHP-FPM. I used a macro for this myself, but the easiest way is to edit your vhosts config, typically located at:

Add the following at the top:

Again, replace “username” with the actual name of the vhost’s user.

Now that we’ve added the PHP-FPM fastcgi handler, all that is left is to tell your vhost to actually use it for .php files. So in the same file, but in the directive, add the following lines:

Replace “username” with the name of the actual vhost user again and save the file. Now all that is left is to let Apache reload its config files:

To see if your changes had any effect, create a phpinfo.php file in your website’s public directory and visit it in your browser:

Look for “Server API”. If everything went well, it should say”FPM/FastCGI”. Congrats, you are now running PHP-FPM on this virtual host.

To complete the process, you should repeat the steps for each of your virtual hosts. When you are entirely sure mod_php is not being used anymore you can disable it through

Until you’ve done this, Apache will still include a PHP process for every request, meaning the memory usage will stay the same and possibly be even higher.

Disclaimer: I’ve only recently started deploying my own servers, so it is entirely possible there are easier and/or better ways to achieve the above. I am open for any suggestions, so please feel free to leave a comment or email me.

  • anonyme mais jai un email

    this was useful for setting up ONE host. I just ignored or removed all the username stuff

    • Sillycybin

      Did the same thing, works like a charm!

  • kons

    Hey, a very usefull guide, but how is it possible for multiple virtual hosts? I have server with 2 vhosts and each should have the own user/group. I applied your settings for one vhost, but now the second vhost has also the same settings… Any help?

  • Michael Richey

    Great write-up! I did run into an issue though. sessions could not be written to /var/lib/php/sessions. I tried chmoding it to 777, I even tried changing ownership to nobody:nogroup but to no avail.

    I like this solution better though.

    Create a “sessions” folder under the users home directory and add an extra line in username.conf under fpm config –
    php_admin_value[session.save_path] = /home/username/sessions

    Now each user has their own session directory.

    I’m looking into the chroot option in fpm config as well – might be beneficial, but will require some testing.

  • Richard Reijmers

    Was running into issues ( until I read this article thanks!

    Basically my fault was to have a single ‘Handler’ for multiple vhosts PHP-FPM sockets.
    One thing I ran into using this code was:

    Permission denied: [client] FastCGI: failed to connect to server “/usr/lib/cgi-bin/”: connect() failed

    This was fixed by placing the following in my PHP-FPM pool conf (username.conf)
    listen.mode = 0666

    Now I have multiple Apache vhosts served by its own users through PHP-FPM.
    Thanks again!

    • Adam Brown

      I had to go a step further.

      Turns out my /usr/lib/cgi-bin dir was owned by root, so I had to change that to www-data:
      sudo chown -R www-data:www-data /usr/lib/cgi-bin

      Then I had to add my user to the www-data group:
      sudo usermod -a -G www-data myuser

      Then it worked.

    • Koen

      Glad to have been of help and thanks for the feedback. I’ll try to update the article when I find some time.

    • yannick_gagnon

      Wow, thanks for that listen.mode = 0666 tip. Saved the day for me.

  • Douglas da Costa

    Hi! Thanks so much for your help. I was issued when tried to migrate from mod_cgi to fastcgi, then after read a ‘thousand’ articles and didn’t find anything helpless, I found this.

  • bnornes

    Question regarding chroot.
    Adding this to userpool.conf causes error :
    “/usr/lib/cgi-bin/php7-fcgi-userpool” stderr: Unable to open primary script:

    Any solution to this problem ?

    chroot = /websites/userpool/
    chdir = /www/html/
    directory structure :

  • Lindsay

    Wow! It’s rather seldom that I come across a “howto” such as this one that mostly just works :) This is probably because it’s relatively in sync with current software versions (which may change a few years down the road).

    I did run into the permissions error which Richard Reijmers described, and the addition of listen.mode to the pool config file solved this. I encourage you to put this into the text. The problem caused me a couple of hours until I stumbled on Richard’s comment.

    I didn’t run into Adam Brown’s problem. /usr/lib/cgi-bin is user/group root:root, mode 755, and although I tried setting it to u/g www-data:www-data (which worked OK), switching it back to root:root ownership made no difference once I had this working.

    Thanks very much for making this recipe available. I got it running on a sandbox virtual machine in anticipation of upgrading my production server to a newer version of Ubuntu Server, using PHP 7 rather than v5 where I’ll have to abandon suPHP, which is what I’m using now for this purpose.

  • Lindsay

    In the interest of simplicity, clarity and speed, here are a few suggestions:

    Your per-vhost config file code contains a permissions grant on /usr/lib/cgi-bin. This need be done but once, and I’ve pulled the last 3 lines before the closing </IfModule> out and added them to the fastcgi.conf file for the mod_fastcgi module. This leaves only the code in the per-vhost conf file which needs to be modified to contain the vhost name.

    A little clarity in this section would help. The next code block is to be added “in the same file, but in the directive”, by which I assume you mean within the <Virtualhost …> block, yes? I puzzled over this but adding it to to this block worked OK, and each of a couple of virtual host test accounts I created worked as expected.

    The FilesMatch directive in the per-vhost file should handle “.php7”, although this may not be in common use. You have “<FilesMatch “[345]?|t|tml)$”>”. Most other contexts I’ve seen in which FilesMatch is uses to identify PHP files add “7” to the numbers in the regexp character class. A small typo, this, but possibly important in a few cases.

    New accounts on my server are created using a collection of python scripts which copy templates to the right places and turn the appropriate cranks. I try to keep the template code and required steps down to a bare minimum once the general environment has been established.

  • Lindsay
  • freddan67

    Great effort, I got it working thanks to this excellent guide.

  • Dominic108

    This is old, but still useful today. If listen.owner and are set to username, apache cannot access the socket, unless you allow anyone to access the socket or you add www-data to the username group. It’s simpler and safer to set listen.owner to www-data and to username. Then the socket can be restricted to the owner and group only (660) and you don’t need to add www-data to the username group.