Перейти к содержанию

Reverse Proxy

Nginx — единая точка входа в платформу. Принимает весь внешний трафик, выполняет TLS-терминирование, проксирует запросы на backend и frontend, ограничивает скорость запросов, публикует административные интерфейсы pgAdmin и RabbitMQ Management. Поставляется как отдельный блок Docker Compose.

Эта статья описывает структуру блока nginx и конфигурацию виртуальных серверов. Установка по шагам — в Быстром старте / п. 4.8 «Nginx». Выпуск сертификатов — в Настройке безопасности.

Структура блока

Каталог блока — /etc/datahub/nginx/:

/etc/datahub/nginx/
├── docker-compose.yml        # описание контейнера
├── certs/                    # TLS-сертификаты и скрипты их выпуска
│   ├── ca.crt, ca.key
│   ├── server.crt, server.key
│   ├── <your-domain>.crt, <your-domain>.key
│   ├── generate-root-CA.sh
│   ├── generate-server-cert.sh
│   └── generate-client-cert.sh
├── config/
│   ├── nginx.conf            # глобальная конфигурация
│   └── conf.d/               # серверы для конкретных доменов и портов
│       ├── http.conf         # HTTP→HTTPS-редирект
│       ├── lk.<domain>.conf  # личный кабинет
│       ├── exchange.<domain>.conf  # exchange API
│       ├── pg-admin.conf     # reverse-proxy на pgAdmin (порт 15432)
│       └── rmq-admin.conf    # reverse-proxy на RabbitMQ Management (порт 15672)
├── html/                     # статика (заглушки на корень domain)
├── log/                      # access/error логи (bind-mount)
└── scripts/
    ├── selfsigned/           # генерация self-signed сертификатов
    └── letsencrypt/          # автоматизация Let's Encrypt

Файл docker-compose.yml:

services:
  nginx:
    image: registry.gitlab.com/datahub/v3/services/nginx:main
    container_name: nginx
    hostname: nginx
    environment:
      - TZ=Europe/Moscow
    volumes:
      - ./certs:/etc/nginx/certs:ro
      - ./config/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./config/conf.d:/etc/nginx/conf.d:ro
      - ./html:/usr/share/nginx/html:ro
      - ./log/:/var/log/nginx/:rw
      - /var/www/letsencrypt:/var/www/letsencrypt:ro
    ports:
      - "80:80"        # redirect to https
      - "443:443"      # https
      # - "18443:18443"  # uncomment for single-domain-two-ports
      - "15432:15432"  # pg-admin reverse proxy
      - "15672:15672"  # rmq-admin reverse proxy
    restart: always
    networks:
      - dh_network

Это единственный блок поставки с пробросом портов (ports:) — весь остальной трафик платформы изолирован в dh_network.

Глобальная конфигурация (nginx.conf)

config/nginx.conf задаёт глобальные настройки HTTP-уровня и подключает все серверы из conf.d/. Полный файл лежит в шаблоне поставки (devops/deployment-templates/nginx/config/nginx.conf). Ключевые параметры платформы:

Директива Значение Назначение
worker_connections 1024 Максимум одновременных соединений на воркер.
client_max_body_size 128m Максимальный размер тела запроса. Лимит обусловлен моделью передачи бинарных вложений внутри сообщения (до выпуска S3).
proxy_buffering off Стриминговое проксирование без буферизации — важно для long-polling exchange API.
proxy_read_timeout 120s Согласовано с polling-timeout: 90000 и request-timeout: 120000 в backend.
keepalive_timeout 65 Сохранение HTTP-keepalive для эффективного proxy на frontend.
gzip on gzip Сжатие текстовых ответов (text, JSON, JavaScript, CSS).
limit_req_zone req_per_ip rate=10r/s Базовый лимит на любой API-эндпоинт с одного IP.
limit_req_zone auth_per_ip rate=5r/m Жёсткий лимит на эндпоинты авторизации.

Логи всех виртуальных серверов пишутся в едином формате datahub_format (ISO-время, статус, request, IP, User-Agent, X-Forwarded-For) — это упрощает анализ через Диагностика / Анализ логов.

