Nginx 504 Gateway Timeout: как найти причину и исправить ошибку

Ошибка Nginx 504 Gateway Timeout означает, что Nginx, работая шлюзом или прокси, не получил своевременный ответ от upstream-сервера.

Проще говоря:

Браузер
   ↓
Nginx
   ↓
PHP-FPM / приложение / API
   ↓
База данных / внешний сервис

Nginx запрос принял, передал его дальше — и слишком долго ждал ответа.

Поэтому при 504 первое желание:

proxy_read_timeout 300s;

часто ведёт не туда.

Если обычная страница вместо двух секунд работает 70 секунд, правильный вопрос — не «как заставить Nginx ждать дольше?», а «почему backend отвечает 70 секунд?».



Что сделать сразу после появления 504

↑ К оглавлению

Если сайт рабочий production, пока ничего не перезапускайте и не меняйте в конфигурации.

Сначала соберите три ответа:

1. Что написал Nginx в error.log?
2. Куда Nginx передаёт запрос?
3. Отвечает ли этот backend самостоятельно?

Очень часто этих трёх шагов уже достаточно, чтобы понять направление.

Если у вас есть SSH-доступ, начинаем.


Шаг 1. Найдите ошибку в журнале Nginx

↑ К оглавлению

На многих серверах журнал находится здесь:

sudo tail -n 100 /var/log/nginx/error.log

Удобнее открыть его и сразу воспроизвести проблему:

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

Теперь в браузере снова откройте страницу, которая выдаёт 504.

И смотрите, какая запись появилась одновременно с ошибкой.

Путь /var/log/nginx/error.log распространён, но не обязателен: расположение журнала задаётся директивой error_log и может отличаться. Поэтому отсутствие такого файла ещё не означает отсутствие логов Nginx.

Можно посмотреть загруженную конфигурацию:

sudo nginx -T 2>/dev/null | grep -n "error_log"

nginx -T проверяет конфигурацию аналогично -t и дополнительно выводит её содержимое. Не публикуйте этот вывод целиком без проверки: конфигурация может содержать внутренние адреса и другие служебные данные.


Что искать в error.log

↑ К оглавлению

Для 504 особенно интересны сообщения наподобие:

upstream timed out

а дальше — на каком этапе произошёл таймаут.

Например:

while connecting to upstream

означает одну ветку диагностики.

А:

while reading response header from upstream

— другую.

Во втором случае Nginx уже работает с upstream, но приложение слишком долго не отдаёт даже заголовки ответа.

Теперь нужно выяснить, кто этот upstream.


Шаг 2. Определите: PHP-FPM или обычный backend

↑ К оглавлению

Выполните:

sudo nginx -T 2>/dev/null | grep -nE "proxy_pass|fastcgi_pass"

Ищем конфигурацию именно той страницы или сайта, где возникает ошибка.

В большинстве случаев увидите один из двух вариантов.

Вариант A — fastcgi_pass

Например:

fastcgi_pass unix:/run/php/php8.4-fpm.sock;

или:

fastcgi_pass 127.0.0.1:9000;

Это почти наверняка PHP-FPM.

Так работают многие сайты на:

  • WordPress;
  • WooCommerce;
  • 1С-Битрикс;
  • OpenCart;
  • других PHP-CMS.

Тогда переходите к разделу «Если используется PHP-FPM».

Вариант B — proxy_pass

Например:

proxy_pass http://127.0.0.1:8000;

или:

proxy_pass http://backend;

Тогда Nginx работает как reverse proxy перед:

  • Node.js;
  • Python;
  • Go;
  • API;
  • контейнером;
  • другим HTTP-сервисом.

Переходим к разделу «Если Nginx проксирует приложение».


Если используется PHP-FPM

↑ К оглавлению

Теперь наша цепочка выглядит так:

Браузер
  ↓
Nginx
  ↓
PHP-FPM
  ↓
PHP-код
  ↓
База / API / файловая система

Нужно понять: сам PHP-FPM умер, очередь забита или конкретный PHP-запрос зависает.


Шаг 3. Найдите службу PHP-FPM

↑ К оглавлению

Не копируйте вслепую название вроде:

php8.4-fpm

