Verification: a143cc29221c9be0

Nginx fastcgi pass php fpm

Nginx fastcgi pass php fpm

1: Установка Apache и PHP-FPM

Сначала нужно установить Apache и PHP-FPM. Также для работы вам понадобится модуль Apache для PHP FastCGI под названием libapache2-mod-fastcgi.

Обновите индекс пакетов:

sudo apt update

Установите необходимые пакеты:

sudo apt install apache2 php-fpm

Модуль Apache FastCGI недоступен в репозитории Ubuntu, поэтому загрузите его с kernel.org и установите с помощью команды dpkg.

wget https://mirrors.edge.kernel.org/ubuntu/pool/multiverse/liba/libapache-mod-fastcgi/libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb

sudo dpkg -i libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb

2: Настройка Apache и PHP-FPM

Теперь нужно настроить порт Apache (8080) и подготовить веб-сервер к поддержке PHP-FPM с помощью модуля mod_fastcgi. Переименуйте конфигурационный файл Apache ports.conf:

sudo mv /etc/apache2/ports.conf /etc/apache2/ports.conf.default

Создайте новый файл ports.conf и укажите в нем порт 8080.

echo "Listen 8080" | sudo tee /etc/apache2/ports.conf

Примечание: Обычно адрес 127.0.0.1:8080 прослушивают прокси-серверы, но в нашем случае это позволит установить в качестве значения переменной РНР SERVER_ADDR loopback IP-адрес вместо внешнего IP-адреса сервера. Нашей целью является такая настройка Apache, при которой веб-сайты, поддерживаемые Apache, не увидят обратного прокси-сервера. Таким образом, Apache нужно настроить для прослушивания порта 8080 на всех IP-адресах.

После этого нужно отредактировать стандартный виртуальный хост Apache. Директива в этом файле обслуживает сайты только на порт 80, это нужно изменить.

Отключите стандартный файл:

sudo a2dissite 000-default

Создайте новый виртуальный хост на основе стандартного файла:

sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/001-default.conf

Откройте новый файл:

sudo nano /etc/apache2/sites-available/001-default.conf

Измените прослушиваемый порт на 8080:


ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

Сохраните и закройте файл. Включите новый файл:

sudo a2ensite 001-default

Перезапустите Apache.

sudo systemctl reload apache2

Установите пакет net-tools:

sudo apt install net-tools

Убедитесь, что веб-сервер прослушивает нужный порт:

sudo netstat -tlpn

Вывод команды должен выглядеть так:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address     Foreign Address      State    PID/Program name
tcp        0      0 0.0.0.0:22        0.0.0.0:*            LISTEN   1086/sshd
tcp6       0      0 :::8080           :::*                 LISTEN   4678/apache2
tcp6       0      0 :::22             :::*                 LISTEN   1086/sshd

3: Настройка модуля mod_fastcgi

По умолчанию Apache обслуживает PHP-страницы с помощью модуля mod_php. Но в данном случае нам нужен дополнительный модуль для PHP-FPM.

Примечание: Если вы выполняете мануал на сервере со стеком LAMP и включенным модулем mod_php, сначала отключите его:

sudo a2dismod php7.4

Добавьте блок настроек для mod_fastcgi. Он зависит от mod_action. Чтобы включить mod_action, введите:

sudo a2enmod actions

Переименуйте существующий конфигурационный файл FastCGI:

sudo mv /etc/apache2/mods-enabled/fastcgi.conf /etc/apache2/mods-enabled/fastcgi.conf.default

Создайте новый файл:

sudo nano /etc/apache2/mods-enabled/fastcgi.conf

Добавьте в файл следующие директивы для передачи запросов к файлам .php на сокет PHP-FPM UNIX:


AddHandler fastcgi-script .fcgi
FastCgiIpcDir /var/lib/apache2/fastcgi
AddType application/x-httpd-fastphp .php
Action application/x-httpd-fastphp /php-fcgi
Alias /php-fcgi /usr/lib/cgi-bin/php-fcgi
FastCgiExternalServer /usr/lib/cgi-bin/php-fcgi -socket /run/php/php7.4-fpm.sock -pass-header Authorization