Схемы публикации

Платформа поддерживает две схемы публикации внешних сервисов.

Схема по умолчанию: два домена

Сервис Адрес Порт
Личный кабинет (frontend + backend API) lk.<your-domain> 443
Exchange API (только эндпоинты обмена) exchange.<your-domain> 443
pgAdmin (опционально) lk.<your-domain>:15432 15432
RabbitMQ Management lk.<your-domain>:15672 15672

Конфиги:

  • conf.d/http.conf — два HTTP-сервера для lk.<domain> и exchange.<domain>, оба редиректят на HTTPS, обслуживают /.well-known/acme-challenge/ для Let's Encrypt.
  • conf.d/lk.<domain>.conf — полный фронт + API, проксирует на frontend:3000 (frontend сам ходит в backend).
  • conf.d/exchange.<domain>.conf — только эндпоинты /api/exchange/ и /api/auth/, проксирует напрямую на backend:80. Корневой запрос отдаёт 404.
  • conf.d/pg-admin.conf — слушает порт 15432, проксирует на pg-admin:80 с поддержкой WebSocket.
  • conf.d/rmq-admin.conf — слушает порт 15672, проксирует на rabbitmq:15672.

Альтернативная схема: один домен, два порта

Используется, если заказчик не может или не хочет выпускать второе доменное имя. Личный кабинет переезжает на нестандартный порт (например, 18443), exchange остаётся на 443.

Пример конфигурации лежит в /etc/datahub/nginx/config/conf.d/examples/single-domain-two-ports/ с README. Краткая инструкция применения — в Быстром старте / п. 4.8 «Nginx». После замены конфигов не забыть пробросить порт 18443 в docker-compose.yml блока nginx и открыть его на сетевом firewall.

Виртуальный сервер личного кабинета (lk)

Файл conf.d/lk.<your-domain>.conf обслуживает домен личного кабинета и проксирует на frontend (frontend сам обращается к backend для API-вызовов). Ключевые блоки:

  • listen 443 ssl; + сертификат — терминирование HTTPS.
  • Стандартные proxy-заголовки: Host, X-Real-IP, X-Forwarded-For, X-Forwarded-Proto.
  • location ^~ /api/auth/ — жёсткий лимит auth_per_ip burst=5 nodelay, проксирование на http://frontend:3000, отдельный лог access_auth.log.
  • location ^~ /api/ — базовый лимит req_per_ip burst=20 nodelay, проксирование на http://frontend:3000, лог access_api.log.
  • location ^~ /docs/ — документация backend (Swagger UI), проксирование на http://backend:80 (минуя frontend), лог access_docs.log.
  • location = /healthz — встроенный healthcheck reverse-proxy, возвращает 200 OK.
  • location / — общий фронт, проксирование на http://frontend:3000.
  • limit_req_status 429 + error_page 429 = @ratelimit — кастомный ответ при превышении лимита с заголовком Retry-After: 60.

Полный конфиг — в шаблоне поставки (devops/deployment-templates/nginx/config/conf.d/lk.1dh.ru.conf), его надо адаптировать под фактический домен заказчика.

