Настройка связки Nginx и PHP-FPM: от базовой конфигурации до продвинутых методов
Взаимодействие Nginx и PHP-FPM: основные варианты
Как организовать передачу PHP-запросов от Nginx к PHP-FPM с минимальной задержкой?
Unix-сокет обеспечивает наименьшую задержку и подходит для однопроцессорных систем или когда PHP-FPM работает на том же хосте. Для настройки необходимо установить пакеты nginx и php-fpm (например, php8.1-fpm). В конфигурации пула /etc/php/8.1/fpm/pool.d/www.conf изменить директиву listen:
listen = /run/php/php8.1-fpm.sockЗатем в блоке server Nginx добавить location для обработки PHP:
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}После перезапуска сервисов Nginx передает запросы на сокет. Типичная ошибка - 502 Bad Gateway из-за отсутствия файла сокета. Решение: проверить запущен ли php-fpm (systemctl status php8.1-fpm), права на сокет (должны быть доступны пользователю Nginx), и путь в fastcgi_pass. Также может потребоваться скорректировать listen.owner и listen.group в конфиге пула.
Ошибка 502 Bad Gateway также возникает, если Nginx не может подключиться к сокету из-за разных пользователей. Рекомендуется установить listen.mode = 0660 и добавить пользователя Nginx в группу пользователя PHP-FPM (обычно www-data).
Когда TCP-соединение предпочтительнее Unix-сокета?
Если PHP-FPM размещается на другом сервере или требуется балансировка нагрузки. В конфигурации пула задают listen = 127.0.0.1:9000 или внешний IP. В Nginx указывают fastcgi_pass 127.0.0.1:9000;.
Проблема: порт может быть занят другим сервисом. Используйте netstat -tulpn | grep 9000 для проверки. При внешнем IP необходимо открыть порт в firewall.
Как разделить разные сайты с разными настройками PHP?
Создаются несколько пулов в /etc/php/8.1/fpm/pool.d/ с уникальными именами. В каждом пуле задаётся свой listen (разные сокеты или порты) и параметры pm. В Nginx для каждого сайта - свой server block с соответствующим fastcgi_pass. Пример пула site1.conf:
[site1]
user = site1
listen = /run/php/php8.1-site1.sock
listen.mode = 0660
pm = dynamic
pm.max_children = 10Как повысить производительность с помощью кэширования ответов PHP?
FastCGI-кэш позволяет сохранять вывод PHP-скриптов. В глобальном контексте Nginx задают fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=phpcache:10m;. В location PHP указывают:
fastcgi_cache phpcache;
fastcgi_cache_valid 200 1h;
fastcgi_cache_use_stale error timeout updating;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
add_header X-Cache $upstream_cache_status;Не кэшируются страницы с куками сессии и POST-запросы.
Ошибка: кэширование может вернуть устаревшие данные. Настройте очистку кэша или используйте fastcgi_cache_bypass для административных страниц.
Расширенная конфигурация WordPress с Nginx и PHP-FPM
# /etc/nginx/sites-available/wordpress
upstream php_backend {
server unix:/run/php/php8.1-fpm.sock;
}
server {
listen 80;
server_name example.com;
root /var/www/wordpress;
index index.php;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass php_backend;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_buffering on;
fastcgi_buffer_size 32k;
fastcgi_buffers 8 16k;
}
}При запросе curl -I http://example.com заголовок X-Cache: MISS при первом обращении.
Динамическое управление процессами в пуле
[dynamic_pool]
listen = /run/php/dynamic.sock
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 8
pm.process_idle_timeout = 30sСтатус пула через pm.status_path показывает количество активных процессов.
FastCGI кэш для высоконагруженного сайта
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=wpcache:100m inactive=60m;
server {
...
set $skip_cache 0;
if ($request_method = POST) { set $skip_cache 1; }
if ($cookie_wordpress_logged_in) { set $skip_cache 1; }
location ~ \.php$ {
fastcgi_cache wpcache;
fastcgi_cache_valid 200 60m;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
...
}
}Заголовок X-Cache: HIT при повторном запросе.
Решение ошибки No input file specified
# Неправильная конфигурация
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# Правильная
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;Без корректного SCRIPT_FILENAME возвращается ошибка 404.
Разные версии PHP в одном сервере
# Пул PHP 7.4
[pool74]
listen = /run/php/php7.4-fpm.sock
# Пул PHP 8.1
[pool81]
listen = /run/php/php8.1-fpm.sock
# Nginx для сайта с PHP 7.4
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
# Nginx для другого сайта
fastcgi_pass unix:/run/php/php8.1-fpm.sock;Каждый сайт обрабатывается своей версией PHP.