Справочник

proxy_pass в nginx: как передать запросы приложению

Директива proxy_pass передаёт запросы из блока location другому серверу — например, приложению на Node.js или Python, которое слушает порт 3000 на том же VPS. nginx принимает посетителей на портах 80 и 443 и отдаёт им ответ приложения.

≈ 7 мин чтения
Содержание 8

Что сделать прямо сейчас

  1. Команды вводятся на сервере: подключитесь к нему по SSH ([как подключиться](/instrukcii/kak-podklyuchitsya-k-vps-po-ssh/)) и набирайте их в том же окне.
  2. Проверьте, что приложение отвечает: curl -I http://127.0.0.1:3000. Вместо 3000 — порт приложения. Если в первой строке ответа есть код, например 200 или 404, приложение работает. Если curl не может подключиться, приложение не запущено или слушает другой порт — как запустить.
  3. Откройте файл сайта: sudo nano /etc/nginx/sites-available/example.com. Вместо example.com — имя файла вашего сайта: список покажет ls /etc/nginx/sites-enabled/. Если система спросит пароль, введите пароль своего пользователя на сервере. Символы при вводе не видны — наберите пароль и нажмите Enter.
  4. В блоке server замените блок location / тем, что ниже. Второй блок location / не добавляйте.
  5. Сохраните файл — Ctrl+O, Enter, затем Ctrl+X — и проверьте настройки: sudo nginx -t. В ответе должны быть слова syntax is ok и test is successful. Тогда примените их: sudo systemctl reload nginx. Если команда ничего не ответила, настройки применены.

Если проверка нашла ошибку, nginx назовёт файл и номер строки, а сайт продолжит работать на старых настройках. Что значит сообщение — Все ошибки nginx.

Приложение на том же сервере

location / {
    proxy_pass http://127.0.0.1:3000;
    include proxy_params;
}

Вместо 3000 — порт вашего приложения. nginx передаёт приложению адрес запроса в том виде, в каком его прислал посетитель.

Строка include proxy_params подключает файл из пакета nginx в Ubuntu. В нём четыре строки:

СтрокаЧто узнаёт приложение
proxy_set_header Host $http_host;имя сайта из запроса, например example.com
proxy_set_header X-Real-IP $remote_addr;IP-адрес посетителя
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;цепочку адресов: к тому, что пришло в запросе, через запятую добавляется IP посетителя
proxy_set_header X-Forwarded-Proto $scheme;протокол: http или https

Без этих строк приложение видит вместо имени сайта адрес из proxy_pass — 127.0.0.1:3000, а вместо IP посетителя — 127.0.0.1.

Запускайте приложение на адресе 127.0.0.1: тогда до него не достучаться снаружи в обход nginx, и порт 3000 в фаерволе открывать не нужно. Как поставить nginx перед приложением с самого начала — в инструкции по размещению сайта.

Слэш после порта меняет адрес

Важно, есть ли что-то после адреса и порта в proxy_pass, — даже один слэш:

location /api/ {
    proxy_pass http://127.0.0.1:3000;
}
location /api/ {
    proxy_pass http://127.0.0.1:3000/;
}
Строка proxy_pass в location /api/Адрес в браузереЧто получит приложение
http://127.0.0.1:3000/api/users?id=5/api/users?id=5
http://127.0.0.1:3000//api/users?id=5/users?id=5
http://127.0.0.1:3000/v2//api/users?id=5/v2/users?id=5

Правило такое. Если после порта ничего нет, адрес уходит приложению как пришёл. Если есть путь, nginx заменяет им часть адреса, совпавшую с location.

Пишите слэш в конце одинаково у location и proxy_pass. Блок location /api со строкой proxy_pass http://127.0.0.1:3000/ отдаст приложению адрес //users с двумя слэшами.

В location с регулярным выражением и в именованном location с @ после порта ничего писать нельзя: проверка sudo nginx -t выдаст ошибку "proxy_pass" cannot have URI part.

Если location записан со слэшем в конце, на адрес без слэша — /api — nginx ответит переадресацией 301 на /api/. Как этого избежать — в разделе про слэш.

WebSocket

Если приложение использует WebSocket — чат, уведомления без перезагрузки страницы, — добавьте в его location ещё три строки:

location / {
    proxy_pass http://127.0.0.1:3000;
    include proxy_params;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

Заголовки Upgrade и Connection nginx приложению сам не передаёт — их задают явно. Строка proxy_http_version 1.1 нужна в nginx из Ubuntu 24.04 и 26.04: он по умолчанию обращается к приложению по HTTP/1.0, а сменить протокол на WebSocket через заголовок Upgrade можно только в HTTP/1.1.

Пишите эти строки в том же блоке, где include proxy_params. Если в location есть хоть одна своя строка proxy_set_header, строки proxy_set_header из server и http в нём не действуют.

Если по WebSocket 60 секунд не идут данные, nginx закрывает соединение. Чтобы держать его дольше, поднимите таймаут, например proxy_read_timeout 1h;, или настройте в приложении периодическую отправку ping.

Таймауты

ДирективаПо умолчаниюСколько nginx ждёт
proxy_connect_timeout60sподключения к приложению
proxy_send_timeout60sмежду двумя отправками запроса приложению
proxy_read_timeout60sмежду двумя порциями ответа приложения

Таймауты считаются не на весь ответ, а на паузу между порциями данных. Если приложение молчит дольше proxy_read_timeout, посетитель получит 504 — какие таймауты за это отвечают и как поднять.

Ошибки и как их исправить

Что видитеЧто делать
502, в журнале connect() failed (111: Connection refused) while connecting to upstreamприложение не запущено или слушает другой порт
502, в журнале upstream prematurely closed connectionприложение оборвало ответ
504 Gateway Time-outприложение отвечает дольше таймаута
host not found in upstream при проверке nginx -tnginx не нашёл IP для имени из proxy_pass
"proxy_pass" cannot have URI part in location given by regular expression…уберите всё после порта: в таком location адрес пишут без пути
приложение получает адрес без /api или с двумя слэшамипроверьте слэш после порта
WebSocket не подключаетсядобавьте три строки
приложение видит IP 127.0.0.1 вместо адреса посетителядобавьте include proxy_params; в тот же location, где proxy_pass

Источники

Сверено 14 октября 2026 года.

Что почитать дальше