This article was last reviewed for Debian 9 (Stretch).
PHP 7 installation and configuration for Nginx using PHP-FPM (Debian, repository)
Author: | Stefán Örvar Sigmundsson |
---|---|
Initial publication: | |
Last updated: | |
Written in: | English (United Kingdom) |
PHP is the world's most popular server-side web development scripting language. The original and primary PHP interpreter implementation is the Zend Engine. This article will demonstrate how to install and configure PHP 7 and PHP-FPM for Nginx on Debian or its derivatives such as Ubuntu and Linux Mint. The scripting language will be configured for the domain name example.org as a virtual server.
PHP-FPM
PHP-FPM (FastCGI Process Manager) is as its name indicates a process manager for PHP over FastCGI. Nginx and PHP can communicate via the FastCGI binary protocol which PHP-FPM implements along with advanced process management features.
PHP-FPM manages processes in what are called pools. A pool is a configurable unit of one or more processes that handle PHP requests. Pools can be optimised in a variety of ways to serve low to high PHP-intensity web sites. Some important features of pools are:
- Pools are ownable by specified OS users and groups (for security reasons).
- Pools are limitable to a minimum and maximum number of processes (for CPU performance reasons).
- Pools are limitable to a maximum number of PHP requests per process before respawning (for RAM performance reasons).
Pool | Process | Single web site | Multiple web sites | |
---|---|---|---|---|
PHP-intensity | PHP-intensity | Administrated | ||
Single | Single | Low | Low | Together |
Multiple | High | High | Together | |
Multiple | Single | Impossible[1] | Low | Separately |
Multiple | High | Separately |
- ^ A single pool can serve multiple web sites but a single web site can not be served by multiple pools.
Installation
PHP and PHP-FPM can be installed from the official Debian repository using APT:
root@computer:~# apt --assume-yes install php7.0-fpm
Configuration
PHP-FPM is stopped before beginning the configuration for the sake of simplicity:
root@computer:~# systemctl stop php7.0-fpm.service
The default log file for PHP-FPM (php7.0-fpm) is deleted and a new one (error.log) created in a dedicated directory (/var/log/php7.0-fpm/) for organisational purposes:
root@computer:~# rm /var/log/php7.0-fpm.log root@computer:~# mkdir /var/log/php7.0-fpm/ root@computer:~# touch /var/log/php7.0-fpm/error.log
A file is created to contain the error log for PHP in a dedicated directory. PHP does not log errors by default but instead embeds them in the web pages where they occur. PHP errors and warnings should not be visible to the world for security reasons.
root@computer:~# mkdir /var/log/php7.0/ root@computer:~# touch /var/log/php7.0/error.log
A directory is created to contain the temporary files uploaded to the web server via PHP before they are saved elsewhere or discarded at the end of scripts:
root@computer:~# mkdir /var/tmp/php7.0/
There is a lot of clutter in the default configuration files even though they are operational. Clearing them will ensure that there is no conflict nor confusion:
root@computer:~# > /etc/php/7.0/fpm/php.ini root@computer:~# > /etc/php/7.0/fpm/php-fpm.conf
The default pool created by the package is called www. A pool is created with a more descriptive name:
root@computer:~# rm /etc/php/7.0/fpm/pool.d/www.conf root@computer:~# touch /etc/php/7.0/fpm/pool.d/example.org.conf
The default user and group assumed by the package are called www-data. A user and a group are created with a more descriptive name:
root@computer:~# useradd --comment "PHP" --shell "/usr/sbin/nologin" --system --user-group php
php.ini
The php.ini file contains PHP's primary configuration:
[PHP]
date.timezone = Atlantic/Reykjavik
display_errors = Off
error_log = /var/log/php7.0/error.log
error_reporting = 32767
log_errors = On
register_argc_argv = Off
session.gc_probability = 0
short_open_tag = Off
upload_tmp_dir = /var/tmp/php7.0/
[PHP]
- Sets the configuration scope for the subsequent directives to PHP.
date.timezone = Atlantic/Reykjavik
- The time zone of the server. The time zone (Atlantic/Reykjavik) should be replaced with the relevant time zone.
display_errors = Off
- Disables the embedding of PHP errors and warnings in outputed HTML for security reasons.
error_log = /var/log/php7.0/error.log
- A log file (/var/log/php7.0/error.log) is created to contain PHP errors and warnings.
error_reporting = 32767
- A predefined construct (32767) that instructs the interpreter to log all PHP errors and warnings.
log_errors = On
- Enables logging of PHP errors and warnings into the log file.
register_argc_argv = Off
- Disables a CLI feature unnecessary for most users.
session.gc_probability = 0
- Disables the garbage collection process to prevent session data loss. Sessions will have to be removed manually periodically.
short_open_tag = Off
- Disables short form open tags for the sake of standardisation.
upload_tmp_dir = /var/tmp/php7.0/
- A directory (/var/tmp/php7.0/) is created to contain uploaded files temporarily.
php-fpm.conf
The php-fpm.conf file contains PHP-FPM's primary configuration:
[global]
error_log = /var/log/php7.0-fpm/error.log
include = /etc/php/7.0/fpm/pool.d/*.conf
[global]
- Sets the configuration scope for the subsequent directives to global.
error_log = /var/log/php7.0-fpm/error.log
- A log file (/var/log/php-fpm/error.log) is created to contain PHP-FPM errors and warnings.
include = /etc/php/7.0/fpm/pool.d/*.conf
- All process pool declaration files are included.
pool.d/example.org.conf
The pool.d/example.org.conf file contains a process pool declaration:
[example.org]
group = php
listen = /run/php/php7.0-fpm.socket
listen.group = nginx
listen.mode = 0660
listen.owner = nginx
pm = ondemand
pm.max_children = 10
pm.max_requests = 200
pm.process_idle_timeout = 10s
user = php
[example.org]
- Sets the configuration scope for the subsequent directives to example.org.
group = php
- The OS user of the process pool.
listen = /run/php/php7.0-fpm.socket
- The socket used by Nginx and PHP-FPM to communicate.
listen.group = nginx
- The OS group of the socket. Nginx must use the same group for communication.
listen.mode = 0660
- The file system permissions of the socket.
listen.owner = nginx
- The OS user of the socket. Nginx must use the same user for communication.
pm = ondemand
- Sets the type of process manager.
pm.max_children = 5
- Sets the maximum number of child processes.
pm.max_requests = 200
- Sets the maximum number of requests processed per child process before respawning to reclaim leaked memory.
pm.process_idle_timeout = 10s
- Sets the idle time for child processes before being killed.
user = php
- The OS group of the process pool.
Conclusion
Log rotation
The package installs a default logrotate configuration file (/etc/logrotate.d/php-fpm) that can be customised:
/var/log/php7.0/*.log /var/log/php7.0-fpm/*.log
{
copytruncate
maxage 365
missingok
monthly
notifempty
rotate 12
}
/var/log/php7.0/*.log /var/log/php7.0-fpm/*.log
- Sets the configuration scope for the subsequent section. The pattern matches all files (*) ending with the extension log in the /var/log/php7.0/ and /var/log/php7.0-fpm/ directories.
copytruncate
- Copy the contents of the log file being rotated into a new file and then truncate the original log file.
maxage 365
- Remove log files older than 365 days.
missingok
- Do not consider it an error if a log file is missing.
monthly
- Perform a log rotation monthly.
notifempty
- Do not perform a log rotation on an empty log file.
rotate 12
- Perform 12 log rotations before older log files are removed.
Nginx configuration
This article assumes that the Nginx installation is compatible and that its configuration has not been altered significantly.
FastCGI parameters
PHP-FPM requires miscellaneous information that Nginx must pass on to it. The FastCGI parameters can be stored in a file called conf.d/http_fastcgi.conf.
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REDIRECT_STATUS 200;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
Virtual server
A directive is added to the virtual server to map PHP-FPM to Nginx so that all PHP files be passed on to PHP-FPM for processing:
server
{
…
location ~ [^/]\.php(/|$)
{
fastcgi_pass unix:/run/php7.0-fpm.socket;
include /etc/nginx/conf.d/http_fastcgi.conf;
}
…
}
location ~ [^/]\.php(/|$)
- A regular expression to locate PHP files.
fastcgi_pass unix:/run/php7.0-fpm.socket;
- The socket to which PHP files will be passed.
include /etc/nginx/conf.d/http_fastcgi.conf;
- The file containing the FastCGI parameters to be passed on to PHP-FPM.
Directory indexing
The conf.d/http_index.conf file defines directory index files. If a directory index file exists in a directory and a user navigates to the directory without specifying a particular file within it then the server will return the directory index file instead of an automatically generated index of the contents of the directory by the http_autoindex module or an HTTP 403 response status code.
index index.php index.htm index.html index.xht index.xhtml;
Reinitiation
Nginx is restarted when the configuration is done:
root@computer:~# systemctl reload nginx.service
Directory ownership and permissions
The configuration directory should be protected:
root@computer:~# chown --recursive root:adm /etc/php/ root@computer:~# chmod --recursive 0770 /etc/php/
The log directories should be protected:
root@computer:~# chown --recursive php:adm /var/log/php7.0/ root@computer:~# chown --recursive php:adm /var/log/php7.0-fpm/ root@computer:~# chmod --recursive 0750 /var/log/php7.0/ root@computer:~# chmod --recursive 0750 /var/log/php7.0-fpm/
The temporary upload directory should be protected:
root@computer:~# chown --recursive php:php /var/tmp/php7.0/ root@computer:~# chmod --recursive 0770 /var/tmp/php7.0/
Process manager initiation
PHP-FPM is started when the configuration is done:
root@computer:~# systemctl start php7.0-fpm.service