A few months back, I started looking into automating my server environment, and php resource pools was completely vague to me. If you don’t already know; my server is used for development – it is essentially my remote-harddrive for client work. I do not use the typical Vagrant, or Local by Flywheel that you see around the web today. Now I’m not going to get into the details as to why, since I would be repeating myself. If you’d like to know, checkout “Why I stopped using vagrant” – an article I wrote over at WebDevStudios. Enough back story, let’s dive in, shall we?

Limitations of this post!

This post is tailored to my server setup, which is the following:

  • PHP-FPM 5.6 ( I haven’t installed 7, I know… I know )
  • Nginx
  • Ubuntu

While the documentation below may be secluded to this specific setup, my hope is the knowledge you learn here can be applied to other situations as well. All in all, the idea is the same — creating configuration files on a per-user basis.

I am not an official system administrator – my server is my playground for administrator stuff. If you have anything to add to this post, I thirst for knowledge – so please share!

What are php resource pools?

In short, it’s a PHP socket, at least that’s my understanding. I found out about sockets entirely by accident a few months back. I was setting up Locust ( a great load testing application if you’re interested ) and wanted to see if I could just kill my server… in short, yep totally possible. Spawning thousands of virtual users is a bad idea against a single socket vanilla setup.

From what I can tell by default a socket has a limited number of connections; which was evident with my Locust testing above. Well this is a problem, the way I setup my server ( more on that in another post ) was completely wrong. Every user/website I have was using the exact same socket. For my purpose this was just bad, having 20+ development sites I’m always working on, as well as multiple live sites, I just wasn’t using my resources to the fullest. I’m just glad the blog wasn’t super popular at the time.

Setting up a Resource Pool

For my server, as I said, I setup a resource pool for each user, and each user ( currently ) has their own home folder. This makes setting up users and resource pools more script-able and easier to follow.

First you must find where your resource pools are coming from, for me it was simple:

/etc/php5/fpm $ cat php-fpm.conf | grep pool
include=/etc/php5/fpm/pool.d/*.conf

Reading the include line, it says “anything in this folder that has an extension of conf, include it”. So this is where my pool files were. Now that I know this, it’s as simple as creating a file.

/etc/php5/fpm $ vim pool.d/user.conf

Now, I’ll be the first to say, PHP-fpm pools are NOT straight forward at first. But once you get the hang of it, you’ll be able to decipher the meanings pretty easily. There’s also a handy manual of PHP-fpm directives available if you’d like to read through.

Below is my config for my playground server, you’ll just need to replace ‘%USER%’ with your username for each user you need a pool for.

# This sets up a resource pool for the user.
# By setting up a resource pool you are basically separating server reources between users.
# Author: Jay Wood
# http://github.com/JayWood

[%USER%]

prefix = /home/$pool

user = %USER%
group = %USER%

listen = /home/$pool/run/php5-fpm.sock
listen.owner = %USER%
listen.group = www-data
listen.mode = 660

# These fields are optional
env[PATH] = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
env[TMPDIR] = /home/$pool/tmp
env[TEMP] = /home/$pool/tmp
env[TMP] = /home/$pool/tmp

# Setting up some logging, to make sure logs are stored in the user directory.
access.format = "%{HTTP_X_FORWARDED_FOR}e - [%t] \"%m %r%Q%q\" %s %l - %P %p %{seconds}d %{bytes}M %{user}C%% %{system}C%% \"%{REQUEST_URI}e\""
access.log = /home/$pool/log/$pool.access.log
slowlog = /home/$pool/log/$pool.slow.log
request_slowlog_timeout = 5s
catch_workers_output = yes

php_value[error_log] = /home/$pool/log/error.log
php_value[mail.log] = /home/$pool/log/mail.log
php_value[upload_tmp_dir] = /home/$pool/tmp
php_value[session.save_path] = /home/$pool/tmp

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

You’ll notice a few specific paths here, mainly /home/$pool – which in my case is the user directory. This obviously requires you have a few folders in the user directory, in this case it’s tmp/, run/ and log/. Feel free to change these where ever you’d like them to be, but you will want to make sure you note down the location of run/ which we’ll get to in a bit.

This is not the alpha and omega of configs, please take time to read through the directives linked above in order to tailor this config to YOUR server.

How does this involve Nginx?

Think of Nginx as border patrol for your domain name, while the resource pool is the shuttle bus that gets users from point A to point B. Nginx determines, at the server level, where to send your users based on the directives you set in the config files. While the resource pool dictates how many can be moved at one time.

In the above section, take note of the listen=/home/$pool/run/php5-fpm.sock directive. This is where your socket file is created, so what we do now, is for the server, we have to tell Nginx to listen on that socket.

Most servers have their vhosts ( virtual hosts ) in a common location:

$ cd /etc/nginx/sites-available

If you open up a file here, you should see something similar to this:

server {
    listen 80;
    listen [::]:80;

    server_name example.com;

    # ... stuff

    location / {
        # ... stuff
    }

    location ~ \.php$ {

        # ... stuff
    }

}

Take note of the location ~ \.php$ directive, this is what we need to update. If you’ve had a slight amount of regular expression experience, this is familiar to you. If this server block stuff doesn’t make sense at all, you may want to look at some server block examples on the official Nginx website.

To force Nginx to use our newly created socket, it’s just a one-line configuration change ( if you’re already using fastcgi ), of course swap %USER% with your username, or if you’ve completely moved the path in the listen= directive, use that.

location ~ \.php$ {
    # ... more stuff
    fastcgi_pass   unix:/home/%USER%/run/php5-fpm.sock;
}

If you’re not using Fast CGI, honestly I can’t help you haha! But again, the server block examples above should give you a general idea of what’s what. Note that the unix: prefix tells Nginx that we’re using a Unix socket.

Now it’s just a matter of restarting Nginx and php-fpm:

service php5-fpm restart
service nginx restart

Summary

I’m still in the process of writing my server-setup scripts over on GitHub. I hope to have a fully automated system to do so eventually. Obviously there’s a large amount of stuff you have to consider when setting up a server, and resource pools are only one piece to the puzzle.

The config values provided are not set in stone — remember, this is YOUR server, set it up how you want. I just hope this article gives you a little insight into the microcosm that is server administration.