Настройка связки Nginx и PHP-FPM: от базовой конфигурации до продвинутых методов

Раздел: Веб-сервер и PHP -> Настройка и управление 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.
- Nginx php fpm (nginx и php-fpm)

Nginx и PHP-FPM - comments

En
Nginx php fpm (php)