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.
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
-
Pool name. It is on the top
[www]
. Rename it to[mysite]
. -
Next, change the user and group field and put the username and group to run it with.
user = mysite_user
group = mysite_user
- 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.
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.
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.