// Engineering Log
HTTPS и веб-сервер на практике: Часть 1 — Ошибки 502, 504, 499 и 413 в Nginx: причины и таймауты
Опубликовано 28.10.2026
// Быстрый маршрут
Эта статья относится к теме Серверы и инфраструктура.
Коды 502, 504, 499 и 413 почти никогда не отдаёт само приложение. Их возвращает Nginx, который стоит перед ним: он не смог подключиться к приложению, не дождался ответа, получил обрыв соединения или отказался принимать слишком большой запрос. Поэтому причину ищут не в коде приложения, а на стыке Nginx и приложения — в журнале ошибок Nginx и в согласовании таймаутов. Ниже — что означает каждый код, какие строки журнала ему соответствуют и что менять в настройках. Общие сведения о кодах состояния — в статье «Что такое HTTP: запрос, ответ, методы и коды состояния».
Сначала — журнал
В access.log видно только код, причина — в error.log (обычно /var/log/nginx/error.log). Строка ошибки содержит адрес приложения (upstream), запрос и системную причину:
2026/09/24 10:15:02 [error] 1234#1234: *5678 connect() failed (111: Connection refused)
while connecting to upstream, client: 192.0.2.7, server: example.ru,
request: "GET /api/orders HTTP/2.0", upstream: "http://127.0.0.1:8080/api/orders"Чтобы видеть время ответа приложения прямо в журнале доступа, расширьте формат:
log_format upstream '$remote_addr "$request" $status '
'rt=$request_time uct=$upstream_connect_time '
'urt=$upstream_response_time us=$upstream_status ua=$upstream_addr';
access_log /var/log/nginx/access.log upstream;$request_time— сколько Nginx обрабатывал запрос целиком, включая передачу клиенту;$upstream_connect_time— время подключения к приложению;$upstream_response_time— сколько отвечало приложение;$upstream_statusи$upstream_addr— что ответило приложение и какой из серверов. Если серверов несколько и Nginx пробовал следующий, значения идут через запятую:502, 200.
502 Bad Gateway
Nginx не получил от приложения корректного ответа. Причину определяет текст в error.log.
connect() failed (111: Connection refused) — на указанном адресе и порту никто не слушает. Приложение не запущено, упало, слушает другой порт или только 127.0.0.1, когда Nginx обращается по внешнему адресу (частый случай в Docker: приложение слушает 127.0.0.1 внутри контейнера и недоступно из соседнего). Проверка:
ss -ltnp | grep 8080
curl -v http://127.0.0.1:8080/connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory) — сокета нет: PHP-FPM не запущен или в Nginx указана другая версия PHP.
(13: Permission denied) while connecting to upstream — у Nginx нет прав на сокет (проверьте listen.owner и listen.group в пуле PHP-FPM) или, в CentOS, Rocky и RHEL, SELinux запрещает подключение: setsebool -P httpd_can_network_connect 1.
(11: Resource temporarily unavailable) while connecting to upstream — очередь соединений к сокету переполнена: все процессы PHP-FPM заняты. Смотрите в журнале PHP-FPM сообщение server reached pm.max_children setting и увеличивайте pm.max_children, если позволяет память, или ищите медленные запросы.
upstream prematurely closed connection while reading response header from upstream — приложение закрыло соединение, не ответив. Причины: процесс упал на этом запросе (смотрите журнал приложения, dmesg на предмет OOM killer), приложение само оборвало долгий запрос по своему таймауту, или гонка keepalive (ниже).
recv() failed (104: Connection reset by peer) — приложение сбросило соединение. Причины те же.
upstream sent too big header while reading response header from upstream — заголовки ответа не помещаются в буфер: обычно много или большие cookie, длинный Location. Увеличьте буфер:
proxy_buffer_size 16k;
proxy_buffers 8 16k;
# для PHP-FPM — fastcgi_buffer_size и fastcgi_buffersno live upstreams while connecting to upstream — все серверы в блоке upstream помечены недоступными после ошибок (параметры max_fails и fail_timeout). Это следствие: ищите в журнале первые ошибки перед этой строкой.
Гонка keepalive: 502 раз в несколько минут
Если 502 появляются редко, без нагрузки и без ошибок в журнале приложения, почти наверняка это гонка keepalive между Nginx и приложением.
Когда в upstream включён keepalive, Nginx держит соединения к приложению открытыми и использует их повторно. Приложение тоже закрывает простаивающие соединения — но по своему таймауту. Если приложение закрыло соединение в тот момент, когда Nginx отправил по нему новый запрос, запрос получает обрыв и 502.
Пример: у Node.js server.keepAliveTimeout по умолчанию 5 секунд, а Nginx держит простаивающее соединение к приложению до 60 секунд (keepalive_timeout в блоке upstream). Через 5 секунд простоя Node.js закрывает соединение, Nginx пытается им воспользоваться — и получает 502.
Правило: таймаут простоя у того, кто ближе к приложению, должен быть больше, чем у того, кто перед ним. Либо уменьшите таймаут в Nginx, либо увеличьте в приложении:
upstream app {
server 127.0.0.1:3000;
keepalive 32;
keepalive_timeout 4s; # меньше, чем keepAliveTimeout в Node.js (5 с)
}
server {
location / {
proxy_pass http://app;
proxy_http_version 1.1;
proxy_set_header Connection ""; # без этого keepalive к приложению не работает
}
}// или в Node.js: больше, чем держит соединения тот, кто стоит перед приложением
server.keepAliveTimeout = 65000;
server.headersTimeout = 66000;То же правило действует для всей цепочки: облачный балансировщик → Nginx → приложение. У AWS ALB таймаут простоя по умолчанию 60 секунд, значит, у Nginx за ним keepalive_timeout для клиентов должен быть больше 60 секунд.
504 Gateway Timeout
Nginx подключился к приложению, но не дождался ответа за отведённое время:
upstream timed out (110: Connection timed out) while reading response header from upstreamТаймауты Nginx при проксировании:
| Директива | По умолчанию | Что ограничивает |
|---|---|---|
proxy_connect_timeout | 60 с | установку соединения с приложением (больше 75 с не задать) |
proxy_send_timeout | 60 с | паузу между двумя операциями записи запроса приложению |
proxy_read_timeout | 60 с | паузу между двумя операциями чтения ответа — не общее время ответа |
fastcgi_read_timeout | 60 с | то же для PHP-FPM |
Что делать:
Найти медленный запрос. 504 — симптом: приложение слишком долго работает. Смотрите
urt=в журнале, медленные запросы к базе, внешние API без таймаутов.Увеличить таймаут только там, где долгий ответ — норма, например для выгрузки отчётов, а не глобально:
nginxlocation /reports/ { proxy_pass http://app; proxy_read_timeout 300s; }Согласовать таймауты по всей цепочке. Увеличить
proxy_read_timeoutбесполезно, если раньше срабатывает таймаут в другом месте:max_execution_timeиrequest_terminate_timeoutв PHP, таймаут воркера в Gunicorn (--timeout, по умолчанию 30 с), таймаут CDN (у Cloudflare ответ должен начаться за 100 секунд, иначе — ошибка 524).Долгие операции — в фон. Если отчёт строится пять минут, правильнее принять задание, вернуть
202 Acceptedи отдать результат по готовности, а не держать HTTP-запрос открытым.
proxy_connect_timeout срабатывает, только если приложение не отвечает на подключение вовсе (адрес недоступен, пакеты теряются) — тогда в журнале while connecting to upstream. Отказ в соединении (Connection refused) приходит мгновенно и даёт 502, а не 504.
499 Client Closed Request
Код, придуманный в Nginx: клиент закрыл соединение, не дождавшись ответа. Клиенту этот код не отправляется — только пишется в журнал.
Причины:
- пользователь закрыл вкладку или ушёл со страницы, пока она грузилась. Единичные 499 — норма;
- у клиента свой таймаут меньше, чем время ответа: мобильное приложение ждёт 30 секунд, API отвечает за 40. Массовые 499 с одинаковым
$request_time— признак именно этого; - перед Nginx стоит балансировщик или CDN со своим таймаутом, и он закрывает соединение раньше;
- мониторинг проверяет доступность с коротким таймаутом.
По умолчанию, когда клиент уходит, Nginx закрывает и соединение с приложением (proxy_ignore_client_abort off), но приложение может продолжить работу и не узнать, что результат никому не нужен. Если 499 массовые — это та же проблема, что 504: медленные ответы, только таймаут сработал у клиента.
413 Content Too Large
Тело запроса больше разрешённого. В Nginx по умолчанию — 1 МБ, поэтому загрузка фотографии или документа через сайт первой упирается именно в этот лимит:
client intended to send too large body: 5242880 bytesserver {
client_max_body_size 50m; # для всего сайта
location /upload/ {
client_max_body_size 500m; # для загрузок — больше
}
}Лимит есть и дальше по цепочке, и поднимать его нужно везде:
- PHP —
upload_max_filesizeиpost_max_sizeвphp.ini; - фреймворк приложения — например,
DATA_UPLOAD_MAX_MEMORY_SIZEв Django,bodyParserв Express; - CDN — у Cloudflare на бесплатном и Pro-тарифах тело запроса ограничено 100 МБ.
Для больших файлов лучше загрузка частями (протокол tus) или прямая загрузка в объектное хранилище по подписанной ссылке, минуя приложение.
Другие коды от Nginx
- 400 Request Header Or Cookie Too Large — заголовки или cookie не помещаются в буфер:
large_client_header_buffers 4 16k;. - 503 Service Temporarily Unavailable — часто это не авария, а сработавшее ограничение частоты
limit_reqилиlimit_conn: по умолчанию они отвечают именно 503. В журнале —limiting requests, excess:. Отдавать правильный код 429 можно директивойlimit_req_status 429;. - 500 с
rewrite or internal redirection cycle— бесконечный циклtry_filesилиrewrite. - 403 с
directory index of "/var/www/…/" is forbidden— запрошен каталог, в нём нетindex.html/index.php, а листинг выключен. С(13: Permission denied)— у пользователя Nginx нет прав на файлы.
Ошибки Cloudflare 52x
Если сайт за Cloudflare, ошибки на стыке CDN и вашего сервера имеют свои коды — это аналоги 502 и 504, но между Cloudflare и Nginx:
| Код | Что значит |
|---|---|
| 520 | сервер вернул пустой или непонятный ответ |
| 521 | сервер отказал в соединении — Nginx не запущен или порт закрыт для адресов Cloudflare |
| 522 | таймаут подключения к серверу |
| 523 | сервер недоступен (неверный адрес в DNS) |
| 524 | соединение есть, но ответ не начался за 100 секунд |
| 525 | не удалось рукопожатие TLS с сервером |
| 526 | неверный сертификат на сервере в режиме Full (strict) |
Порядок диагностики
- Найти строку в
error.logпо времени и адресу — текст ошибки почти всегда указывает на причину. - Проверить приложение напрямую, минуя Nginx:
curl -v http://127.0.0.1:8080/путь. - Сравнить
$request_timeи$upstream_response_time: если время уходит в приложении — искать там, если нет — в сети или в Nginx. - Выписать таймауты всей цепочки — CDN, балансировщик, Nginx, приложение, база — и проверить, что каждый следующий согласован с предыдущим.
- Для редких 502 без видимой причины — проверить keepalive между Nginx и приложением.
// Похожая задача
Если у вас похожая ситуация
Эта статья относится к одной из рабочих тем. Можно продолжить чтение по теме, перейти на главную, чтобы понять, чем я занимаюсь, или сразу открыть услуги.
Тема статьи
Серверы и инфраструктура
VPS, Linux, веб-стек, миграции, хостинг, базы данных и базовая эксплуатация.
Часто с этим приходят
- Перенести сайт или сервис на новый сервер
- Настроить Linux, Nginx, базу данных и бэкапы
- Разобраться, почему всё работает нестабильно
// Следующий шаг
Если вам нужна не только статья, а помощь по этой теме, удобнее сразу перейти в услугу. Главная и подборка материалов остаются рядом.
Открыть услуги// Reviews
Отзывы по теме
Спасибо Михаилу за отзывчивость. Созвонились, объяснил как сделать самому. Обращаюсь уже второй раз, все супер и оперативно.
Спасибо Михаилу за отзывчивость. Созвонились, объяснил как сделать самому. Обращаюсь уже второй раз, все супер и оперативно.
Хочу выразить огромную благодарность специалисту, который настроил мне ЧПУ на OpenCart. Настроить ЧПУ оказалось легко и просто, и я рад, что наконец нашел профессионала, который сделал всё качественно и без лишних сложностей. До этого я сменил четырёх специалистов, и каждый раз возникали проблемы с настройкой, но этот человек справился с задачей идеально.
Хочу выразить огромную благодарность специалисту, который настроил мне ЧПУ на OpenCart. Настроить ЧПУ оказалось легко и просто, и я рад, что наконец нашел профессионала, который сделал всё качественно и без лишних …
Отличная работа, обращаюсь не первый раз, находит решения к сложным задачам. Рекомендую.
Отличная работа, обращаюсь не первый раз, находит решения к сложным задачам. Рекомендую.
Отличная работа! Выполнил поставленную задачу в срок и без ошибок. Было приятно сотрудничать, рекомендую.
Отличная работа! Выполнил поставленную задачу в срок и без ошибок. Было приятно сотрудничать, рекомендую.
Отличный специалист, вник в проблему, разобрался, исправил. Рекомендую.
Отличный специалист, вник в проблему, разобрался, исправил. Рекомендую.
Нужно было решить проблему с SSL сертификатом на сервере, который был выпущен через Ngnix Proxy manager. Михаил уточнил все детали, как у меня все устроено, попросил доступы чтобы оценить реальность решения задачи, т. к. до этого не сталкивался с подобным сервисом. Быстро разобрался и решил мою проблему. Идеальное сотрудничество)
Нужно было решить проблему с SSL сертификатом на сервере, который был выпущен через Ngnix Proxy manager. Михаил уточнил все детали, как у меня все устроено, попросил доступы чтобы оценить реальность решения задачи, т. …
Диагностика Nginx Proxy Manager в docker контейнере и решение проблемы
15.03.2024 · ★ 5/5
// Contact
Нужна помощь?
Свяжись со мной и я помогу решить проблему
Написать в TelegramОтвечаю в течение рабочего дня (03:00–13:00 GMT)
Или оставьте заявку здесь:
// Related