Обратите внимание: backend проксируется не напрямую, а через frontend (http://frontend:3000). Frontend выполняет дополнительную обработку (server-side rendering, переадресацию авторизации) и сам обращается к backend:80 внутри dh_network.

Виртуальный сервер обмена (exchange)

Файл conf.d/exchange.<your-domain>.conf обслуживает домен exchange API и проксирует напрямую на backend (без frontend). Ключевые отличия от lk-сервера:

  • add_header Strict-Transport-Security ...; X-Content-Type-Options nosniff; X-Frame-Options DENY; X-XSS-Protection 1; mode=block — полный набор security headers по умолчанию (на lk эти заголовки в шаблоне закомментированы и включаются опционально).
  • location ^~ /api/auth/http://backend:80/api/auth/ — авторизация напрямую, без frontend.
  • location ^~ /api/exchange/http://backend:80/api/exchange/ — основные эндпоинты обмена.
  • location /return 404; — ничего, кроме /api/auth/ и /api/exchange/, на этом домене не отдаётся.

Назначение раздельного домена для обмена:

  • упростить настройку клиентских адаптеров (отдельный URL без необходимости знать структуру личного кабинета);
  • позволить отдельную сетевую политику для трафика обмена (например, разрешить доступ интегрируемым системам по белому списку IP только к этому домену);
  • ограничить площадь поверхности атаки — на exchange.<domain> нет ни фронта, ни админских эндпоинтов.

Reverse-proxy на pgAdmin и RabbitMQ Management

Файлы conf.d/pg-admin.conf и conf.d/rmq-admin.conf устроены одинаково: слушают отдельный порт хоста (15432 и 15672), терминируют TLS, проксируют запросы на соответствующий сервис в dh_network с поддержкой WebSocket.

Особенности:

  • listen 15432 ssl default_server; server_name _; — принимают любой Host (по сути «свой собственный» виртуальный сервер на каждом порту).
  • Используют общий серверный сертификат server.crt/server.key, отдельные сертификаты под админские порты не нужны.
  • proxy_connect_timeout 300; proxy_send_timeout 300; proxy_read_timeout 300; — увеличенные таймауты под длительные операции pgAdmin (восстановление, экспорт).
  • proxy_http_version 1.1 + Upgrade $http_upgrade + Connection "upgrade" — поддержка WebSocket (требуется живым UI для обновления статистики).
  • add_header X-Frame-Options "SAMEORIGIN" — смягчённый по сравнению с DENY (нужно для встроенных iframe в pgAdmin).

Эти эндпоинты — для администраторов, не для интегрируемых систем. На продуктивных стендах их доступ часто дополнительно ограничивается на сетевом firewall (разрешён только из VPN администраторов или из административной подсети).

Подстановка имён доменов

При установке шаблоны конфигов в conf.d/*.conf нужно адаптировать под фактические домена заказчика — в дефолтной поставке они идут с заглушками lk.1dh.ru / exchange.1dh.ru:

sudo sed -i 's/1dh\.ru/<your-domain>/g' /etc/datahub/nginx/config/conf.d/*.conf

Также проверить и поправить пути к сертификатам в ssl_certificate / ssl_certificate_key.

После правки — пересоздать контейнер nginx:

sudo docker compose -f /etc/datahub/nginx/docker-compose.yml up -d --force-recreate

Проверка и диагностика

Проверка корректности конфигурации без рестарта:

sudo docker exec nginx nginx -t

Применить обновлённый конфиг без полного рестарта (graceful reload):

sudo docker exec nginx nginx -s reload

Мониторинг сразу всех логов nginx (удобно для общего наблюдения):

sudo tail -f /etc/datahub/nginx/log/*

Общий access-лог:

sudo tail -f /etc/datahub/nginx/log/access.log

Общий error-лог:

sudo tail -f /etc/datahub/nginx/log/error.log

Раздельные access-логи по виртуальным серверам — каждый можно смотреть отдельно. access_api.log — обращения к /api/* на личном кабинете:

sudo tail -f /etc/datahub/nginx/log/access_api.log

access_auth.log — обращения к /api/auth/*:

sudo tail -f /etc/datahub/nginx/log/access_auth.log

access_auth_session.log — обращения к /api/auth/session*:

sudo tail -f /etc/datahub/nginx/log/access_auth_session.log

access_docs.log — обращения к документации backend:

sudo tail -f /etc/datahub/nginx/log/access_docs.log

access_exchange_log.log — обращения к exchange API:

sudo tail -f /etc/datahub/nginx/log/access_exchange_log.log

access_log_80.log — запросы на порт 80 до редиректа:

sudo tail -f /etc/datahub/nginx/log/access_log_80.log

access_log_15432.log — обращения к pgAdmin / RabbitMQ Management:

sudo tail -f /etc/datahub/nginx/log/access_log_15432.log

Что дальше