Версия PHP на вашем сервере может быть другой.

Посмотрите доступные службы:

systemctl list-units --type=service --all | grep -Ei "php.*fpm|php-fpm"

Допустим, нашли:

php8.3-fpm.service

Тогда:

systemctl status php8.3-fpm --no-pager

Ситуация 1. PHP-FPM остановлен

Если статус:

inactive

или:

failed

Nginx физически не может нормально передать PHP-запрос.

Сначала смотрим причину:

journalctl -u php8.3-fpm -n 100 --no-pager

Если это именно нужный PHP-FPM для сайта и сервис должен быть запущен, можно после выяснения причины запустить его:

sudo systemctl start php8.3-fpm

И снова проверить:

systemctl status php8.3-fpm --no-pager

После этого повторить запрос к сайту.

Если сайт заработал

Не заканчивайте диагностику сразу.

Нужно понять, почему FPM остановился:

  • ошибка конфигурации;
  • нехватка памяти;
  • аварийное завершение;
  • проблема после обновления PHP;
  • неправильный socket;
  • другая системная причина.

Иначе 504 может вернуться.


Ситуация 2. PHP-FPM работает, но 504 остаётся

Это уже интереснее.

Теперь нам нужно определить:

PHP-FPM свободен?
или
все worker-процессы заняты?

Для этого у PHP-FPM существует status page.

Она показывает, в частности:

  • listen queue;
  • idle processes;
  • active processes;
  • max children reached;
  • slow requests.

PHP отдельно предупреждает, что status page нельзя оставлять открытой всему интернету: она может раскрывать URL запросов и информацию о ресурсах сервера. Доступ следует ограничивать локальными или доверенными адресами.


Что означают показатели PHP-FPM

↑ К оглавлению

Допустим, вы открыли status page и увидели:

listen queue: 0
idle processes: 4
active processes: 2
max children reached: 0

Это выглядит нормально: свободные процессы есть.

А теперь другой вариант:

listen queue: 18
idle processes: 0
active processes: 10
max children reached: 27

Здесь уже видно проблему.

Запросы ждут свободный PHP-процесс.

То есть 504 может возникать примерно так:

пришёл запрос
   ↓
все PHP worker заняты
   ↓
запрос попал в очередь
   ↓
ждёт
   ↓
Nginx не дождался
   ↓
504

listen queue показывает запросы, ожидающие свободного процесса, а max children reached фиксирует достижение максимального количества процессов пула.


Что делать, если PHP-FPM упёрся в pm.max_children

↑ К оглавлению

Не начинайте сразу увеличивать:

pm.max_children

в несколько раз.

Сначала выясните, почему процессы так долго заняты.

Причиной может быть:

  • медленный PHP-код;
  • тяжёлый SQL-запрос;
  • зависший внешний API;
  • импорт;
  • резервное копирование;
  • проблемный плагин;
  • WooCommerce-задача;
  • обмен с 1С;
  • массовая генерация страниц;
  • реальная высокая посещаемость.

Если просто увеличить количество PHP-процессов на сервере с недостатком RAM, можно получить новую проблему — уже с памятью и swap.

Нам нужен следующий шаг: найти медленный запрос.


Шаг 4. Включите PHP-FPM slowlog

↑ К оглавлению

У PHP-FPM для этого есть специальный механизм.

Директива:

request_slowlog_timeout

задаёт время, после которого FPM записывает PHP backtrace выполняющегося запроса в slowlog.

Например:

request_slowlog_timeout = 5s
slowlog = /var/log/php/php-fpm-slow.log

Это пример, а не универсальная конфигурация — путь к логам и нужный порог зависят от системы.

По актуальной документации PHP значение 0 отключает request_slowlog_timeout; после превышения указанного времени backtrace запроса записывается в файл slowlog.

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

Теперь повторяем проблемный запрос.


Что даст slowlog на практике

↑ К оглавлению

Допустим, 504 появляется при открытии:

/wp-admin/admin.php?page=some-import

После воспроизведения ошибки slowlog указывает на код конкретного плагина.

Вот теперь у нас уже не:

WordPress почему-то выдаёт 504.

А:

Nginx ждёт PHP
↓
PHP-FPM работает
↓
один PHP-запрос висит
↓
slowlog показывает конкретный код
↓
проблема локализована

