Обратный прокси в Nginx: чек-лист перед продакшеном
Один Nginx может принимать трафик для сайта, API и админки, но ошибка в proxy_pass или таймаутах проявится уже под нагрузкой. Проверяем маршрутизацию, заголовки, WebSocket, лимиты и безопасный выпуск.

Один Nginx перед несколькими приложениями упрощает TLS, маршрутизацию и журналы, но ошибка в одном location может отправить запрос не тому сервису, обрезать URI или превратить долгий API-вызов в поток 504. Ниже — практический чек-лист для Nginx OSS 1.26.x: что проверить до выпуска сайта, API и административной панели в продакшен.
Сначала зафиксируйте схему маршрутизации
До правок в конфигурации составьте таблицу: какой внешний адрес или путь принадлежит приложению, на каком локальном адресе оно слушает, нужен ли WebSocket, какой размер запроса допустим и сколько может длиться ответ. Это избавляет от конфигурации, где соседние приложения случайно делят один маршрут.
| Маршрут | Приложение | Особые условия |
|---|---|---|
example.ru/ | веб-приложение, 127.0.0.1:8000 | обычные HTML и API-запросы |
example.ru/api/ | API, 127.0.0.1:9000 | длинные ответы, JSON, увеличенный лимит тела |
admin.example.ru/ | админка, 127.0.0.1:9100 | отдельные правила доступа и журналы |
Термин: upstream — группа серверов, на которую Nginx пересылает запросы. Даже если в группе один процесс, отдельный блок upstream делает адрес приложения явным и облегчает последующее добавление реплик.
Выберите границу маршрутизации
Есть два основных подхода. Разносить приложения по поддоменам проще для cookies, документации и правил доступа. Разносить их по путям удобно, когда нужен единый домен, но приложение должно корректно работать с префиксом: ссылками, редиректами и статическими файлами.
| Подход | Плюсы | Цена и риск | Когда выбирать |
|---|---|---|---|
| Разные поддомены | Простые маршруты, независимые корни приложения | Нужны DNS, сертификат и настройка cookies для каждого имени | Для независимых сервисов и админки |
| Разные пути | Один домен и один сертификат | Префиксы могут ломать ссылки, редиректы и авторизацию | Для API или сервиса, который умеет работать под префиксом |
| Отдельные порты наружу | Минимум правил Nginx | Сложнее TLS, firewall и пользовательские URL | Обычно только для внутренних или временных стендов |
Главное правило перед продакшеном: приложение должно знать внешний URL, а Nginx — внутренний адрес процесса. Не смешивайте эти два уровня.
Проверьте базовую конфигурацию прокси
Для примера ниже используется Nginx OSS 1.26.x. Синтаксис proxy_pass, proxy_set_header и proxy_read_timeout относится к стандартному модулю HTTP proxy. Блок map размещают внутри http, а server — внутри http или подключаемого файла конфигурации.
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream web_app {
server 127.0.0.1:8000;
}
upstream api_app {
server 127.0.0.1:9000;
}
server {
listen 443 ssl;
server_name example.ru;
client_max_body_size 20m;
location /api/ {
proxy_pass http://api_app;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60s;
}
location / {
proxy_pass http://web_app;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
}
Здесь в proxy_pass нет URI после имени upstream. Поэтому Nginx передаёт исходный путь: запрос к /api/orders попадёт в API именно с таким путём. Если написать proxy_pass http://api_app/;, поведение при замене части URI изменится. Проверяйте это отдельным запросом, а не предполагайте по виду строки.
Что проверить в заголовках
Hostнужен приложению для выбора домена, генерации ссылок и проверки origin.X-Forwarded-Forсохраняет цепочку IP, но приложение должно доверять этому заголовку только от вашего Nginx, а не от любого клиента.X-Forwarded-Protoсообщает, что снаружи использовался HTTPS. Без него приложение может генерировать HTTP-ссылки или зациклить редирект.UpgradeиConnectionнужны WebSocket-соединениям, но не превращают обычный HTTP-запрос в WebSocket. В приложении всё равно должна быть поддержка этого протокола.
Сверьте таймауты и размеры
Таймаут — это не скорость ответа, а предел ожидания на конкретном этапе. Например, proxy_read_timeout 60s означает, что Nginx будет ждать очередной фрагмент ответа не дольше минуты. Если API выполняет экспорт пять минут и не отправляет данные частями, клиент получит 504 независимо от того, что процесс продолжает работу.
Перед выпуском ответьте на четыре вопроса:
- какой максимальный размер загрузки нужен каждому приложению;
- какой endpoint действительно выполняется дольше стандартного таймаута;
- можно ли повторять запрос после обрыва соединения;
- не держит ли приложение соединение открытым для событий или потокового ответа.
Не ставьте большие таймауты на все маршруты. Для обычного API это увеличит число занятых соединений при зависшем upstream. Долгие операции лучше выносить в фоновую задачу с идентификатором результата, а не держать HTTP-запрос открытым несколько минут.
Проверьте WebSocket, загрузки и буферизацию
WebSocket тестируйте отдельным сценарием: обычная страница может открываться, пока обновления в реальном времени не работают. После установления соединения проверьте авторизацию, восстановление после перезапуска Nginx и закрытие неактивных соединений.
Для загрузок проверьте не только client_max_body_size, но и лимиты самого приложения, временное место на диске и время обработки. Если Nginx отвечает 413 Request Entity Too Large, лимит сработал на его стороне. Если запрос доходит до приложения и получает ошибку размера, искать причину нужно уже в настройках upstream.
Не отключайте proxy_buffering без измерений. Буферизация позволяет Nginx быстрее освободить соединение с приложением, но для потоковых ответов может быть нежелательна. Сначала определите маршрут, который действительно отдаёт поток, и меняйте настройку только для него.
Сделайте проверку перед переключением DNS
- Проверьте конфигурацию. Выполните
nginx -t. В успешном результате должны быть сообщенияsyntax is okиtest is successful. Если команда не проходит, перезагружать Nginx нельзя. - Проверьте каждый маршрут напрямую. Отправьте запросы к домену с тестового окружения или через временную запись DNS. Убедитесь, что главная страница, API, загрузка файла и авторизация попадают в правильное приложение.
- Проверьте внешний протокол. Убедитесь, что приложение видит HTTPS, корректный host и реальный адрес клиента. Смотрите не только тело ответа, но и редиректы с помощью заголовков ответа.
- Проверьте отказ upstream. Остановите тестовый процесс приложения и убедитесь, что Nginx отдаёт ожидаемую ошибку, а в журнале есть адрес проблемного upstream. Пользователь не должен получать страницу другого сервиса.
- Проверьте выпуск новой версии. Перезапустите или замените одно приложение, пока второе обслуживает запросы. Смотрите ошибки 502, 504, число активных соединений и время ответа.
Что обычно ломается
502 Bad Gateway
Чаще всего Nginx не может подключиться к upstream: процесс остановлен, порт другой, сокет недоступен или соединение отклонено firewall. Сверьте адрес из блока upstream с фактическим слушающим портом и журналом приложения.
404 после добавления префикса
Приложение получило путь /api/orders, хотя ожидало /orders, или наоборот. Сравните два варианта proxy_pass с завершающим слэшем и без него, затем посмотрите путь в access log приложения.
Бесконечный редирект на HTTPS
Обычно приложение не видит X-Forwarded-Proto: https или не настроено доверять прокси. Исправляйте доверенные прокси в самом приложении, а не подменяйте схему случайным заголовком от клиента.
504 Gateway Timeout
Upstream не прислал данные в установленный срок. Не начинайте с увеличения таймаута: сначала измерьте время запроса, найдите медленный SQL или внешнюю зависимость и проверьте, нужен ли этому endpoint синхронный ответ.
WebSocket сразу закрывается
Проверьте HTTP/1.1, заголовки upgrade, таймауты и балансировщик перед Nginx. Если соединение проходит через несколько прокси, каждый из них должен корректно передавать WebSocket.
Где подход ломается
Один Nginx не решает проблемы приложения с неправильными абсолютными ссылками, общей cookie между сервисами или несогласованными правилами авторизации. При большом числе команд и независимых релизов маршрутизация по путям начинает усложнять тестирование: изменения одного сервиса затрагивают общий конфиг и общий домен.
Отдельно проверяйте кэширование, rate limiting и инвалидацию кеша — это самостоятельные темы. Не добавляйте кэш для API только потому, что ответ выглядит одинаковым: там могут быть персональные данные и заголовки авторизации.
Что делать дальше
После базовой проверки добавьте метрики по каждому upstream: долю 4xx и 5xx, время ответа, число активных соединений и размер ответов. Затем настройте ротацию access и error log, проверку конфигурации в CI и безопасный reload вместо ручных правок на сервере. Если маршрутов станет больше, вынесите повторяющиеся proxy-заголовки в понятный включаемый фрагмент, но сохраняйте отдельные правила для WebSocket, загрузок и долгих операций.
Тендерный специалист 44-ФЗ / 223-ФЗ: Разбор PDF-документации закупки, поиск «заточек» под поставщика, чек-лист заявки.
Спросить за 20 ₽Источники: NGINX ngx_http_proxy_module documentation, NGINX ngx_http_upstream_module documentation
Частые вопросы
Почему запрос к /api/ попадает в веб-приложение?
Чем опасен слэш в конце proxy_pass?
Нужно ли всегда добавлять заголовки WebSocket?
Что делать, если после выпуска появился 504?
Можно ли использовать один Nginx для нескольких HTTPS-доменов?
Как понять, что приложение получает реальный IP клиента?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.