Require all granted

Сохраните изменения и проверьте ошибки в файле:

sudo apachectl -t

Примечание: Если вы получили предупреждение

Could not reliably determine the server's fully /
qualified domain name, using 127.0.1.1. Set the /'ServerName' directive globally/
to suppress this message.

Проигнорируйте его пока что. Мы настроим директиву ServerName чуть позже.

Если команда вернула Syntax OK, перезапустите Apache.

sudo systemctl reload apache2

4: Тестирование PHP

Убедитесь, что PHP работает должным образом. Для этого создайте файл /var/www/html/info.php и откройте его в браузере.

В файл нужно поместить функцию:

echo "" | sudo tee /var/www/html/info.php

Обратите внимание: если вы выполнили начальную настройку сервера согласно этому мануалу, вы, вероятно, включили брандмауэр для Apache. Давайте откроем доступ к нашему IP-адресу через порт 8080, который в настоящее время заблокирован. Мы ограничим общий доступ к этому порту в разделе 10.

Чтобы открыть порт в брандмауэре, введите команду:

sudo ufw allow 8080

Поскольку мы собираемся защитить наши домены Apache, давайте проверим, поддерживает ли брандмауэр трафик TLS на порт 443.

Включите профиль Apache Full, чтобы разрешить трафик на порты 80 и 443:

sudo ufw allow "Apache Full"

Теперь проверьте статус вашего брандмауэра:

sudo ufw status

Если вы выполнили предварительные требования к мануалу, результат будет выглядеть так:

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Apache Full                ALLOW       Anywhere
8080                       ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Apache Full (v6)           ALLOW       Anywhere (v6)
8080 (v6)                  ALLOW       Anywhere (v6)

Теперь откройте info.php  в браузере:

http://your_ip_address:8080/info.php

На экране появится список настроек PHP.

В верхней части страницы найдите Server API, в этой строке должно быть указано FPM/FastCGI. Затем найдите раздел PHP Variables, строку SERVER_SOFTWARE. Она должна содержать Apache и Ubuntu. Это подтверждает, что mod_fastcgi включен и Apache поддерживает PHP-FPM для обработки файлов PHP.

5: Создание виртуального хоста Apache

Создайте виртуальные хосты Apache для доменов apache1.your_domain и apache2.your_domain. Сначала создайте корневые каталоги для этих сайтов.

sudo mkdir -v /var/www/apache1.your_domain /var/www/apache2.your_domain

Создайте index-файлы для каждого сайта:

echo "

Apache 1

" | sudo tee /var/www/apache1.your_domain/index.html
echo "

Apache 2

" | sudo tee /var/www/apache2.your_domain/index.html

Чтобы протестировать PHP, создайте файл phpinfo() для каждого сайта.

echo "" | sudo tee /var/www/apache1.your_domain/info.php
echo "" | sudo tee /var/www/apache2.your_domain/info.php

Затем создайте файл виртуального хоста для домена apache1.your_domain.

sudo nano /etc/apache2/sites-available/apache1.your_domain.conf

Поместите в него следующие строки:


ServerName apache1.your_domain
ServerAlias www.apache1.your_domain
DocumentRoot /var/www/apache1.your_domain

AllowOverride All

Строка AllowOverride All включает поддержку .htaccess.

Теперь файл содержит базовые директивы виртуального хоста.

Читайте также: Настройка виртуальных хостов Apache в Ubuntu 18.04

Сохраните и закройте файл. Теперь создайте такой же файл для apache2.your_domain.

sudo nano /etc/apache2/sites-available/apache2.your_domain.conf

Вставьте в него такие строки:


ServerName apache2.your_domain
ServerAlias www.apache2.your_domain
DocumentRoot /var/www/apache2.your_domain
AllowOverride All

Сохраните и закройте файл.

Итак, теперь виртуальные хосты Apache готовы. Чтобы включить сайты, используйте команду a2ensite, которая создаст симлинки на виртуальные хосты в каталоге sites-enabled.

sudo a2ensite apache1.your_domain
sudo a2ensite apache2.your_domain

Проверьте синтаксис Apache:

sudo apachectl -t