Дальше можно проверять:

  • что делает этот плагин;
  • какой запрос выполняется;
  • не ждёт ли он API;
  • не завис ли SQL;
  • не обрабатывает ли огромный объём данных.

Это уже настоящее исправление причины.


Если Nginx проксирует приложение через proxy_pass

↑ К оглавлению

Теперь рассматриваем другую схему:

Браузер
   ↓
Nginx
   ↓
127.0.0.1:8000
   ↓
Python / Node.js / API / контейнер

Допустим, конфигурация содержит:

proxy_pass http://127.0.0.1:8000;

Самый полезный тест — обратиться к backend мимо Nginx.


Шаг 3 для proxy: проверьте backend напрямую

↑ К оглавлению

Например:

curl -sS   -o /dev/null   -w 'HTTP=%{http_code} time=%{time_total}s
'   --max-time 15   http://127.0.0.1:8000/

Допустим, результат:

HTTP=200 time=0.086s

Backend отвечает быстро.

А если:

curl: (28) Operation timed out

или запрос висит почти все 15 секунд — проблема уже воспроизвелась без Nginx.

То есть крутить proxy_read_timeout пока бессмысленно.

Нужно идти в логи приложения.


Проверяйте именно проблемный маршрут

↑ К оглавлению

Это важно.

Главная страница backend может отвечать:

0.05 секунды

а:

/api/report

— зависать.

Поэтому если 504 возникает на:

https://example.com/api/report

проверяйте именно соответствующий backend-route.

Например:

curl -sS   -o /dev/null   -w 'HTTP=%{http_code} time=%{time_total}s
'   --max-time 15   http://127.0.0.1:8000/api/report

Если приложению нужен определённый Host, авторизация или другие заголовки, тест необходимо адаптировать — случайный curl / не всегда воспроизводит реальный запрос.


Backend отвечает медленно

↑ К оглавлению

Допустим:

HTTP=200 time=12.840s

Хотя нормальная страница должна открываться за доли секунды.

Nginx в этом случае уже не главный подозреваемый.

Проверяем:

  • журнал приложения;
  • SQL;
  • внешний API;
  • файловые операции;
  • блокировки;
  • очередь задач;
  • использование CPU/RAM;
  • конкретный обработчик маршрута.

Например:

/api/order
↓
приложение
↓
внешний платёжный API
↓
ответ API задержался
↓
приложение ждёт
↓
Nginx ждёт приложение
↓
504

Увеличить timeout Nginx можно.

Но внешний API от этого быстрее не станет.


Backend отвечает быстро, но через Nginx остаётся 504

↑ К оглавлению

Тогда область поиска резко сужается.

Проверяем:

  • тот ли backend тестировали;
  • тот ли URL;
  • правильный ли proxy_pass;
  • нет ли нескольких upstream;
  • не меняется ли маршрут внутри Nginx;
  • не обращается ли Nginx к другому серверу;
  • нет ли сетевой проблемы именно между Nginx и upstream.

Полезно снова посмотреть активную конфигурацию:

sudo nginx -T 2>/dev/null

И найти нужный server / location.


Наглядная развилка

↑ К оглавлению
Получили Nginx 504
        ↓
Смотрим error.log
        ↓
Находим upstream
        ↓
┌───────────────────────┬─────────────────────────┐
│ fastcgi_pass          │ proxy_pass              │
│                       │                         │
│ PHP-FPM               │ HTTP backend            │
│ ↓                     │ ↓                       │
│ status FPM            │ curl backend напрямую   │
│ ↓                     │ ↓                       │
│ остановлен?           │ не отвечает?            │
│ → logs/start          │ → проблема backend      │
│                       │                         │
│ очередь?              │ отвечает медленно?      │
│ → slowlog/нагрузка    │ → код/SQL/API           │
│                       │                         │
│ один запрос висит?    │ отвечает быстро?        │
│ → slowlog             │ → Nginx/маршрут         │
└───────────────────────┴─────────────────────────┘
        ↓
Исправляем причину
        ↓
Повторяем исходный запрос
        ↓
Проверяем время и логи

Сценарий 1. 504 на всём PHP-сайте

