VDS · Сайты и веб-серверы

Обратный прокси: несколько приложений на одном адресе

Как раздать один публичный адрес VDS между несколькими приложениями по доменам и путям, правильно передать заголовки и не сломать WebSocket.

Обновлено 23 августа 2026 г.

У машины один публичный адрес IPv4, а приложений на ней обычно несколько. Обратный прокси принимает все запросы на 80 и 443 порты и раздаёт их внутренним сервисам по имени домена или пути. Заодно на нём живёт единственный сертификат и общие логи.

Схема

Каждое приложение слушает свой локальный порт и только 127.0.0.1:

  • сайт-фронтенд — 127.0.0.1:3000;
  • API — 127.0.0.1:8000;
  • панель мониторинга — 127.0.0.1:9090.

Наружу торчит только Nginx. Проверить, что приложение не выставлено напрямую:

ss -tulpn | grep LISTEN

Строки вида 0.0.0.0:3000 означают, что сервис доступен из интернета в обход прокси и без шифрования.

По доменам

server {
    listen 80;
    server_name app.example.ru;
    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;
    }
}

server {
    listen 80;
    server_name api.example.ru;
    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Без X-Forwarded-For приложение будет видеть все запросы как пришедшие с 127.0.0.1, и любые ограничения по IP перестанут работать.

По путям

location /api/ {
    proxy_pass http://127.0.0.1:8000/;
}

Здесь важна косая черта в конце proxy_pass: с ней префикс /api отрезается и приложение получает /users, без неё — /api/users. Половина «непонятных 404» на прокси растёт именно отсюда.

WebSocket и долгие ответы

location /ws/ {
    proxy_pass http://127.0.0.1:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 3600s;
}

Без пары Upgrade/Connection соединение рвётся сразу после рукопожатия, а без увеличенного таймаута — через минуту тишины.

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

СимптомПричина
502 Bad GatewayПриложение не запущено или слушает другой порт
504 Gateway Time-outПриложение отвечает дольше proxy_read_timeout
Бесконечный редиректПриложение не знает про HTTPS — передайте X-Forwarded-Proto
Ломается загрузка файловМал client_max_body_size, по умолчанию 1 МБ
В логах приложения один и тот же IPНе передан X-Forwarded-For

Дальше: несколько сайтов, сертификат, Caddy с автоматическим HTTPS.

Один сертификат на прокси покрывает все приложения за ним. Внутренние соединения по 127.0.0.1 шифровать не нужно — они не покидают машину.