Если ошибок нет, перезапустите веб-сервер:

sudo systemctl reload apache2

Если в синтаксисе обнаружены ошибки, сначала исправьте их.

Чтобы убедиться, что сайты работают и каждый сайт отображает содержимое файла index.html, откройте в браузере:

http://apache1.your_domain:8080
http://apache2.your_domain:8080

На экране появится:

Apache 1

и

Apache 2

Теперь убедитесь, что PHP работает. Для этого откройте файлы info.php каждого сайта в браузере. Эти файлы доступны по ссылкам:

http://apache1.your_domain:8080/info.php
http://apache2.your_domain:8080/info.php

На экране должен появиться список настроек PHP (как в шаге 4).

Теперь Apache обслуживает два сайта по порту 8080. Перейдем к настройке Nginx.

6: Установка и настройка Nginx

Теперь нужно установить Nginx и настроить виртуальные хосты для доменов nginx1.your_domain и nginx2.your_domain.

Читайте также: Установка Nginx в Ubuntu 20.04

Установите Nginx:

sudo apt install nginx

Удалите симлинк стандартного виртуального хоста, он в дальнейшем не понадобится нам.

sudo rm /etc/nginx/sites-enabled/default

Теперь нужно создать новые виртуальные хосты для сайтов. Мы будем следовать той же процедуре, которую использовали для настройки Apache. Сначала создайте каталоги для них:

sudo mkdir -v /usr/share/nginx/nginx1.your_domain /usr/share/nginx/nginx2.your_domain

Мы будем хранить сайты Nginx в /usr/share/nginx, где Nginx ищет их по умолчанию. Вы можете разместить их в каталоге /var/www/html вместе с сайтами Apache, но для настройки Nginx удобнее разделить сайты.

Затем создайте файлы index и phpinfo():

echo "

Nginx 1

" | sudo tee /usr/share/nginx/nginx1.your_domain/index.html
echo "

Nginx 2

" | sudo tee /usr/share/nginx/nginx2.your_domain/index.html
echo "" | sudo tee /usr/share/nginx/nginx1.your_domain/info.php
echo "" | sudo tee /usr/share/nginx/nginx2.your_domain/info.php

Теперь создайте виртуальный хост для nginx1.your_domain.

sudo nano /etc/nginx/sites-available/nginx1.your_domain

Nginx называет области server {. . .} конфигурационного файла блоками server, которые являются виртуальными хостами. Создайте блок server для первого сайта, nginx1.your_domain. Директива default_server сделает этот файл виртуальным хостом по умолчанию. Он будет обрабатывать HTTP-запросы, которые не соответствуют другим виртуальным хостам.

server {
listen 80 default_server;
root /usr/share/nginx/nginx1.your_domain;
index index.php index.html index.htm;
server_name nginx1.your_domain www.nginx1.your_domain;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
include snippets/fastcgi-php.conf;
}
}

Сохраните и закройте файл. Теперь создайте виртуальный хост для nginx2.your_domain.

sudo nano /etc/nginx/sites-available/nginx2.your_domain

Вставьте в этот файл такие строки:

server {
root /usr/share/nginx/nginx2.your_domain;
index index.php index.html index.htm;
server_name nginx2.your_domain www.nginx2.your_domain;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
include snippets/fastcgi-php.conf;
}
}

Сохраните и закройте файл. Чтобы включить сайты, создайте симлинки для них:

sudo ln -s /etc/nginx/sites-available/nginx1.your_domain /etc/nginx/sites-enabled/nginx1.your_domain
sudo ln -s /etc/nginx/sites-available/nginx2.your_domain /etc/nginx/sites-enabled/nginx2.your_domain

Проверьте синтаксис Nginx:

sudo nginx -t

Если ошибок нет, перезапустите веб-сервер:

sudo systemctl reload nginx

Теперь попробуйте открыть в браузере файлы phpinfo() для виртуальных хостов Nginx.

http://nginx1.your_domain/info.php
http://nginx2.your_domain/info.php

Проверьте раздел PHP Variables.