↑ К оглавлению

Например, не работают одновременно:

/
/wp-admin/

и любые PHP-страницы, а сам Nginx отвечает.

Порядок:

1. Смотрим Nginx

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

2. Проверяем fastcgi_pass

sudo nginx -T 2>/dev/null | grep -n "fastcgi_pass"

3. Проверяем PHP-FPM

systemctl list-units --type=service --all | grep -Ei "php.*fpm|php-fpm"

Затем:

systemctl status <имя-службы> --no-pager

4. Если FPM failed

journalctl -u <имя-службы> -n 100 --no-pager

5. Если FPM работает

Проверяем очередь/status page и slowlog.

То есть всего за несколько шагов мы отделили:

Nginx

от:

PHP-FPM

и от:

конкретного PHP-кода

Сценарий 2. 504 только на одной странице

↑ К оглавлению

Это один из самых полезных симптомов.

Допустим:

/

открывается мгновенно.

Но:

/export/

через минуту выдаёт 504.

В такой ситуации не стоит начинать с глобальной настройки Nginx.

Проблема с большой вероятностью связана с тем, что делает именно /export/.

Проверьте:

  • запрос к базе;
  • экспорт;
  • импорт;
  • генерацию файла;
  • внешний API;
  • тяжёлый плагин;
  • обработку большого количества записей.

Для PHP — slowlog.

Для HTTP backend — прямой curl именно этого route и логи приложения.


Сценарий 3. WordPress выдаёт 504 только при определённом действии

↑ К оглавлению

Например:

  • открытие конкретной страницы администратора;
  • импорт товаров;
  • создание резервной копии;
  • генерация фида;
  • WooCommerce-операция;
  • синхронизация;
  • запуск тяжёлого плагина.

Главная работает — значит PHP-FPM вообще способен обслуживать запросы.

Дальше:

воспроизводим конкретную операцию
↓
смотрим Nginx error.log
↓
смотрим PHP-FPM slowlog
↓
находим выполняющийся код
↓
проверяем плагин / SQL / API

Это значительно полезнее, чем просто:

fastcgi_read_timeout 300s;

Сценарий 4. 504 возникает только днём или при нагрузке

↑ К оглавлению

Ночью сайт работает.

Днём начинаются 504.

Проверяем ресурсы в момент проблемы:

uptime
free -h
df -h

И процессы:

top

или:

htop

если он установлен.

Но одного CPU недостаточно.

Например:

CPU: 25%

не доказывает, что сервер здоров.

Возможна ситуация:

CPU нормальный
↓
PHP-FPM все worker заняты
↓
listen queue растёт
↓
новые запросы ждут
↓
504

Поэтому для PHP одновременно смотрим:

  • listen queue;
  • max children reached;
  • active processes;
  • idle processes;
  • slow requests.

Что делать при заполненной очереди PHP-FPM

↑ К оглавлению

Если:

listen queue > 0

и:

max children reached > 0

нужно определить, почему процессы заняты.

Если процессы выполняют нормальную работу быстро

Возможно, серверу действительно не хватает размера пула.

Если процессы висят по десятки секунд

Увеличение пула только позволит одновременно запустить больше медленных запросов.

Тогда сначала:

slowlog
↓
код
↓
SQL / API / плагин
↓
оптимизация

И только после этого решаем вопрос с размером пула.


Сценарий 5. 504 появился после переноса сайта

↑ К оглавлению

Сайт работал на старом сервере.

Перенесли.

Получили 504.

В этом случае особенно внимательно смотрим:

proxy_pass

или:

fastcgi_pass

Например, осталось:

proxy_pass http://127.0.0.1:8000;

а приложение теперь работает на другом порту.

Или было:

fastcgi_pass unix:/run/php/php8.2-fpm.sock;

а после переноса установлен PHP другой версии.

Проверяем:

sudo nginx -T 2>/dev/null | grep -nE "proxy_pass|fastcgi_pass"

Для порта:

ss -ltnp

Для PHP socket:

ls -la /run/php/

Если конфигурация Nginx указывает на несуществующий socket или неправильный адрес, увеличение таймаута проблему не решит.


Сценарий 6. 504 появился после обновления PHP

