# LiveKit SFU. Верифицировано по официальной документации
# (github.com/livekit/livekit config-sample.yaml + configuration.md).
# Реальный API key/secret — из .env (LIVEKIT_API_KEY / LIVEKIT_API_SECRET);
# этот файл намеренно не содержит `keys:` — ключи передаются через
# LIVEKIT_KEYS (см. docker-compose.yml, формат "key: secret").
#
# LiveKit НЕ читает переменные окружения внутри своего YAML-конфига (в
# отличие от `keys:`, которые подаются отдельно через LIVEKIT_KEYS) —
# статические поля (use_external_ip/node_ip/webhook.api_key) рендерятся
# из этого шаблона в livekit.yaml скриптом deploy/render-templates.sh
# (envsubst) ПЕРЕД `docker compose up`. Не редактируйте livekit.yaml
# напрямую — правки затрутся при следующем рендере.

port: 7880

rtc:
  tcp_port: 7881
  # Один UDP-порт с мультиплексированием ICE вместо диапазона портов.
  # Раньше здесь был port_range_start/port_range_end (54000-54100) — под
  # каждый порт диапазона Docker поднимал отдельный процесс docker-proxy
  # (userland-прокси на весь медиатрафик), на 101 порт — 101 процесс.
  # udp_port переключает LiveKit на единственный сокет с демультиплексацией
  # по ICE ufrag; port_range_start/end при заданном udp_port игнорируются
  # (проверено по исходникам сервера) — оставлять их рядом бессмысленно.
  udp_port: 54000
  # use_external_ip: false + node_ip=127.0.0.1 — режим для локальной
  # разработки (Docker Desktop): use_external_ip=true определяет публичный
  # IP через STUN, что в контейнере на macOS даёт недостижимый изнутри хоста
  # внутренний IP (172.18.x.x) — DTLS-хендшейк по data-каналам не проходит
  # ("dtls timeout" в логах). node_ip=127.0.0.1 работает, потому что порты
  # 7881/tcp и 54000/udp проброшены на loopback хоста, а браузер-клиент
  # запускается на том же хосте.
  # В проде (LIVEKIT_USE_EXTERNAL_IP=true, LIVEKIT_NODE_IP=<внешний IP/домен
  # сервера> в .env) клиенты снаружи хоста подключаются по этому адресу —
  # сервер не должен быть за NAT без проброса портов 1:1.
  use_external_ip: ${LIVEKIT_USE_EXTERNAL_IP}
  node_ip: ${LIVEKIT_NODE_IP}

  # Внешний TURN (сервис coturn, профиль `media`) — АНОНС КЛИЕНТАМ.
  # Сам SFU через эти серверы не ходит: LiveKit лишь отдаёт их браузеру в
  # списке ICE-серверов при подключении (см. iceServersForParticipant в
  # pkg/service/roommanager.go), а клиент уже решает, нужен ли ему relay.
  #
  # Зачем. До 28.07.2026 coturn работал, но КЛИЕНТЫ О НЁМ НЕ ЗНАЛИ: секция
  # `turn` ниже выключена (встроенный TURN не поднимаем), внешний в конфиге
  # объявлен не был, а фронтенд `iceServers` не задаёт. За всё время работы
  # в логах coturn — ноль ALLOCATE. Итог: у клиентов из сетей с жёстким NAT
  # не было relay-фолбэка вообще, только прямой UDP и TCP 7881. Именно так
  # объясняются `PEER_CONNECTION_DISCONNECTED` на нагрузочном тесте — все
  # у внешних участников, ни одного у офисных (.forcc/LOAD-FINDINGS.md,
  # причина C).
  #
  # `secret` обязан совпадать с `static-auth-secret` в turnserver.conf —
  # оба рендерятся из одного TURN_STATIC_AUTH_SECRET (deploy/render-templates.sh).
  # Логин/пароль LiveKit генерирует сам по механизму TURN REST API.
  #
  # UDP и TCP на 3478 — оба порта уже открыты в ufw.
  #
  # TLS (5349) объявляется ТОЛЬКО когда в .env задан TURN_TLS_HOST (см.
  # render-templates.sh) — до тех пор блок между маркерами вырезается
  # целиком, и клиент его не увидит вовсе. Это осознанно: анонс
  # неработающего `turns:` (без смонтированных в coturn сертификатов)
  # заставил бы клиента впустую ждать TLS-таймаута, прежде чем перейти
  # к рабочему кандидату — именно так это и стояло здесь до включения TLS.
  #
  # Хост для TLS-записи обязан быть ДОМЕНОМ, а не IP (в отличие от udp/tcp
  # выше): браузер проверяет TLS-сертификат TURN-сервера по имени хоста,
  # а сертификат Let's Encrypt выписан на домен, не на IP — с IP в host
  # TLS-хендшейк упадёт на проверке имени, и это будет выглядеть как ещё
  # один вариант «coturn healthy, но relay не работает».
  #
  # TLS-запись стоит ПОСЛЕДНЕЙ: клиент перебирает кандидатов по порядку,
  # а TLS через TCP дороже прямого UDP — она должна быть фолбэком, а не
  # выбираться первой.
  turn_servers:
    - host: ${TURN_EXTERNAL_IP}
      port: 3478
      protocol: udp
      secret: ${TURN_STATIC_AUTH_SECRET}
      ttl: 14400
    - host: ${TURN_EXTERNAL_IP}
      port: 3478
      protocol: tcp
      secret: ${TURN_STATIC_AUTH_SECRET}
      ttl: 14400
    # BEGIN-TLS-TURN
    - host: ${TURN_TLS_HOST}
      port: 5349
      protocol: tls
      secret: ${TURN_STATIC_AUTH_SECRET}
      ttl: 14400
    # END-TLS-TURN

# Redis обязателен для сервиса egress (см. deploy/egress/) — он использует
# его как pub/sub и key-value хранилище состояния запущенных записей;
# без него egress не может получать room/track-события от LiveKit
# (проверено по официальной документации livekit/egress, раздел "Running
# locally"). LiveKit сам по себе тоже использует redis для координации
# между узлами кластера (здесь один узел, но сервис оставлен включённым).
# password подставляется рендером (deploy/render-templates.sh) из
# REDIS_PASSWORD в .env — redis в docker-compose.yml запускается с
# --requirepass, без пароля LiveKit не подключится (см.
# .forcc/deploy/SESSION2-FINDINGS.md про redis без пароля).
redis:
  address: redis:6379
  password: ${REDIS_PASSWORD}

# TURN обслуживает отдельный сервис coturn (профиль `media`, deploy/coturn).
# При публичной экспозиции LiveKit разместите coturn/TURN-TLS на 443 и
# держите эту секцию отключённой, чтобы не поднимать два TURN-сервера.
turn:
  enabled: false

# Webhook-приёмник backend'а: события room_started/participant_joined/
# participant_left/room_finished подписываются ключом api_key, который
# должен совпадать с одним из ключей в LIVEKIT_KEYS (см. выше и
# docker-compose.yml) — берём тот же LIVEKIT_API_KEY из .env.
webhook:
  api_key: ${LIVEKIT_API_KEY}
  urls:
    - http://backend:8000/api/v1/livekit/webhook
    # Если backend запускается на хосте (uvicorn вне docker-compose, а
    # LiveKit — внутри), используйте вместо этого:
    # - http://host.docker.internal:8000/api/v1/livekit/webhook

logging:
  level: info
  json: false

# Prometheus metrics (scraped by the monitoring profile).
prometheus:
  port: 6789
