← Назад в блог

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

Подробное руководство по настройке 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 или получил некорректный ответ.

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

  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

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

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

Предыдущая часть: Nginx: virtual hosts и структура сайтов — как обслуживать несколько проектов правильно
0 просмотров

Комментарии

Загрузка комментариев...
Пока нет комментариев. Будьте первым!