↑ К оглавлению

После обновления могла измениться служба:

php8.2-fpm

php8.3-fpm

а Nginx всё ещё использует старый socket.

Сначала:

ls -la /run/php/

Затем:

sudo nginx -T 2>/dev/null | grep -n "fastcgi_pass"

Сравниваем.

Но здесь есть важная оговорка: неправильный или недоступный socket часто проявляется как 502 Bad Gateway, а не 504. Поэтому всегда ориентируемся прежде всего на фактическую запись error.log, а не пытаемся подобрать ошибку под статью.


Сценарий 7. Backend ждёт внешний API

↑ К оглавлению

Например:

клиент
↓
Nginx
↓
приложение
↓
внешний API

Приложение отправило запрос внешнему сервису и зависло в ожидании.

Через некоторое время Nginx отдаёт 504.

В Nginx всё может быть совершенно нормально.

Нужно проверить:

  • timeout HTTP-клиента приложения;
  • лог внешнего запроса;
  • DNS;
  • доступность внешнего сервиса;
  • обработку ошибок;
  • есть ли retries;
  • не выполняется ли длительная операция синхронно.

Хорошая архитектура часто вообще не должна держать пользовательский HTTP-запрос открытым несколько минут ради тяжёлой фоновой работы.


Как понять, сколько времени Nginx ждёт upstream

↑ К оглавлению

Nginx предоставляет переменные:

$upstream_connect_time
$upstream_header_time
$upstream_response_time

Они позволяют измерить:

  • установление соединения с upstream;
  • ожидание заголовка;
  • получение ответа.

Можно добавить отдельный диагностический формат:

log_format upstream_timing
    '$remote_addr "$request" status=$status '
    'request_time=$request_time '
    'upstream_connect=$upstream_connect_time '
    'upstream_header=$upstream_header_time '
    'upstream_response=$upstream_response_time';

access_log /var/log/nginx/upstream-timing.log upstream_timing;

$request_time показывает общее время обработки запроса Nginx.

Перед применением:

sudo nginx -t

Если получили успешную проверку, только тогда применяем конфигурацию:

sudo nginx -s reload

или используем штатный reload вашей системы.


Как читать timing log

↑ К оглавлению

Предположим:

request_time=60.002
upstream_connect=0.001
upstream_header=-
upstream_response=60.001

Соединение установилось практически мгновенно.

Но backend не дал нормального ответа.

Или:

request_time=2.100
upstream_connect=2.050
upstream_header=2.070
upstream_response=2.080

Большая часть времени ушла на подключение.

Это уже совершенно другая проблема.

Вместо:

Ну, кажется, сервер тормозит.

мы получаем измеряемую точку:

Соединение занимает две секунды.

Почему таймаут часто равен примерно 60 секундам

↑ К оглавлению

Для обычного HTTP proxy актуальное значение по умолчанию:

proxy_read_timeout 60s;

Но важно понимать его правильно.

Это не ограничение общей продолжительности HTTP-запроса.

Nginx считает интервал между последовательными операциями чтения ответа от upstream. Если upstream ничего не передаёт в течение этого периода, соединение закрывается.

Для FastCGI:

fastcgi_read_timeout 60s;

работает по тому же принципу: timeout задаётся между чтениями ответа от FastCGI-сервера.

Отдельно существует:

proxy_connect_timeout

Соответствующий таймаут относится уже к установлению соединения с upstream.

Поэтому важно читать текст ошибки и понимать:

  • не смог подключиться;
  • или подключился, но не дождался ответа.

Когда увеличение proxy_read_timeout действительно правильно

↑ К оглавлению

Увеличение timeout не всегда плохо.

Есть операции, которые действительно могут занимать долгое время:

  • формирование большого отчёта;
  • административный импорт;
  • экспорт;
  • тяжёлая генерация;
  • специфический API-запрос.

Если вы измерили операцию и знаете, что она нормально выполняется 70–90 секунд, можно увеличить timeout именно для неё.

Например:

location /admin/long-report/ {
    proxy_pass http://127.0.0.1:8000;
    proxy_read_timeout 120s;
}

Лучше локально, чем глобально:

proxy_read_timeout 600s;

для абсолютно всего сайта.


