Путь к файлу со значениями был жёстко зашит как `<корень>/.env`. На
машине разработчика корневой `.env` держит боевые адреса
(LIVEKIT_NODE_IP/TURN_EXTERNAL_IP смотрят на прод), поэтому рендерить из
него конфиги для локального стенда нельзя, а подменить нечем — локальные
сессии дважды повторяли логику скрипта вручную через envsubst, что
означало расхождение с реальным рендером при первой же правке шаблонов.
Теперь источник значений задаётся переменной ENV_FILE:
ENV_FILE=.env.local ./deploy/render-templates.sh
Поведение по умолчанию не меняется — тот же корневой `.env`. install.sh
свою переменную ENV_FILE не экспортирует, так что она сюда не протекает;
вызов из install.sh и рендер на сервере работают как раньше. Скрипт
дополнительно печатает, из какого файла взяты значения, и подсказывает
про ENV_FILE, если файл не найден.
106 lines
7.7 KiB
Bash
Executable File
106 lines
7.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Рендерит статические конфиги coturn/LiveKit из шаблонов (deploy/**/*.template)
|
||
# в реальные файлы, которые монтирует docker-compose. Оба образа (coturn,
|
||
# livekit-server) НЕ поддерживают подстановку переменных окружения в файле
|
||
# конфигурации (см. комментарии в *.template) — единственный способ вынести
|
||
# секреты/IP в .env и не хранить их в git — сгенерировать файл перед стартом.
|
||
#
|
||
# Вызывается автоматически из install.sh. При ручном запуске (без install.sh)
|
||
# запускайте ПЕРЕД `docker compose up` (и после каждого изменения .env,
|
||
# влияющего на эти конфиги) — из корня репозитория:
|
||
# ./deploy/render-templates.sh
|
||
#
|
||
# Источник значений можно подменить переменной ENV_FILE:
|
||
# ENV_FILE=.env.local ./deploy/render-templates.sh
|
||
# Это нужно для локальных стендов: корневой `.env` рабочего чекаута обычно
|
||
# держит боевые значения (LIVEKIT_NODE_IP/TURN_EXTERNAL_IP смотрят на прод), и
|
||
# рендерить конфиги из него для локального запуска нельзя. Без этой переменной
|
||
# путь был жёстко зашит, и локальные сессии повторяли логику скрипта вручную
|
||
# через envsubst — расхождение с реальным рендером ждало своего часа.
|
||
# По умолчанию — как раньше, `<корень репозитория>/.env`, поэтому install.sh
|
||
# и сервер ничего не замечают (свою переменную ENV_FILE install.sh не
|
||
# экспортирует, так что она сюда не протекает).
|
||
set -euo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
# Относительный путь разрешаем от текущей директории вызова (`ENV_FILE=.env.local`
|
||
# из корня репозитория), абсолютный — как есть.
|
||
ENV_FILE="${ENV_FILE:-$SCRIPT_DIR/../.env}"
|
||
|
||
if [ ! -f "$ENV_FILE" ]; then
|
||
echo "render-templates.sh: не найден $ENV_FILE — сначала запустите ./install.sh или скопируйте .env.example в .env" >&2
|
||
echo "render-templates.sh: другой файл значений можно задать так: ENV_FILE=.env.local $0" >&2
|
||
exit 1
|
||
fi
|
||
|
||
echo "[render] источник значений: $ENV_FILE"
|
||
|
||
# Читаем только нужные ключи через grep/cut (НЕ `source .env`) — .env содержит
|
||
# значения вроде `SMTP_FROM=VidConf <no-reply@vidconf.example>`, где `<` —
|
||
# валидный литерал для docker-compose/pydantic, но невалидный bash-синтаксис
|
||
# (интерпретируется как редирект) при попытке `source` файла целиком.
|
||
#
|
||
# `|| true` в конце обязателен: под `set -e -o pipefail` (см. выше) сборка
|
||
# `"$(env_var VAR)"` для ключа, которого в файле нет ВООБЩЕ (не просто
|
||
# пустое значение, а отсутствующая строка) иначе завершает весь скрипт
|
||
# ошибкой grep ДО того, как сработает дружелюбная проверка `:?` ниже —
|
||
# найдено на TURN_TLS_HOST (новый необязательный ключ, есть не во всех
|
||
# существующих .env).
|
||
env_var() {
|
||
grep -E "^${1}=" "$ENV_FILE" 2>/dev/null | tail -1 | cut -d= -f2- || true
|
||
}
|
||
|
||
TURN_STATIC_AUTH_SECRET="$(env_var TURN_STATIC_AUTH_SECRET)"
|
||
TURN_REALM="$(env_var TURN_REALM)"
|
||
TURN_EXTERNAL_IP="$(env_var TURN_EXTERNAL_IP)"
|
||
# TURN_TLS_HOST — единственный переключатель TURN over TLS (5349) во всём
|
||
# проекте: непустой = TLS смонтирован и объявляется клиентам, пустой = TLS
|
||
# отсутствует везде (dev по умолчанию). Поэтому НЕ обязателен (без `:?`) —
|
||
# в отличие от TURN_EXTERNAL_IP, который должен быть IP хоста, TURN_TLS_HOST
|
||
# обязан быть ДОМЕНОМ сертификата (иначе браузер не пройдёт TLS-валидацию
|
||
# по имени хоста для `turns:`, см. комментарий в livekit.yaml.template).
|
||
TURN_TLS_HOST="$(env_var TURN_TLS_HOST)"
|
||
LIVEKIT_API_KEY="$(env_var LIVEKIT_API_KEY)"
|
||
LIVEKIT_NODE_IP="$(env_var LIVEKIT_NODE_IP)"
|
||
LIVEKIT_USE_EXTERNAL_IP="$(env_var LIVEKIT_USE_EXTERNAL_IP)"
|
||
REDIS_PASSWORD="$(env_var REDIS_PASSWORD)"
|
||
|
||
: "${TURN_STATIC_AUTH_SECRET:?TURN_STATIC_AUTH_SECRET не задан в .env}"
|
||
: "${TURN_REALM:?TURN_REALM не задан в .env}"
|
||
: "${TURN_EXTERNAL_IP:?TURN_EXTERNAL_IP не задан в .env (внешний IP/домен сервера для TURN-релея)}"
|
||
: "${LIVEKIT_API_KEY:?LIVEKIT_API_KEY не задан в .env}"
|
||
: "${LIVEKIT_NODE_IP:?LIVEKIT_NODE_IP не задан в .env (внешний IP/домен для ICE)}"
|
||
: "${LIVEKIT_USE_EXTERNAL_IP:?LIVEKIT_USE_EXTERNAL_IP не задан в .env (true/false)}"
|
||
: "${REDIS_PASSWORD:?REDIS_PASSWORD не задан в .env (redis запускается с --requirepass, см. docker-compose.yml)}"
|
||
|
||
export TURN_STATIC_AUTH_SECRET TURN_REALM TURN_EXTERNAL_IP TURN_TLS_HOST LIVEKIT_API_KEY LIVEKIT_NODE_IP LIVEKIT_USE_EXTERNAL_IP REDIS_PASSWORD
|
||
|
||
# Вырезает блок между парой маркеров-комментариев (не только их самих), если
|
||
# TURN_TLS_HOST пуст — так рендер отражает реальное наличие TLS-сертификатов,
|
||
# а не просто закомментированные "на будущее" строки.
|
||
strip_tls_block_if_disabled() {
|
||
local file="$1" begin_marker="$2" end_marker="$3"
|
||
if [ -z "$TURN_TLS_HOST" ]; then
|
||
sed -i.bak "/${begin_marker}/,/${end_marker}/d" "$file" && rm -f "$file.bak"
|
||
else
|
||
sed -i.bak "/${begin_marker}/d; /${end_marker}/d" "$file" && rm -f "$file.bak"
|
||
fi
|
||
}
|
||
|
||
envsubst '${TURN_STATIC_AUTH_SECRET} ${TURN_REALM} ${TURN_EXTERNAL_IP}' \
|
||
< "$SCRIPT_DIR/coturn/turnserver.conf.template" > "$SCRIPT_DIR/coturn/turnserver.conf"
|
||
strip_tls_block_if_disabled "$SCRIPT_DIR/coturn/turnserver.conf" "# BEGIN-TLS-CERT" "# END-TLS-CERT"
|
||
echo "[render] deploy/coturn/turnserver.conf готов$([ -n "$TURN_TLS_HOST" ] && echo " (TLS включён)" || echo " (TLS выключен — TURN_TLS_HOST пуст)")"
|
||
|
||
# TURN_EXTERNAL_IP и TURN_STATIC_AUTH_SECRET нужны и здесь: с 0.0.14 LiveKit
|
||
# анонсирует клиентам внешний coturn (секция `rtc.turn_servers`), и секрет
|
||
# обязан совпадать с `static-auth-secret` в turnserver.conf выше.
|
||
envsubst '${LIVEKIT_USE_EXTERNAL_IP} ${LIVEKIT_NODE_IP} ${LIVEKIT_API_KEY} ${REDIS_PASSWORD} ${TURN_EXTERNAL_IP} ${TURN_STATIC_AUTH_SECRET} ${TURN_TLS_HOST}' \
|
||
< "$SCRIPT_DIR/livekit/livekit.yaml.template" > "$SCRIPT_DIR/livekit/livekit.yaml"
|
||
strip_tls_block_if_disabled "$SCRIPT_DIR/livekit/livekit.yaml" "# BEGIN-TLS-TURN" "# END-TLS-TURN"
|
||
echo "[render] deploy/livekit/livekit.yaml готов"
|
||
|
||
envsubst '${REDIS_PASSWORD}' \
|
||
< "$SCRIPT_DIR/egress/egress.yaml.template" > "$SCRIPT_DIR/egress/egress.yaml"
|
||
echo "[render] deploy/egress/egress.yaml готов"
|