Nginx + PHP-FPM: как работает связка и решаем ошибки 502 и 504
Подробное руководство по настройке Nginx с PHP-FPM: разбор архитектуры, типичные проблемы и их решения, настройка таймаутов, работа с ошибками 502 и 504. Практическое руководство для системных администраторов и веб-разработчиков.
Требования
- Базовое знание Linux/терминала
- Понимание работы Nginx
- Доступ к серверу (VPS или локальный)
- Основы PHP
Nginx + PHP-FPM: как работает связка и почему возникают ошибки 502 и 504
Часть 3 серии про Nginx В прошлой части мы разобрали virtual hosts и структуру сайтов. Теперь переходим к главному: как Nginx выполняет PHP-код и что такое PHP-FPM на самом деле.
Введение
Nginx + PHP-FPM — это стандартная связка для обработки PHP-приложений в продакшене. Понимание принципов её работы критически важно для диагностики и решения проблем.
В этой статье разберём:
- архитектуру взаимодействия Nginx и PHP-FPM;
- типичные ошибки 502 и 504 и их причины;
- практические методы диагностики;
- настройку таймаутов и пулов процессов;
- полные примеры конфигураций для реальных проектов.
Главная мысль, которую нужно понять сразу
👉 Nginx НЕ исполняет PHP. Вообще. Никогда.
Nginx — это веб-сервер, который:
- принимает HTTP-запросы;
- анализирует URL и заголовки;
- передаёт PHP-файлы в PHP-FPM через протокол FastCGI;
- ждёт результат выполнения;
- отдаёт ответ клиенту.
Если PHP-FPM не отвечает или работает некорректно — проблема не в Nginx, а в конфигурации или состоянии PHP-FPM.
Что такое PHP-FPM простыми словами
PHP-FPM (FastCGI Process Manager) — это менеджер процессов PHP, который:
- запускает и управляет PHP-процессами;
- поддерживает пул воркеров для параллельной обработки запросов;
- принимает запросы от Nginx через протокол FastCGI;
- выполняет PHP-код из
.phpфайлов; - возвращает результат выполнения (HTML, JSON и т.д.) обратно в Nginx.
Схема взаимодействия выглядит так:
Браузер
↓ HTTP-запрос
Nginx
↓ FastCGI-протокол
PHP-FPM
↓ выполнение кода
PHP-процесс
↓ результат
PHP-FPM → Nginx → Браузер
Как Nginx определяет, что файл — PHP
Nginx использует директиву location с регулярным выражением для определения PHP-файлов:
location ~ \.php$ {
# конфигурация обработки PHP
}
Это означает:
- любой запрос, URL которого заканчивается на
.php; - будет обработан этим блоком
location; - и передан в PHP-FPM для выполнения.
Базовая конфигурация Nginx для PHP
Минимально рабочая конфигурация для обработки PHP:
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
Разберём каждую директиву:
include fastcgi_params;— подключает стандартные параметры FastCGI;fastcgi_pass— указывает, куда передавать запрос (сокет или TCP);fastcgi_index— индексный файл по умолчанию;fastcgi_param SCRIPT_FILENAME— самая важная строка, указывает PHP-FPM путь к файлу для выполнения.
fastcgi_pass — способы подключения к PHP-FPM
Есть два варианта подключения Nginx к PHP-FPM.
Вариант 1. Unix-сокет (рекомендуется)
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
Преимущества:
- быстрее (нет сетевых задержек);
- безопаснее (нет сетевого доступа);
- стандартный способ для одного сервера;
- меньше накладных расходов.
Недостатки:
- работает только локально на том же сервере.
Вариант 2. TCP-подключение
fastcgi_pass 127.0.0.1:9000;
Используется, если:
- PHP-FPM запущен в Docker-контейнере;
- PHP-FPM находится на другом сервере;
- нужна сетевая изоляция между процессами.
Где узнать путь к сокету PHP-FPM
Путь к сокету указывается в конфигурационном файле пула PHP-FPM.
Ubuntu / Debian
/etc/php/8.2/fpm/pool.d/www.conf
Ищите строку:
listen = /run/php/php8.2-fpm.sock
CentOS / Rocky Linux
/etc/php-fpm.d/www.conf
👉 Этот путь должен точно совпадать с fastcgi_pass в конфигурации Nginx.
SCRIPT_FILENAME — самая важная строка
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
Если эта строка неправильная или отсутствует → 502 Bad Gateway гарантирован.
Что здесь происходит:
$document_root— значение директивыrootиз блокаserver;$fastcgi_script_name— путь к PHP-файлу из URL запроса;- результат — полный абсолютный путь к файлу на диске.
Пример:
URL запроса: /index.php
root: /var/www/site/public
Итоговый SCRIPT_FILENAME:
/var/www/site/public/index.php
PHP-FPM использует этот путь для загрузки и выполнения файла.
index.php и try_files — правильная связка
Для современных PHP-фреймворков (Laravel, Symfony, Bitrix, WordPress) критически важно правильно настроить try_files:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
Что это даёт:
- если файл существует — отдаём его напрямую;
- если это директория — пробуем найти индексный файл;
- если ничего не найдено — передаём запрос в
index.phpс сохранением query string; - идеально для фреймворков с роутингом через
index.php.
Полный пример server block для PHP-проекта
Продакшен-адекватная конфигурация для PHP-приложения:
server {
listen 80;
server_name site.ru www.site.ru;
root /var/www/site.ru/public;
index index.php index.html;
access_log /var/www/site.ru/logs/access.log;
error_log /var/www/site.ru/logs/error.log;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# Таймауты (подробнее ниже)
fastcgi_read_timeout 60s;
fastcgi_connect_timeout 60s;
}
# Защита скрытых файлов
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}
👉 Это здоровый, продакшен-адекватный минимум для большинства PHP-проектов.
Готовые конфигурации для популярных фреймворков
Для конкретных фреймворков и CMS могут потребоваться дополнительные настройки. Ниже приведены ссылки на готовые конфигурации, основанные на официальной документации:
-
Nginx для Bitrix CMS — конфигурация с поддержкой URL rewriting через
/bitrix/urlrewrite.php, защитой директорий и увеличенными таймаутами для операций Bitrix. -
Nginx для WordPress — конфигурация с поддержкой pretty permalinks, защитой директории uploads и оптимизацией для WordPress.
-
Nginx для Laravel — конфигурация с правильной настройкой
rootна директориюpublic, обработкой толькоindex.phpи поддержкой Laravel роутинга. -
Nginx для Astro (статический сайт) — конфигурация для статических Astro сайтов с поддержкой SPA роутинга, кеширования и gzip сжатия.
Все конфигурации проверены и основаны на официальной документации соответствующих проектов.
Ошибка 502 Bad Gateway — причины и диагностика
Что означает 502
Nginx не смог получить ответ от PHP-FPM или получил некорректный ответ.
Частые причины
- PHP-FPM не запущен — самая частая причина;
- Неверный путь к сокету — сокет не существует или путь указан неправильно;
- PHP упал с fatal error — критическая ошибка в PHP-коде;
- Недостаточно памяти — сервер исчерпал доступную память;
- Неверный
SCRIPT_FILENAME— PHP-FPM не может найти файл для выполнения; - Проблемы с правами доступа — Nginx не может прочитать сокет или файлы.
Диагностика по шагам
Шаг 1. Проверка статуса PHP-FPM:
systemctl status php8.2-fpm
Если сервис не запущен:
systemctl start php8.2-fpm
systemctl enable php8.2-fpm
Шаг 2. Проверка существования сокета:
ls -l /run/php/
Должен быть файл php8.2-fpm.sock (или другой, в зависимости от версии).
Шаг 3. Проверка логов PHP-FPM:
tail -f /var/log/php8.2-fpm.log
Или для конкретного пула:
tail -f /var/log/php8.2-fpm/www-error.log
Шаг 4. Проверка логов Nginx:
tail -f /var/www/site.ru/logs/error.log
Или системный лог:
tail -f /var/log/nginx/error.log
Шаг 5. Проверка конфигурации:
nginx -t
php-fpm8.2 -t
👉 Начинайте всегда с логов, не с конфигов. Логи покажут реальную причину проблемы.
Ошибка 504 Gateway Timeout — причины и решения
Что означает 504
PHP слишком долго выполняет запрос, Nginx устал ждать и закрыл соединение.
Типовые причины
- Тяжёлые запросы к базе данных — медленные SQL-запросы без индексов;
- Внешние API без таймаутов — зависание на запросах к внешним сервисам;
- Зависший PHP-процесс — бесконечный цикл или блокирующая операция;
- Маленькие лимиты пула FPM — все процессы заняты, новые запросы ждут;
- Неправильные настройки таймаутов — несоответствие между Nginx, PHP-FPM и PHP.
Настройка таймаутов на всех уровнях
Таймауты нужно настраивать на трёх уровнях, и они должны быть согласованы.
В Nginx
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
# Время ожидания ответа от PHP-FPM
fastcgi_read_timeout 60s;
# Время на установку соединения с PHP-FPM
fastcgi_connect_timeout 60s;
# Время на отправку запроса в PHP-FPM
fastcgi_send_timeout 60s;
}
В PHP-FPM (pool.d/www.conf)
; Максимальное время выполнения запроса (в секундах)
; 0 = без ограничений (не рекомендуется)
request_terminate_timeout = 60
В PHP (php.ini)
; Максимальное время выполнения скрипта (в секундах)
max_execution_time = 60
; Максимальное время загрузки файла
max_input_time = 60
👉 Все три уровня должны быть согласованы. Рекомендуется устанавливать одинаковые значения или делать таймаут PHP-FPM немного больше, чем PHP.
Пример согласованной настройки:
Nginx fastcgi_read_timeout: 60s
PHP-FPM request_terminate_timeout: 65s
PHP max_execution_time: 60s
Это даёт небольшой запас для завершения процесса после таймаута PHP.
Настройка пула PHP-FPM
Каждый pool — это отдельный набор PHP-процессов с собственными настройками. Правильная настройка пула критически важна для производительности.
Базовые параметры пула
; Режим управления процессами: static, dynamic, ondemand
pm = dynamic
; Максимальное количество дочерних процессов
pm.max_children = 50
; Количество процессов, запускаемых при старте
pm.start_servers = 10
; Минимальное количество свободных процессов
pm.min_spare_servers = 5
; Максимальное количество свободных процессов
pm.max_spare_servers = 15
; Количество запросов, после которого процесс перезапускается
pm.max_requests = 500
Что это значит
pm.max_children— максимум одновременных запросов. Если все процессы заняты → новые запросы ждут → возможен 504;pm.start_servers— сколько процессов запускается при старте PHP-FPM;pm.min_spare_servers— минимальное количество процессов в режиме ожидания;pm.max_spare_servers— максимальное количество процессов в режиме ожидания;pm.max_requests— после этого количества запросов процесс перезапускается (защита от утечек памяти).
Расчёт оптимального количества процессов
Формула для pm.max_children:
max_children = (RAM доступная для PHP) / (RAM на один PHP-процесс)
Пример:
Доступно RAM: 2 GB
Один PHP-процесс: ~50 MB
max_children = 2048 MB / 50 MB ≈ 40 процессов
Режимы управления процессами
pm = static — фиксированное количество процессов:
pm = static
pm.max_children = 20
Подходит для стабильной нагрузки, предсказуемое потребление памяти.
pm = dynamic — динамическое управление (рекомендуется):
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 15
Подходит для переменной нагрузки, оптимальное использование ресурсов.
pm = ondemand — процессы запускаются по требованию:
pm = ondemand
pm.max_children = 50
pm.process_idle_timeout = 10s
Подходит для серверов с низкой нагрузкой, экономия ресурсов.
Типовые ошибки новичков
❌ Путают Apache mod_php и PHP-FPM — думают, что PHP встроен в Nginx, как в Apache.
❌ Думают, что PHP — часть Nginx — не понимают архитектуру FastCGI.
❌ Правят php.ini, а проблема в FPM — не различают настройки PHP и PHP-FPM.
❌ Игнорируют логи — начинают менять конфиги наугад вместо чтения логов.
❌ Сразу крутят таймауты — увеличивают таймауты, не понимая реальную причину медленной работы.
❌ Неправильный порядок location — блок location ~ \.php$ должен быть после location /.
❌ Забывают про try_files — без него фреймворки с роутингом не работают.
Чек-лист диагностики проблем с PHP
Если PHP не работает, проверьте по порядку:
- PHP-FPM запущен —
systemctl status php8.2-fpm - Путь к сокету совпадает — проверьте
fastcgi_passв Nginx иlistenв pool.conf - SCRIPT_FILENAME корректный — должен содержать полный путь к файлу
- try_files настроен — для фреймворков обязателен
- Логи читаются — начните с
tail -fна error.log - Нет fatal error — проверьте логи PHP-FPM
- Права доступа корректны — Nginx должен читать файлы и сокет
- Конфигурация синтаксически правильна —
nginx -tиphp-fpm8.2 -t - Достаточно памяти — проверьте
free -hи логи OOM killer - Таймауты согласованы — проверьте на всех трёх уровнях
Рекомендации по настройке и безопасности
Производительность
- Используйте Unix-сокеты вместо TCP для локальных подключений.
- Настройте кэширование статических файлов в Nginx.
- Используйте OPcache для PHP (включён по умолчанию в современных версиях).
- Мониторьте использование памяти и CPU процессами PHP-FPM.
Безопасность
- Ограничьте выполнение PHP только в нужных директориях.
- Используйте отдельные пулы для разных сайтов с разными правами.
- Настройте
open_basedirв PHP для ограничения доступа к файлам. - Регулярно обновляйте PHP и PHP-FPM до актуальных версий.
Мониторинг
- Настройте ротацию логов для предотвращения переполнения диска.
- Используйте мониторинг процессов PHP-FPM (например, через systemd или внешние системы).
- Отслеживайте метрики: количество активных процессов, время выполнения запросов, ошибки.
Что будет в части 4
Дальше логичное продолжение:
Часть 4 — Reverse Proxy и проксирование (API, Node.js, Python)
proxy_passи проксирование запросов;- работа с заголовками;
- WebSocket через Nginx;
- настройка backend-сервисов за Nginx.
Заключение
Связка Nginx + PHP-FPM — это не магия, а чёткий контракт между компонентами:
- Nginx — маршрутизатор и точка входа, принимает HTTP-запросы;
- PHP-FPM — исполнитель PHP-кода, управляет процессами;
- FastCGI — протокол взаимодействия между ними;
- Ошибки почти всегда читаются в логах — начинайте диагностику с них.
Когда вы понимаете эту архитектуру, 502 и 504 перестают пугать — они становятся понятными сигналами о конкретных проблемах, которые можно быстро диагностировать и исправить.
Правильная настройка таймаутов, пулов процессов и мониторинг логов — это основа стабильной работы PHP-приложений в продакшене.



Комментарии