Для PHP аналогично

↑ К оглавлению

Если конкретная PHP-операция действительно должна выполняться долго:

location ~ \.php$ {
    ...
    fastcgi_read_timeout 120s;
}

может быть оправдано.

Но сначала ответьте:

Почему этот PHP-запрос выполняется больше минуты?

Если это:

экспорт 200 000 товаров

— возможно, логично.

Если это:

главная страница WordPress

— увеличение timeout почти наверняка не является полноценным решением.


Плохое исправление

↑ К оглавлению

Было:

60 секунд
↓
504

Поставили:

proxy_read_timeout 300s;

Стало:

240 секунд
↓
200 OK

Технически 504 исчезла.

Но пользователь ждёт страницу четыре минуты.

Проблема не исправлена, а спрятана.


Хорошее исправление

↑ К оглавлению

Было:

60 секунд
↓
504

Нашли медленный SQL или зависший API.

Исправили.

Стало:

1.3 секунды
↓
200 OK

Вот это уже результат.


Что делать, если 504 возникает только иногда

↑ К оглавлению

Например:

20 запросов работают
21-й → 504
потом снова нормально

Ищите корреляцию:

  • время суток;
  • нагрузка;
  • cron;
  • backup;
  • импорт;
  • очередь PHP-FPM;
  • внешний API;
  • база данных;
  • периодическая синхронизация.

Особенно полезно иметь timing log и сопоставлять его со временем других событий.

Например:

02:00 — запускается backup
02:02 — диск перегружен
02:03 — PHP начинает ждать
02:04 — 504

Тогда изменение Nginx timeout вообще не требуется.


Что не стоит делать при Nginx 504

↑ К оглавлению

1. Сразу увеличивать timeout

Первым действием должны быть логи и определение upstream.

2. Перезапускать всё подряд

Не начинайте с:

restart nginx
restart php-fpm
restart mysql
restart сервер

Да, сайт иногда оживает.

Но вместе с проблемой исчезает часть полезного состояния для диагностики.

Сначала:

логи
status
нагрузка
очередь

Потом действия.

3. Одновременно менять пять настроек

Например:

proxy_read_timeout
fastcgi_read_timeout
pm.max_children
memory_limit
настройки MySQL

После этого сайт заработал.

Что именно помогло?

Никто не знает.

Меняйте одну обоснованную вещь и проверяйте результат.

4. Публично открывать PHP-FPM status

В ней содержатся сведения о запросах и ресурсах.

PHP рекомендует ограничивать её внутренними запросами или доверенными IP.

5. Копировать чужую конфигурацию целиком

Настройка:

fastcgi_read_timeout 300;

с форума ничего не говорит о причине вашего 504.


Чем 504 отличается от 502 Bad Gateway

↑ К оглавлению

Эти ошибки часто смешивают.

504 Gateway Timeout

Nginx как gateway/proxy не получил своевременный ответ от upstream.

502 Bad Gateway

Gateway/proxy получил от upstream некорректный ответ.

На практике:

504
→ думать про ожидание / зависший backend / медленную обработку

502
→ чаще проверять доступность backend, socket, порт, протокол и корректность ответа

Но настоящий ответ всегда ищите в error.log.


Как проверить исправление

↑ К оглавлению

Самая частая ошибка после ремонта:

Главная открылась — значит всё нормально.

Нет.

Нужно воспроизвести исходный сценарий.

Если проблема была в импорте — снова запускаем импорт.

Если в /checkout/ — проверяем checkout.

Если в API — вызываем тот же API.

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

После исправления:

  1. Повторите проблемный запрос.
  2. Проверьте HTTP-ответ.
  3. Посмотрите error.log.
  4. Сравните время выполнения.
  5. Если используется PHP-FPM — проверьте очередь.
  6. Если добавляли timing log — сравните upstream time.
  7. Выполните сценарий несколько раз.

Короткий алгоритм: что делать при Nginx 504

↑ К оглавлению
Появился Nginx 504
        ↓
1. Открываем error.log
        ↓
2. Повторяем проблемный запрос
        ↓
3. Находим upstream
        ↓
4. Смотрим nginx -T
        ↓
   ┌──────────────┴───────────────┐
   ↓                              ↓
