Differences between revisions 2 and 18 (spanning 16 versions)
Revision 2 as of 2020-01-20 04:35:49
Size: 1822
Comment:
Revision 18 as of 2022-09-26 17:07:51
Size: 3634
Comment:
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
= FastCGI = = PHP-FPM =
Line 3: Line 3:
'''FastCGI''' is a PHP implementation of the Common Gateway Interface (CGI). It works especially well with [[SetupNGINX|NGINX]]. The PHP '''FastCGI Process Manager''' ('''PHP-FPM''') is an implementation of the [[Protocols/CGI|FastCGI]] specification.

<<TableOfContents>>
Line 9: Line 11:
== Setup Files == == Installation ==
Line 11: Line 13:
The recommendation is to either serve web content from: PHP-FPM naturally depends on `php(1)`. See [[PHP#Installation|here]] for help with installation, and [[PHP/Configuration|here]] for help with configuration.
Line 13: Line 15:
 A. a dedicated top-level directory (such as `/srv`) that can be ''easily'' separately-mounted with special settings (i.e. `ro`--the read-only fstab option)
 B. the traditional web content directory, `/var/www`
Most Linux and BSD distributions will offer a `php-fpm` package.
Line 16: Line 17:
Note that any directory can be a mounted device, but there are complications with applying special settings to directories that many package managers expect to be able to write to. Official container images are available from the upstream development team. They are tagged like `php:<version>-fpm`
Line 18: Line 19:
Write the below to `cgi/test.php`, under whichever directory structure you prefer. ----



== Configuration ==

`php-fpm(8)` listens on one or more ports or sockets. Each point of contact is a '''pool'''.

Each pool should have it's own configuration file under `/etc/php/php.fpm.d`. A pool's name (`$pool`) is derived from the section header.

As an example:
Line 21: Line 32:
<?php phpinfo(); ?> [www]
user = www-data
group = www-data

listen = 9000
listen.allowed_clients = 127.0.0.1, 192.168.86.1

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



=== TCP Sockets ===

The above example uses a shorthand: `listen = 9000`. This causes `php-fpm(8)` to listen on all addresses at port 9000.

However, `listen.allowed_clients` overrides this with a client whitelist. This should be comma-separated.

An IPv4 address is specified like `127.0.0.1:9000`; an IPv6 address is specified like `[::1]:9000`.



=== Unix Sockets ===

To use a [[Linux/UnixSocket|Unix socket]] to pass requests, try:

{{{
listen = /run/php-fpm/php-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
}}}



=== Static Process Management ===

A pool spawns and maintains `pm.max_children` number of processes.

{{{
pm = static
pm.max_children = 5
}}}



=== Dynamic Process Management ===

A pool spawns `pm.start_servers` processes. At any given time, some number are 'idle'. The pool tries to keep this number within the range of `pm.min_spare_servers` to `pm.max_spare_servers`, never surpassing `pm.max_children`.

{{{
pm = static
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
}}}



=== On-Demand Process Management ===

A pool spawns processes on-demand up until `pm.max_children`. A process is killed after `pm.process_idle_timeout` has passed.

{{{
pm = ondemand
pm.max_children = 5
pm.process_idle_timeout = 10s
}}}



=== Process Termination ===

`php(1)` scripts are known to leak memory frequently. As such, a regular task is to terminate long-running processes.

A simple solution is to set `pm.max_requests` to any number other than 0. Processes are killed after handling this number of requests.



=== Hardening ===

As a security measure, the allowable script extensions should be set as strictly as possible.

{{{
security.limit_extensions = .php .html .htm
}}}

A pool can be hardened by isolating it to a distinct working directory, or even a chroot.

{{{
chroot = /absolute/path/to/chroot
# or
chdir = relative/or/absolute/path/to/working/directory
}}}

By default, `php-fpm(8)` clears all environment variables. This can be disabled, but a better strategy is to set specific environment variables.

{{{
env[HOSTNAME] = $HOSTNAME
env[TMP] = /tmp
}}}

The same is true of PHP system variables.

{{{
php_admin_value[error_log] = /var/log/php-fpm.log
Line 28: Line 149:
== Setup User ==

Linux permissions and restrictions are most easily done through users, groups, and umasks. The recommendation is to set a specific user and group for the web service. The common options are `www-data` (Apache) and `http` (PHP).

Depending on your ditro, these users and groups may already be created. See details on running `useradd` and `groupadd` in UserSetup.

----
== Usage ==
Line 38: Line 153:
== Setup Software ==

At a minimum, we need: php, php-fpm, fcgi, fcgiwrap, and nginx.

Common additional tools include:
 * apache2-utils (a.k.a. apache-tools, httpd-utils, etc.) for creating .htpasswd files for basic restrictions

=== PHP ===

The primary configuration for PHP is found in `/etc/php/php.ini`. Some distributions carry two versions--`php.ini-production` which is more secure and `php.ini-development` which is more backwards-compatible. Chuck the latter straight into the bin.


=== PHP-FPM ===

=== FastCGI ===
Line 56: Line 155:
---- See [[NGINX/FastCGI#PHP_FPM|here]] for details.
Line 60: Line 159:
== Startup == === Apache ===
Line 62: Line 161:
----



== Maintenance ==
See [[Apache/FastCGI#PHP_FPM|here]] for details.

PHP-FPM

The PHP FastCGI Process Manager (PHP-FPM) is an implementation of the FastCGI specification.


Installation

PHP-FPM naturally depends on php(1). See here for help with installation, and here for help with configuration.

Most Linux and BSD distributions will offer a php-fpm package.

Official container images are available from the upstream development team. They are tagged like php:<version>-fpm


Configuration

php-fpm(8) listens on one or more ports or sockets. Each point of contact is a pool.

Each pool should have it's own configuration file under /etc/php/php.fpm.d. A pool's name ($pool) is derived from the section header.

As an example:

[www]
user = www-data
group = www-data

listen = 9000
listen.allowed_clients = 127.0.0.1, 192.168.86.1

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

TCP Sockets

The above example uses a shorthand: listen = 9000. This causes php-fpm(8) to listen on all addresses at port 9000.

However, listen.allowed_clients overrides this with a client whitelist. This should be comma-separated.

An IPv4 address is specified like 127.0.0.1:9000; an IPv6 address is specified like [::1]:9000.

Unix Sockets

To use a Unix socket to pass requests, try:

listen = /run/php-fpm/php-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

Static Process Management

A pool spawns and maintains pm.max_children number of processes.

pm = static
pm.max_children = 5

Dynamic Process Management

A pool spawns pm.start_servers processes. At any given time, some number are 'idle'. The pool tries to keep this number within the range of pm.min_spare_servers to pm.max_spare_servers, never surpassing pm.max_children.

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

On-Demand Process Management

A pool spawns processes on-demand up until pm.max_children. A process is killed after pm.process_idle_timeout has passed.

pm = ondemand
pm.max_children = 5
pm.process_idle_timeout = 10s

Process Termination

php(1) scripts are known to leak memory frequently. As such, a regular task is to terminate long-running processes.

A simple solution is to set pm.max_requests to any number other than 0. Processes are killed after handling this number of requests.

Hardening

As a security measure, the allowable script extensions should be set as strictly as possible.

security.limit_extensions = .php .html .htm

A pool can be hardened by isolating it to a distinct working directory, or even a chroot.

chroot = /absolute/path/to/chroot
# or
chdir = relative/or/absolute/path/to/working/directory

By default, php-fpm(8) clears all environment variables. This can be disabled, but a better strategy is to set specific environment variables.

env[HOSTNAME] = $HOSTNAME
env[TMP] = /tmp

The same is true of PHP system variables.

php_admin_value[error_log] = /var/log/php-fpm.log


Usage

NGINX

See here for details.

Apache

See here for details.


CategoryRicottone

PHP/FPM (last edited 2023-05-25 17:00:50 by DominicRicottone)