Servers Guide

Nginx как reverse proxy: Node.js и Python за Nginx

Полная конфигурация Nginx как reverse proxy: proxy_pass, заголовки X-Forwarded-For, несколько приложений на одном сервере, WebSocket, статика и таймауты.

Проверено: Ubuntu 22.04, Nginx 1.24

Nginx как reverse proxy — один из самых распространённых паттернов: принимает HTTPS-запрос снаружи, передаёт его на внутренний сервис (Node.js, Python/Gunicorn, Go) и возвращает ответ клиенту. Это позволяет любому приложению работать за HTTPS без встроенной поддержки TLS.

Зачем reverse proxy

  • TLS termination — Nginx принимает HTTPS, в backend идёт HTTP по localhost
  • Один сервер — несколько приложений по разным доменам или путям
  • Статические файлы отдаёт Nginx напрямую, не нагружая приложение
  • Rate limiting, кэш, сжатие на уровне прокси без изменения кода приложения

Базовая конфигурация: приложение на порту 3000

server {
    listen 443 ssl http2;
    server_name app.example.com;

    ssl_certificate     /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;

    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 support
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_cache_bypass $http_upgrade;
    }
}
Совет: Заголовок X-Forwarded-For передаёт реальный IP клиента в приложение. Без него приложение будет видеть только 127.0.0.1.

Несколько приложений на одном сервере по доменам

# /etc/nginx/sites-available/multi-app

server {
    listen 443 ssl http2;
    server_name api.example.com;
    # ssl ...
    location / { proxy_pass http://127.0.0.1:3001; proxy_set_header Host $host; }
}

server {
    listen 443 ssl http2;
    server_name admin.example.com;
    # ssl ...
    location / { proxy_pass http://127.0.0.1:4000; proxy_set_header Host $host; }
}

Reverse proxy по пути (один домен — несколько сервисов)

server {
    listen 443 ssl http2;
    server_name example.com;
    # ssl...

    # Frontend — React/Vue/static
    location / {
        root /var/www/frontend/dist;
        try_files $uri /index.html;
    }

    # API — Node.js/Python
    location /api/ {
        proxy_pass http://127.0.0.1:3000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # WebSocket
    location /ws/ {
        proxy_pass http://127.0.0.1:8080/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
    }
}

Таймауты и буферизация

# Добавить в location {} или server {}
proxy_connect_timeout   10s;
proxy_send_timeout      30s;
proxy_read_timeout      60s;

proxy_buffering         on;
proxy_buffer_size       4k;
proxy_buffers           8 4k;
Внимание: Если backend медленный (генерирует большие ответы), увеличьте proxy_read_timeout. Если видите 504 Gateway Timeout — именно этот параметр.

Статические файлы через Nginx, не backend

location /static/ {
    alias /var/www/myapp/static/;
    expires 30d;
    access_log off;
    add_header Cache-Control "public, immutable";
}

location /uploads/ {
    alias /var/www/myapp/uploads/;
    expires 7d;
}

Проверить конфигурацию

sudo nginx -t && sudo systemctl reload nginx

# Проверить что запрос проходит до backend
curl -I https://app.example.com/api/health

Итог

Nginx как reverse proxy: proxy_pass на backend, X-Forwarded-For для реального IP клиента, отдача статики напрямую. Добавляет TLS, rate limiting и кэш без изменения кода приложения.