fastcgi_pass                  proxy_pass
   ↓                              ↓
PHP-FPM                      приложение
   ↓                              ↓
status                       curl напрямую
   ↓                              ↓
работает?                    отвечает?
   ↓                              ↓
очередь?                     медленно?
   ↓                              ↓
slowlog                      логи backend
   ↓                              ↓
PHP / SQL / API              код / SQL / API
   └──────────────┬───────────────┘
                  ↓
            исправляем причину
                  ↓
              nginx -t
                  ↓
                 reload
                  ↓
       повторяем исходный сценарий
                  ↓
        проверяем время и логи

Быстрый чек-лист

↑ К оглавлению

Если прямо сейчас перед вами 504, выполните по порядку:

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

Воспроизведите ошибку.

Затем:

sudo nginx -T 2>/dev/null | grep -nE "proxy_pass|fastcgi_pass"

Если fastcgi_pass:

systemctl list-units --type=service --all | grep -Ei "php.*fpm|php-fpm"
systemctl status <php-fpm-service> --no-pager

Если:

proxy_pass http://127.0.0.1:8000;

проверьте backend:

curl -sS   -o /dev/null   -w 'HTTP=%{http_code} time=%{time_total}s
'   --max-time 15   http://127.0.0.1:8000/

После этого у вас уже должно быть значительно больше информации, чем просто:

504 Gateway Timeout


Если причина всё равно не найдена

↑ К оглавлению

Не увеличивайте timeout снова и снова.

Соберите четыре вещи:

1. запись Nginx error.log в момент 504;
2. соответствующий server/location из конфигурации;
3. состояние PHP-FPM или backend;
4. время выполнения проблемного запроса.

После этого цепочка обычно уже выглядит не как:

Nginx выдаёт 504

а гораздо конкретнее:

Nginx соединяется с PHP-FPM сразу, но PHP-запрос на странице импорта больше минуты ждёт внешний API.

И вот такую проблему уже можно нормально исправлять.



Частые вопросы

Почему Nginx выдаёт 504 Gateway Timeout?

Потому что Nginx, работая шлюзом или прокси, не получил своевременный ответ от upstream. Upstream может быть PHP-FPM, приложение, API или другой сервер.

Что первым проверять при 504?

error.log Nginx.

После этого определить proxy_pass или fastcgi_pass и проверить соответствующий backend.

Поможет ли `proxy_read_timeout 300s`?

Иногда, если операция действительно должна выполняться долго.

Но если обычная страница неожиданно стала отвечать больше минуты, сначала нужно найти причину медленной работы backend.

Что делать при 504 на WordPress?

Если используется Nginx + PHP-FPM:

error.log Nginx
↓
PHP-FPM status
↓
очередь
↓
slowlog
↓
конкретный PHP-запрос
↓
плагин / SQL / внешний API

Особенно важно воспроизвести именно ту страницу или операцию, на которой появляется 504.

Может ли 504 быть из-за базы данных?

Да.

Nginx напрямую может вообще не работать с базой.

Но:

Nginx
↓
PHP
↓
SQL

Если SQL-запрос выполняется слишком долго, PHP ждёт базу, Nginx ждёт PHP — и пользователь в итоге видит 504.

Может ли 504 быть из-за внешнего API?

Да.

Приложение может ждать внешний сервис дольше, чем Nginx готов ждать приложение.

Что означает `max children reached` в PHP-FPM?

Это означает, что пул достиг настроенного максимального количества процессов. Если одновременно растёт listen queue, запросам приходится ждать свободного worker.

Нужно ли перезапускать Nginx после изменения конфигурации?

Конфигурацию необходимо применить.

Но сначала:

sudo nginx -t

И только после успешной проверки — reload.

↑ К оглавлению

Нужна помощь с Nginx 504?

Если сайт продолжает выдавать 504 и по логам непонятно, где возникает задержка, можно провести диагностику всей цепочки:

Nginx → PHP-FPM / backend → приложение → база данных → внешние сервисы.

Важно не просто убрать страницу 504 увеличенным timeout, а найти участок, на котором запрос действительно теряет время, исправить его и повторно проверить результат.

↑ К оглавлению