Перейти к содержимому

Nginx как обратный прокси для приложения

Спрятать Node.js, Python или Go-приложение за Nginx: HTTPS, правильные заголовки и WebSocket.

Уровень
Средний
Время чтения
3 мин чтения
Обновлено
Проверено на
Ubuntu 22.04, Ubuntu 24.04, Debian 12
Содержание
  1. Приложение слушает только localhost
  2. Конфигурация Nginx
  3. Зачем эти заголовки
  4. Статику — напрямую
  5. Проверьте результат
  6. Частые ошибки

Приложение слушает локальный порт, например 127.0.0.1:3000, а наружу смотрит только Nginx. Так приложение не видно из интернета напрямую, HTTPS настраивается в одном месте, а статику отдаёт Nginx без участия приложения.

Приложение слушает только localhost

Убедитесь, что приложение привязано к 127.0.0.1, а не к 0.0.0.0. Посмотреть, кто какой порт слушает:

bash
$ ss -tlnp

Конфигурация Nginx

/etc/nginx/sites-available/app.example.com
map $http_upgrade $connection_upgrade {    default upgrade;    ''      close;}server {    listen 80;    listen [::]:80;    server_name app.example.com;    client_max_body_size 20m;    location / {        proxy_pass http://127.0.0.1:3000;        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;        # WebSocket        proxy_set_header Upgrade $http_upgrade;        proxy_set_header Connection $connection_upgrade;        proxy_read_timeout 60s;    }}

Блок map объявляется один раз на весь сервер (в контексте http). Если сайтов с WebSocket несколько, вынесите его в отдельный файл /etc/nginx/conf.d/upgrade.conf.

bash
$ ln -s /etc/nginx/sites-available/app.example.com /etc/nginx/sites-enabled/$ nginx -t && systemctl reload nginx$ certbot --nginx -d app.example.com

Зачем эти заголовки

  • Host — приложение видит настоящий домен, а не 127.0.0.1.
  • X-Real-IP и X-Forwarded-For — реальный IP посетителя для логов и ограничений. В приложении включите доверие к прокси (trust proxy в Express, ProxyFix во Flask).
  • X-Forwarded-Proto — приложение понимает, что запрос пришёл по HTTPS, и строит правильные ссылки и cookie.
  • Upgrade и Connection — без них WebSocket-соединения обрываются сразу после рукопожатия.

Статику — напрямую

Если у приложения есть каталог со статикой, отдавайте его Nginx-ом — это быстрее и разгружает приложение:

nginx
location /static/ {    alias /var/www/app/static/;    expires 7d;    access_log off;}

Проверьте результат

bash
$ curl -I http://127.0.0.1:3000$ curl -I https://app.example.com

Частые ошибки

  • 502 Bad Gateway — приложение не запущено или слушает другой порт. Смотрите ss -tlnp и журнал приложения.
  • 504 Gateway Timeout — приложение отвечает дольше proxy_read_timeout. Увеличьте таймаут или ускорьте обработку.
  • 413 Request Entity Too Large — загрузка больше client_max_body_size (по умолчанию 1 МБ).
  • Бесконечный редирект на HTTPS — приложение не получает X-Forwarded-Proto и считает, что запрос пришёл по HTTP.

Дочитайте до конца — статья засчитается в обучении автоматически.

  • Nginx
  • прокси
  • reverse proxy
  • proxy_pass
  • WebSocket

Статья помогла?