DEV Community

Андрей Викулов (VProger)
Андрей Викулов (VProger)

Posted on • Originally published at viku-lov.ru on

Nginx + PHP-FPM: как работает связка и решаем ошибки 502 и 504

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 → Браузер

Enter fullscreen mode Exit fullscreen mode

Как Nginx определяет, что файл — PHP

Nginx использует директиву location с регулярным выражением для определения PHP-файлов:


location ~ \.php$ {

конфигурация обработки PHP

}

Enter fullscreen mode Exit fullscreen mode

Это означает:

  • любой запрос, 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;

}

Enter fullscreen mode Exit fullscreen mode

Разберём каждую директиву:

  • 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;

Enter fullscreen mode Exit fullscreen mode

Преимущества:

  • быстрее (нет сетевых задержек);
  • безопаснее (нет сетевого доступа);
  • стандартный способ для одного сервера;
  • меньше накладных расходов.

Недостатки:

  • работает только локально на том же сервере.

Вариант 2. TCP-подключение


fastcgi\_pass 127.0.0.1:9000;

Enter fullscreen mode Exit fullscreen mode

Используется, если:

  • PHP-FPM запущен в Docker-контейнере;
  • PHP-FPM находится на другом сервере;
  • нужна сетевая изоляция между процессами.

Где узнать путь к сокету PHP-FPM

Путь к сокету указывается в конфигурационном файле пула PHP-FPM.

Ubuntu / Debian


/etc/php/8.2/fpm/pool.d/www.conf

Enter fullscreen mode Exit fullscreen mode

Ищите строку:


listen = /run/php/php8.2-fpm.sock

Enter fullscreen mode Exit fullscreen mode

CentOS / Rocky Linux


/etc/php-fpm.d/www.conf

Enter fullscreen mode Exit fullscreen mode

👉 Этот путь должен точно совпадать с fastcgi_pass в конфигурации Nginx.


SCRIPT_FILENAME — самая важная строка


fastcgi\_param SCRIPT\_FILENAME $document\_root$fastcgi\_script\_name;

Enter fullscreen mode Exit fullscreen mode

Если эта строка неправильная или отсутствует → 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

Enter fullscreen mode Exit fullscreen mode

PHP-FPM использует этот путь для загрузки и выполнения файла.


index.php и try_files — правильная связка

Для современных PHP-фреймворков (Laravel, Symfony, Bitrix, WordPress) критически важно правильно настроить try_files:


location / {

try\_files $uri $uri/ /index.php?$query\_string;

}

Enter fullscreen mode Exit fullscreen mode

Что это даёт:

  • если файл существует — отдаём его напрямую;
  • если это директория — пробуем найти индексный файл;
  • если ничего не найдено — передаём запрос в 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;

}

}

Enter fullscreen mode Exit fullscreen mode

👉 Это здоровый, продакшен-адекватный минимум для большинства 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 или получил некорректный ответ.

Частые причины

  1. PHP-FPM не запущен — самая частая причина;
  2. Неверный путь к сокету — сокет не существует или путь указан неправильно;
  3. PHP упал с fatal error — критическая ошибка в PHP-коде;
  4. Недостаточно памяти — сервер исчерпал доступную память;
  5. Неверный SCRIPT_FILENAME — PHP-FPM не может найти файл для выполнения;
  6. Проблемы с правами доступа — Nginx не может прочитать сокет или файлы.

Диагностика по шагам

Шаг 1. Проверка статуса PHP-FPM:


systemctl status php8.2-fpm

Enter fullscreen mode Exit fullscreen mode

Если сервис не запущен:


systemctl start php8.2-fpm

systemctl enable php8.2-fpm

Enter fullscreen mode Exit fullscreen mode

Шаг 2. Проверка существования сокета:


ls -l /run/php/

Enter fullscreen mode Exit fullscreen mode

Должен быть файл php8.2-fpm.sock (или другой, в зависимости от версии).

Шаг 3. Проверка логов PHP-FPM:


tail -f /var/log/php8.2-fpm.log

Enter fullscreen mode Exit fullscreen mode

Или для конкретного пула:


tail -f /var/log/php8.2-fpm/www-error.log

Enter fullscreen mode Exit fullscreen mode

Шаг 4. Проверка логов Nginx:


tail -f /var/www/site.ru/logs/error.log

Enter fullscreen mode Exit fullscreen mode

Или системный лог:


tail -f /var/log/nginx/error.log

Enter fullscreen mode Exit fullscreen mode

Шаг 5. Проверка конфигурации:


nginx -t

php-fpm8.2 -t

Enter fullscreen mode Exit fullscreen mode

👉 Начинайте всегда с логов, не с конфигов. Логи покажут реальную причину проблемы.


Ошибка 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;

}

Enter fullscreen mode Exit fullscreen mode

В PHP-FPM (pool.d/www.conf)


; Максимальное время выполнения запроса (в секундах)

; 0 = без ограничений (не рекомендуется)

request\_terminate\_timeout = 60

Enter fullscreen mode Exit fullscreen mode

В PHP (php.ini)


; Максимальное время выполнения скрипта (в секундах)

max\_execution\_time = 60

; Максимальное время загрузки файла

max\_input\_time = 60

Enter fullscreen mode Exit fullscreen mode

👉 Все три уровня должны быть согласованы. Рекомендуется устанавливать одинаковые значения или делать таймаут PHP-FPM немного больше, чем PHP.

Пример согласованной настройки:


Nginx fastcgi\_read\_timeout: 60s

PHP-FPM request\_terminate\_timeout: 65s

PHP max\_execution\_time: 60s

Enter fullscreen mode Exit fullscreen mode

Это даёт небольшой запас для завершения процесса после таймаута 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

Enter fullscreen mode Exit fullscreen mode

Что это значит

  • 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-процесс)

Enter fullscreen mode Exit fullscreen mode

Пример:


Доступно RAM: 2 GB

Один PHP-процесс: ~50 MB

max\_children = 2048 MB / 50 MB ≈ 40 процессов

Enter fullscreen mode Exit fullscreen mode

Режимы управления процессами

pm = static — фиксированное количество процессов:


pm = static

pm.max\_children = 20

Enter fullscreen mode Exit fullscreen mode

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

pm = dynamic — динамическое управление (рекомендуется):


pm = dynamic

pm.max\_children = 50

pm.start\_servers = 10

pm.min\_spare\_servers = 5

pm.max\_spare\_servers = 15

Enter fullscreen mode Exit fullscreen mode

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

pm = ondemand — процессы запускаются по требованию:


pm = ondemand

pm.max\_children = 50

pm.process\_idle\_timeout = 10s

Enter fullscreen mode Exit fullscreen mode

Подходит для серверов с низкой нагрузкой, экономия ресурсов.


Типовые ошибки новичков

Путают 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-приложений в продакшене.

Read more on viku-lov.ru

Top comments (0)