Строка [“SERVER_SOFTWARE”] должна показывать nginx (это значит, что файлы обслуживаются сервером Nginx). В [“DOCUMENT_ROOT”] должен находиться путь к root-каталогу сайта.

Теперь веб-сервер Nginx установлен и поддерживает два сайта.

7: Настройка Nginx для поддержки виртуальных хостов Apache

Теперь нужно создать дополнительный виртуальный хост Nginx для нескольких доменов в директиве server_name. Запросы к этим доменам будут проксироваться на Apache.

Создайте новый файл:

sudo nano /etc/nginx/sites-available/apache

Добавьте в него следующий блок настроек. Он задаёт имена сайтов Apache и проксирует их запросы. В proxy_pass укажите внешний IP.

server {
listen 80;
server_name apache1.your_domain www.apache1.your_domain apache2.your_domain www.apache2.your_domain;
location / {
proxy_pass http://your_server_ip:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

Сохраните и закройте файл. Создайте симлинк:

sudo ln -s /etc/nginx/sites-available/apache /etc/nginx/sites-enabled/apache

Проверьте настройки на наличие ошибок:

sudo nginx -t

Перезапустите Nginx, если ошибок не обнаружено.

sudo systemctl reload nginx

Откройте браузер и перейдите по ссылке:

http://apache1.your_domain/info.php

Найдите раздел PHP Variables. Переменные SERVER_SOFTWARE и DOCUMENT_ROOT подтверждают, что запрос был обработан Apache. Переменные HTTP_X_REAL_IP и HTTP_X_FORWARDED_FOR были добавлены сервером Nginx и отображают внешний IP-адрес текущей машины.

Теперь Apache использует Nginx в качестве обратного прокси-сервера. Нужно установить переменную Apache, REMOTE_ADDR. Она позволяет «скрыть» прокси-сервер.

8: Установка и настройка модуля mod_rpaf

Теперь нужно установить модуль mod_rpaf, который будет переопределять значения REMOTE_ADDR, HTTPS и HTTP_PORTс помощью значений, предоставленных обратным прокси-сервером. Без этого модуля некоторые приложения PHP

могут потребовать изменений в коде. Модуль можно найти в репозитории Ubuntu, его пакет называется libapache2-mod-rpaf. Однако этот пакет устаревший и не поддерживает некоторых директив. Потому лучше скомпилировать модуль из исходного кода.

Чтобы собрать модуль, установите пакеты:

sudo apt install unzip build-essential apache2-dev

Загрузите последний релиз с GitHub:

wget https://github.com/gnif/mod_rpaf/archive/stable.zip

Распакуйте его:

unzip stable.zip

Перейдите в рабочий каталог:

cd mod_rpaf-stable

Скомпилируйте и установите модуль:

make
sudo make install

В каталоге mods-available создайте файл для модуля rpaf.

sudo nano /etc/apache2/mods-available/rpaf.load

Вставьте в файл следующую строку:

LoadModule rpaf_module /usr/lib/apache2/modules/mod_rpaf.so

Сохраните и закройте файл.

Создайте файл для настроек модуля:

sudo nano /etc/apache2/mods-available/rpaf.conf

Добавьте в конфигурационный файл следующие строки:


RPAF_Enable             On
RPAF_Header             X-Real-Ip
RPAF_ProxyIPs           your_server_ip
RPAF_SetHostName        On
RPAF_SetHTTPS           On
RPAF_SetPort            On

Этот файл содержит следующие настройки:

  • RPAF_Header: заголовок для клиентского IP-адреса.
  • RPAF_ProxyIPs: IP прокси-сервера, для которого нужно отредактировать запросы.
  • RPAF_SetHostName: обновление имени виртуального хоста для ServerNameиServerAlias.
  • RPAF_SetHTTPS: настраивает переменную среды HTTPS на основе значения X-Forwarded-Proto.
  • RPAF_SetPort: устанавливает переменную среды SERVER_PORT (эта настройка полезна для Apache на SSL).

Примечание: Подробную информацию о настройках вы найдете в README модуля.

Сохраните файл rpaf.conf и включите модуль:

sudo a2enmod rpaf

Эта команда создаст символьную ссылку файлов rpaf.load и rpaf.conf в каталоге mods-enabled. Проверьте настройки:

sudo apachectl -t

Перезапустите Apache, если ошибок не обнаружено.

sudo systemctl reload apache2

Откройте страницу phpinfo() одного из сайтов Apache и найдите раздел PHP Variables. Переменная REMOTE_ADDR теперь должна содержать IP локального сервера.

9: Поддержка HTTPS с помощью Let’s Encrypt (опционально)

Теперь нужно создать SSL-сертификаты для сайтов Apache. Получите бесплатные доверенные сертификаты от Let’s Encrypt.

Nginx поддерживает терминацию SSL, потому можно настроить SSL, не изменяя настроек Apache.

Модуль mod_rpaf установит все переменные Apache, необходимые для поддержки SSL.

Для начала создайте для обоих доменов блок server {…}, чтобы у каждого из них был свой сертификат. Откройте /etc/nginx/sites-available/apache:

sudo nano /etc/nginx/sites-available/apache

Отредактируйте файл, создав блок server для apache1.your_domain and apache2.your_domain:

server {
listen 80;
server_name apache1.your_domain www.apache1.your_domain;
location / {
proxy_pass http://your_server_ip:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
server_name apache2.your_domain www.apache2.your_domain;
location / {
proxy_pass http://your_server_ip:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

Сертификаты TLS/SSL можно сгенерировать с помощью клиента Certbot. Его плагин для Nginx автоматически перенастроит веб-сервер и обновит конфигурационный файл.

Установите Certbot:

sudo snap install --classic certbot

Затем используйте команду certbot, чтобы сгенерировать сертификаты для apache1.your_domain и www.apache1.your_domain:

sudo certbot --agree-tos --no-eff-email --email your-email --nginx -d apache1.your_domain -d www.apache1.your_domain

С помощью этой команды Certbot сможет использовать плагин nginx; флаг –d позволяет указать домены, для которых предназначен сертификат.

Выполните следующую команду для второго домена:

sudo certbot --agree-tos --no-eff-email --email your-email --nginx -d your_domain -d www.apache2.your_domain

Попробуйте открыть один из этих сайтов в браузере с префиксом https://.

https://apache1.your_domain/info.php

На появившейся странице найдите раздел PHP Variables. Для переменной SERVER_PORT установлено значение 443, а HTTPS – on, как если бы веб-сервер Apache был напрямую доступен через HTTPS.

Теперь давайте отключим прямой доступ к Apache.

10: Блокирование прямого доступа к Apache (опционально)

Apache слушает порт 8080 на внешнем IP-адресе, потому доступ к нему может получить любой желающий. Этот доступ можно заблокировать с помощью брандмауэра IPtables.

sudo iptables -I INPUT -p tcp --dport 8080 ! -s your_server_ip -j REJECT --reject-with tcp-reset

Примечание: Вместо your_server_ip укажите IP-адрес сервера.

Теперь порт 8080 блокируется брандмауэром, и доступ к Apache закрыт.

Откройте браузер и попробуйте получить доступ к одному из сайтов Apache.

http://apache1.your_domain:8080

Браузер должен выдать сообщение об ошибке «Unable to connect» или «Webpage is not available». Директива tcp-reset позволяет скрыть от посторонних разницу между портами.

Примечание: Правила IPtables сбрасываются при каждой перезагрузке сервера. Чтобы сохранить их, используйте iptables-persistent.

Читайте также: Настройка фаервола с помощью IPTables на Ubuntu 14.04

Prerequisites

Shell access with sudo privileged account to Ubuntu 20.04 system.

Step 1 – Installing Nginx

Nginx packages are available under default repositories. SSH to your Ubuntu 20.04 LTS system with sudo privileges account and install Nginx web server from the official repository.

sudo apt update 
sudo apt install nginx

Step 2 – Installing PHP

For the PHP installation we recommend to use ppa:ondrej/php PPA, which provides latest PHP versions for Ubuntu systems. Use the below couple of commands to add the PPA to your system.

sudo apt install software-properties-common
sudo add-apt-repository ppa:ondrej/php

Then install PHP 7.4 the latest version available on the day of writing this tutorial. Simply execute follows commands for the installation of PHP and PHP-FPM packages.

apt update
sudo apt install php7.4 php7.4-fpm

Note:- When you are using PHP-FPM. All the PHP modules configurations are residing under /etc/php/7.4/fpm directory. You can read more about enable/disable PHP modules.

After installing above packages php7.4-fpm service will automatically be started. You can make sure by typing below command on terminal.

sudo systemctl status php7.4-fpm

● php7.4-fpm.service - The PHP 7.4 FastCGI Process Manager
     Loaded: loaded (/lib/systemd/system/php7.4-fpm.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2020-06-16 05:15:57 UTC; 1 day 10h ago
       Docs: man:php-fpm7.4(8)
   Main PID: 882699 (php-fpm7.4)
     Status: "Processes active: 0, idle: 2, Requests: 2, slow: 0, Traffic: 0req/sec"
      Tasks: 3 (limit: 2283)
     Memory: 12.1M
     CGroup: /system.slice/php7.4-fpm.service
             ├─882699 php-fpm: master process (/etc/php/7.4/fpm/php-fpm.conf)
             ├─882714 php-fpm: pool www
             └─882715 php-fpm: pool www

Jun 16 05:15:57 tecadmin systemd[1]: Starting The PHP 7.4 FastCGI Process Manager...
Jun 16 05:15:57 tecadmin systemd[1]: Started The PHP 7.4 FastCGI Process Manager.

Step 4 – Configuring NGINX with FPM

Next, create a Nginx server block configuration file to run PHP with FPM. Create and Edit a VirtualHost host configuration file in a text editor. You can create new VirtualHost as per your requirements, so make sure to enable any new VirtualHost.

sudo vim /etc/nginx/sites-available/example.com

Use the below basic Nginx Virtual host configuration with php fpm settings. Update the configuration as followings.

server {

        listen 80;

        root /var/www/html;

        index index.php index.html index.htm;

        server_name example.com;

        location / {

            try_files $uri $uri/ =404;

        }

        location ~ \.php$ {

            include snippets/fastcgi-php.conf;

            fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;

        }

}

Save your changes to the configuration file and create a link to site enabled directory.

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com 

Then restart Nginx service to reload the changes.

sudo systemctl restart nginx

Step 4 – Testing the Setup

Your server setup is completed now. Let’s create a PHP script with phpinfo() function and place it to your server document root. Use below command to create php script:

echo "" > /var/www/html/info.php

Then access info.php viausing server IP address (for default VirtualHost) or configured domain in Nginx VirtualHost.

how to setup nginx php fpm ubuntu 20.04

Slide down the page and see the value of $_SERVER[‘SERVER_SOFTWARE’]. This will the show the web server details.

Настройка PHP-FPM

Менеджер процессов PHP-FPM может запускать несколько процессов обработчиков. Обычно для каждого отдельного сайта принято использовать отдельный обработчик, это позволяет распределить нагрузку и отслеживать статистику по каждому сайту. Поэтому есть общий конфигурационный файл php-fpm и конфигурационный файл для каждого обработчика, который обычно называется конфигурационным файлом пула. Обработчик принято называть пулом потому что на самом деле обработкой занимается не один процесс, а целая группа процессов, у каждого из которых есть несколько потоков. Всё это обеспечивает быстрое выполнение скриптов.

1. Установка компонентов

Сервис php-fpm поставляется вместе с интерпретатором php. Установка php-fpm Ubuntu выполняется такой командой:

sudo apt install php-fpm

Кроме того нам понадобится веб-сервер Nginx, потому что php-fpm чаще всего используется вместе с этим веб-сервером:

sudo apt install nginx

2. Конфигурационные файлы

В этой инструкции мы будем рассматривать настройку PHP-FPM на примере Ubuntu. Основной конфигурационный файл находится в такому пути:

ls /etc/php/7.4/fpm/php-fpm.conf

Обратите внимание, что это не php.ini файл, а файл настройки именно FPM процессов. Файл php.ini находится в этой же папке:

ls /etc/php/7.4/fpm/php.ini

А вот файлы конфигурации пулов находятся в каталоге /etc/php/7.4/fpm/pool.d/. По умолчанию там находится файл пула по умолчанию www.conf:

ls /etc/php/7.4/fpm/pool.d/

Вы можете использовать его в своей конфигурации или копировать для создания новых пулов.

3. Создание пула

Скопируйте файл пула, например losst.conf в папке /etc/php/7.4/fpm/pool.d/ скопируйте в него содержимое файла www.conf. В конце статьи я приведу полностью рабочий конфигурационный файл, но лучше всё же использовать конфигурацию вашей версии PHP:

cp /etc/php/7.4/fpm/pool.d/www.conf /etc/php/7.4/fpm/pool.d/losst.conf

Теперь откройте этот файл в текстовом редакторе, например в vim:

sudo vi /etc/php/7.4/fpm/pool.d/losst.conf

Первым делом вам нужно выбрать имя пула в квадратных скобках в самой верхней части файла, например, losst, это имя можно использовать в конфигурации с помощью переменной $pool, а ещё оно будет отображаться в менеджере процессов:

Далее надо изменить группу и пользователя, от имени которых будут запускаться процессы пула. Это важно, поскольку у процесса должен быть доступ к файлам PHP, которые надо выполнить. Обычно в Ubuntu для таких целей используется пользователь и группа www-data. От имени этого же пользователя обычно запускается веб-сервер:

Обычно, если вы получаете ошибку permission denied при интерпретации php файлов в php-fpm, означает, что процесс php-fpm запущен от имени не того пользователя или включена строгая политика SELinux.

4. Настройка сокета

Дальше нужно настроить каким образом Nginx или другой веб-сервер будет обращаться к PHP-FPM. Как я уже говорил выше, можно настроить ожидание соединений на TCP порту. Обычно используются порты 9000, 9001, 9002 и так далее. В данном случае надо передать IP адрес на котором следует слушать и порт. Лучше использовать локальный IP адрес 127.0.0.1, чтобы к сервису никто не мог подключится из интернета. Второй вариант - использовать файловый Unix сокет, тогда надо просто передать путь к файлу сокета. В данном примере используется сетевой сокет 127.0.0.1:9000. Вид сокета не имеет значения, но сетевой использовать удобнее:

Если вы используйте файловый сокет, к нему должен быть доступ у веб-сервера, поэтому надо сделать владельцами файла того пользователя и группу, от имени которых запущен веб-сервер, в данном случае www-data и дать им все права на него:

listen.owner = www-data
listen.group = www-data
listen.mode = 0660

Если сокет сетевой, то в этом нет необходимости. Для сетевого сокета можно дополнительно указать с каких адресов можно к нему подключаться. Например, только от 127.0.0.1:

listen.allowed_clients = 127.0.0.1

5. Настройка процессов

С помощью параметра pm можно настроить сколько дочерних процессов будет запускаться для этого пула и когда. Есть три режима работы:

  • dynamic - процессы создаются в зависимости от нагрузки и настроек, если нагрузки нет, всё равно работает определённое количество процессов;
  • ondemand - процессы создаются как только возникает нагрузка;
  • static - количество процессов всегда одинаковое, указанное в настройках.

Режим static не выгоден, потому что вне зависимости от нагрузки потребляется много памяти и процессорного времени на поддержание работы процессов. Более интересны режимы ondemand и dynamic. Давайте будем использовать режим dynamic. Этот режим имеет три настройки:

  • pm.max_children - очень важный параметр, который работает для всех трёх режимов, означает максимально возможное количество дочерних процессов, если значение будет слишком маленьким, то при возрастании нагрузки, лимит исчерпается и ваш сайт начнёт тупить, если слишком большим - исчерпается оперативная память и что-то упадёт;
  • pm.start_servers - указывает сколько процессов запускать при старте сервиса;
  • pm.min_spare_servers - минимальное количество процессов в режиме ожидания (ничего не обрабатывающих), если количество процессов меньше, будет создан ещё один;
  • pm.max_spare_server - максимальное количество процессов в режиме ожидания, если количество процессов будет больше, лишние будут завершены;

Для режима static надо указать только pm.max_children. Для режима ondemand кроме pm.max_children надо указать pm.process_idle_timeout этот параметр означает через какой промежуток времени простоя процесс будет завершен.

Давайте разберемся с режимом dynamic. Запускать много дочерних процессов при старте не надо, в большинстве случаев 2-3 будет достаточно:

pm.start_servers = 3

Минимальное количество процессов в режиме ожидания тоже большое не нужно, это запас, чтобы php-fpm смог быстро обработать новые запросы не тратя время на запуск новых процессов. Однако это значение должно быть не меньше pm.start_servers, иначе ничего не заработает:

pm.min_spare_servers = 3

Максимальное количество процессов определяет как быстро процессы будут завершаться при падении нагрузки, можно оставить 10 процессов:

pm.max_spare_servers = 10

Параметр pm.max_children настройте под себя, обычно достаточно 20-30 процессов, но всё зависит от нагрузки и количества оперативной памяти, если памяти мало лучше пожертвовать производительностью и установить меньшее значение:

pm.max_children = 30

Почти готово. Но есть ещё одна проблема. Если дочерние процессы работают слишком долго, в них накапливаются утечки памяти, и рано или поздно на сервере память закончится. Чтобы этого избежать можно настроить автоматическое завершение процесса после выполнения определённого количества запросов, например, 1000:

pm.max_requests = 1000

6. Настройка статистики

Для подбора оптимального значения pm.max_children вам может понадобиться посмотреть статистику в реальном времени сколько процессов запущено, сколько из них находится в ожидании, а также какая длина очереди ожидающих выполнения запросов. Для включения вывода статистики просто добавьте такую строчку:

pm.status_path = /status

7. Настройка php.ini

Несмотря на то, что есть общий файл php.ini для всех пулов, вы можете менять настройки прямо в файле пула, для этого используются директивы php_admin_value и php_admin_flag. Первая используется для установки строковых значений, а вторая - для флагов. У директив есть альтернативы: php_value и php_flag, они отличаются только тем, что их можно перезаписать с помощью функции ini_set, а значения заданные с помощью директив с приставкой admin перезаписать нельзя.

Например:

php_admin_flag[display_errors] = off
php_admin_value[error_log] = /var/log/fpm-php.losst.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 32M

Когда все настройки завершены, не забудьте сохранить изменения и перезапустить php-fpm:

sudo systemctl restart php7.4-fpm

8. Настройка веб-сервера

Для того чтобы всё протестировать придётся настроить ещё и веб-сервер. В конфигурационный файл виртуального хоста Nginx надо добавить такие строки:

location /status {
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
}

Первая секция позволяет смотреть статистику работы php-fpm открыв в браузере ссылку /status, которую мы ранее указали в настройках. Вторая секция обрабатывает всё остальные файлы php. Первая строка второй секции разбивает путь к скрипту по регулярному выражению на две части: $fastcgi_script_name и $fastcgi_path. Первая переменная нам понадобится в следующей же строчке, где с помощью условия проверяется существует ли такой файл, и если нет, то возвращается 404.

Дальше надо импортировать файл fastcgi_params, в котором передаются все переменные, которые потом будут доступны в массиве $_SERVER из скрипта. В следующей строчке объявляется ещё один важный параметр, которого нет в fastcgi_params, потому что он использует переменную $fastcgi_script_name, полученную ранее. Именно по нему php-fpm определяет путь к скрипту, который надо выполнить, если его не передать, вы получите пустой экран.

Последняя директива fastcgi_pass указывает как надо передавать данные php-fpm, сюда можно передать путь к файлу сокету, на котором слушает сервис или IP адрес и порт. В данном случае используется ранее настроенный 127.0.0.1:9000. После завершения настройки перезапустите Nginx:

sudo systemctl restart nginx

Теперь вы можете открыть в браузере страницу статистики, как видите всё работает:

Можно ещё создать файл phpinfo.php с текстом в каталоге веб-сервера и посмотреть настройки php, например, memory_limit, заданный в файле конфигурации пула работает:

Настройка веб-сервера может очень сильно отличаться в зависимости от ваших требований. Здесь приведен только общий пример, чтобы проверить работоспособность и верность настройки.