Skip to content

Instantly share code, notes, and snippets.

@fyrebase
Created December 2, 2015 10:02
Show Gist options
  • Star 32 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save fyrebase/62262b1ff33a6aaf5a54 to your computer and use it in GitHub Desktop.
Save fyrebase/62262b1ff33a6aaf5a54 to your computer and use it in GitHub Desktop.
Setup individual pools for PHP-FPM and NGINX - http://www.binarytides.com/php-fpm-separate-user-uid-linux/

Php-FPM

Php fpm is the new way to setup php to run with your webserver. Php-fpm is a fastcgi process manager for php that is totally separate from the webserver. The webserver communicates with fpm through a socket and passes the name of the script to execute. So fpm can run with any web server that is fastcgi compatible.

I recently moved from my old shared hosting to linode. Linode provides linux vps hosting at economic prices. However the servers are totally unmanaged are just raw linux machines that have shell access. So through the shell you have to setup everything including the web server, php and the web files.

So this time I decided to go with the combination of nginx and php-fpm. I had multiple sites to setup on this new webserver. Nginx deals with these through separate server blocks (aka vhost in apache). However there was another thing needed. Php on each site should run with its own user and not the nginx common user named www-data.

Running each site with its own uid/gid is more secure and easier to deal with. If all sites ran with same user, then php on one site could read/write the files of other users. This is a security concern. Moreover having separate users gives benefits like separate crontabs, ability to identify processes from each user etc.

Separate Pools

Php-fpm creates and manages a pool of php processes, also called workers that receive and server requests to execute php files from the web directory. Now fpm can run multiple separate pools each with its own uid/gid. This is actually very easy to setup.

On ubuntu, the directory that contains the pool configuration files is /etc/php5/fpm/pool.d/

A file called www.conf already exists which can be copied to create more pool configuration files. Each file must end with .conf to be recognised as a pool configuration file by php fpm.

The file is very long but starts with something like this.

; Start a new pool named 'www'.
; the variable $pool can we used in any directive and will be replaced by the
; pool name ('www' here)
[www]

; Per pool prefix
; It only applies on the following directives:
; - 'slowlog'
; - 'listen' (unixsocket)
; - 'chroot'
; - 'chdir'
; - 'php_values'
; - 'php_admin_values'
; When not set, the global prefix (or /usr) applies instead.
; Note: This directive can also be relative to the global prefix.
; Default Value: none
;prefix = /path/to/pools/$pool

; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
user = enlightened
group = enlightened

; The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses on a
;                            specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
listen = /var/run/php5-fpm.sock

; Set listen(2) backlog.
; Default Value: 128 (-1 on FreeBSD and OpenBSD)
;listen.backlog = 128

So create a copy of this file and name it to anything like the site which will be using this pool. The important fields to edit are

  1. Pool name. It is on the top [www]. Rename it to [mysite].

  2. Next, change the user and group field and put the username and group to run it with.

user = mysite_user
group = mysite_user
  1. Change the socket file name. Every pool should have its own separate socket. And the particular site should use this particular socket file to connect to fpm.

listen = /var/run/php5-fpm-mysite.sock

Now restart php-fpm

$ sudo service php5-fpm restart

Now check the processes in htop. You should see the new pool running with separate username. Check the documentation for details about all the configuration parameters. Each pool can have different configuration depending on the needs of the site.

Configure Nginx

If you are using nginx, then put the socket descriptor in the right place and it will use it.

location ~ \.php.*$ {
	fastcgi_split_path_info ^(.+\.php)(/.+)$;

	# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

	# With php5-cgi alone:
	# fastcgi_pass 127.0.0.1:9000;
	# With php5-fpm:
	fastcgi_pass unix:/var/run/php5-fpm.sock;
	fastcgi_index index.php;
	include fastcgi_params;

	fastcgi_param PATH_INFO $uri;
}

Put the socket descriptor path in the fastcgi_pass line.

fastcgi_pass unix:/var/run/php5-fpm-mysite.sock;

Thats it. Nginx will now use this socket and hence its pool for mysite.

@ojtibi
Copy link

ojtibi commented Nov 21, 2017

Reading your gist right now. An issue with this setup is POST uploads through PHP-FPM, since PHP-FPM does not have write access to nginx's temporary upload directory.

@YIN-Renlong
Copy link

Hi, would there be a comprehensive test about the necessity to create multi FPF socks? Any threshold value for the quantity of Wordpress sites?

@jerrylau91
Copy link

unix socket file

@shubhamoli
Copy link

shubhamoli commented Mar 12, 2019

Sometimes one can get following error which is due to permissions:

connect() to unix:/var/run/php5-fpm-mysite.sock failed (13: Permission denied) while connecting to upstream

Then please add

listen = /var/run/php5-fpm-mysite.sock
listen.owner = mysite_user
listen.group = mysite_user

@LC43
Copy link

LC43 commented Apr 7, 2021

also, change the [pool-name] so php-fpm can create the new socket

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment