Nginx как reverse proxy
Почему перед приложением почти всегда стоит прокси — и как читать 502 против 504.
Зачем прокси перед приложением
Приложение слушает свой порт (скажем, 8080) только на localhost, а наружу на 80/443 смотрит nginx. Он берёт на себя то, что приложению делать не стоит:
- TLS — сертификаты и шифрование в одном месте, приложение говорит по простому HTTP;
- несколько сервисов на одном сервере — маршрутизация по доменам и путям;
- статика — файлы nginx отдаёт сам, не будя приложение;
- буферизация и лимиты — медленные клиенты и гигантские запросы не занимают воркеры приложения.
Минимальный конфиг
server {
listen 443 ssl;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Заголовки X-Forwarded-* — не украшение: без них приложение видит все запросы приходящими со 127.0.0.1 по HTTP. Логи, rate-limiting по IP и генерация ссылок ломаются молча.
502 против 504
Две ошибки прокси, которые постоянно путают, хотя они указывают в разные стороны:
502 Bad Gateway — nginx постучался в upstream, и соединение не удалось: приложение не запущено, слушает другой порт или упало. Проверяйте процесс: ss -tlnp | grep 8080, логи приложения.
504 Gateway Timeout — соединение есть, но ответ не пришёл за proxy_read_timeout (по умолчанию 60 с). Приложение живо, но что-то в нём висит: медленный запрос к базе, внешний API, блокировка.
Правило: 502 — «не смог подключиться», 504 — «подключился и не дождался». Первое лечится на стороне процесса, второе — поиском того, что тормозит.
Не забыть перечитать
nginx -t # проверить конфиг ДО перезагрузки
nginx -s reload # применить без разрыва соединений
nginx -t перед каждым reload — рефлекс: сломанный конфиг при reload nginx просто не применит, а вот при рестарте — не поднимется вовсе.