How to set up PHP-FPM¶
As mentioned on the official website, PHP-FPM (FastCGI Process Manager) is is an alternative PHP FastCGI implementation with some additional features (mostly) useful for heavy-loaded sites.
It allows PHP to run as its own process under its own user, separate from Apache, unlike mod_php
.
It also makes it possible to use multiple PHP versions from the same Apache setup.
In order to use php-fpm
to serve a website, follow the steps below.
System service¶
You will need to have one system service for each version of php-fpm
you may want to run concurrently (e.g. PHP5 and PHP7).
The SysV-style init script is bundled with your PHP.
For instance, for a phpbrew
-based installation of PHP 7.2.15 in /opt/phpbrew
:
sudo cp /opt/phpbrew/build/php-7.2.15/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm-7.2.15
sudo chmod +x /etc/init.d/php-fpm-7.2.15
You may want to tweak the code of the script so it prints php-fpm-7.2.15
rather than just php-fpm
, but it is not necessary.
Before you can run this, you have to tweak the php-fpm.conf
file, which is usually close to where the relevant php.ini
is.
For this phpbrew
-based install, it would be in /opt/phpbrew/php/php-7.2.15/etc/php-fpm.conf
.
Make sure you uncomment the line mentioning the pid
variable, so that a PID file is created.
You will also need to ensure that both user
and group
are set to the appropriate one in the php-fpm.d/www.conf
file.
It would be even better if you used an app-specific user, to isolate PHP applications from each other.
Once these tweaks are ready, start the service manually and check it started correctly with:
sudo /etc/init.d/php-fpm-7.2.15 start
sudo /etc/init.d/php-fpm-7.2.15 status
Make sure you register the service to be started on boot:
sudo systemctl enable php-fpm
Reloading the PHP OPCACHE¶
When a new version of a website is deployed via FPM, PHP does not automatically flush its OPCODE cache, which means that users will see the old version of the application.
In order to force this to happen, the following needs to be added to the project.sh
file:
# Ensure PHP FPM is reloaded (picks up new code)
if test -x /usr/sbin/service; then
sudo -n /usr/sbin/service php7.2-fpm reload
fi
This means that gitlab-runner
, which runs as an unprivileged user, needs to call sudo
.
To make this happen, on Ubuntu servers, run sudo visudo
and add this to the sudoers
file:
gitlab-runner ALL = (root) NOPASSWD: /usr/sbin/service php7.2-fpm reload
Note that the command itself is run with sudo -n
, so it will never prompt for a password and just fail if it were to ask for a password.
See this guide for more details on editing sudoers
on Ubuntu.
Apache virtual host (UNIX socket-based)¶
To switch from mod_php
to php-fpm
, go to your <VirtualHost>
and change it to use ProxyPassMatch
for any .php
files:
ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/opt/phpbrew/php/php-7.2.15/var/run/php-fpm.sock|fcgi://localhost/path/to/document/root
This must be done at the <VirtualHost>
level: it cannot be done from a <Directory>
.
Apache virtual host (TCP socket-based)¶
On SELinux-happy environments, it may be easier to tweak the php-fpm.d/www.conf
file to listen on a TCP port:
listen = 127.0.0.1:port
You can then tell Apache to use that TCP socket, with a slightly different syntax. This used to be necessary on CentOS servers - it may not be necessary on Ubuntu servers.
By the way, this syntax can be used to forward specific subfolders in a <VirtualHost>
to specific versions of PHP (as done in the Industry Club website):
ProxyPassMatch "^/folder/(.*\.php(/.*)?)$" fcgi://127.0.0.1:9007/path/to/folder/$1