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

Доступ участников к шине

Шина гетерогенна (event-bus-concept.md, разделы 1, 3): участники разнородны и часть из них внешние. Поэтому у шины два класса подключения с разной обвязкой.

Две сети, два класса участников

Класс Кто Как подключается Транспорт
Свои (on-box) сервисы Coolify на той же машине (n8n, боты, Go/Python-сервисы, мост) общая Docker-сеть event-bus nats://nats:4222
Внешние чужие API, другие машины/стеки публичный домен Coolify wss://<домен> (Traefik → ws 8080)

Хранилища движка (postgres, redis) и сам inngest — на сети internal, в шину и наружу не светятся. Движок — участник через мост, не напрямую.

Свои участники (общая сеть)

Шина владеет сетью event-bus (объявлена в stacks/bus/docker-compose.yml). Чтобы свой сервис увидел nats:4222 по DNS, он подключается к той же сети. В его compose:

services:
  my-service:
    networks: [event-bus]
    environment:
      NATS_URL: nats://nats:4222
networks:
  event-bus:
    external: true     # сеть создаёт стек шины, мы только присоединяемся

В Coolify это же делается тумблером «подключить к предопределённой сети» для ресурса. Публичный эндпойнт таким участникам не нужен.

Внешние участники (wss через Traefik)

Сырой порт 4222 наружу не выставляется. Внешние ходят по NATS WebSocket:

  1. Traefik (proxy Coolify) терминирует TLS на 443 и проксирует на ws-листенер NATS (websocket { port: 8080 }, см. stacks/bus/nats/nats-server.conf).
  2. В Coolify сервису nats назначается домен на порт 8080 → Let's Encrypt выдаёт сертификат автоматически.
  3. Внешний клиент подключается на wss://<домен> (клиенты NATS для Go/JS/Python умеют WebSocket-транспорт).

Назначать домен можно — авторизация шины включена (ниже), поэтому публичный ws не открыт на запись без кред.

Почему не обратный прокси (Caddy/Traefik) для авторизации шины: прокси видит только ws/TCP-поток и не понимает NATS-протокол — он не может применить права на subject'ы и не различает участников. Авторизация шины обязана жить внутри NATS. Прокси уместен только для HTTP-дашбордов (Inngest/мониторинг).

Авторизация (включена)

Модель — общие users с правами на subject'ы (зафиксировано, #10). Конфиг — в stacks/bus/nats/nats-server.conf:

  • Внутренние (мост, ops, smoke-тест) — пользователь internal с полным доступом, пароль из NATS_INTERNAL_PASSWORD (Infisical). no_auth_user НЕ задан: раз ws публичный, креды обязаны предъявлять все, иначе любой подключится без пароля.
  • Внешние — каждый со своими кредами (user/password) и allow-list на subject'ы. Это «контракт как ворота» (раздел 7) в рантайме: участник физически пишет/читает только заявленные в контракте subject'ы.

Пароли — через env-интерполяцию NATS ($VAR), значения из Infisical (secrets.md). В nats-server.conf — только имена переменных.

Гранулярность: остановились на users (проще, достаточно для нескольких участников). Переход на accounts (изоляция неймспейсов) — когда появится недоверенная сторона; отдельным решением, не сейчас.

Онбординг внешнего участника (по контракту, раздел 9)

  1. PR в contracts/asyncapi.yaml: какие subject'ы публикует/потребляет.
  2. Завести креды участника (значение — в Infisical, имя — в secrets.md).
  3. Добавить юзера с allow-list на эти subject'ы в nats-server.conf.
  4. Передать участнику wss://<домен> + креды.
  5. Отразить в каталоге зависимостей (когда он появится, раздел 10).

Удаление — зеркально: убрать юзера, отозвать креды, PR в контракты, чистка осиротевших consumer'ов (раздел 9).