diff --git a/deploy/install.sh b/deploy/install.sh index 2f1b848..25e444d 100755 --- a/deploy/install.sh +++ b/deploy/install.sh @@ -61,6 +61,10 @@ TURN_CERT_SRC="${TURN_CERT_SRC:-}" TURN_CERT_SRC_KEY="${TURN_CERT_SRC_KEY:-}" TURN_RELAY_HOST="${TURN_RELAY_HOST:-}" TURN_RELAY_PORT="${TURN_RELAY_PORT:-3478}" +# Имя хоста для TURN/TLS: сертификат Let's Encrypt выписан на turn.<домен>, и +# браузеры отклоняют TLS-соединение к IP (несовпадение имени). По умолчанию +# берём turn.<домен>; если он не резолвится, остаётся адрес релея. +TURN_RELAY_TLS_HOST="${TURN_RELAY_TLS_HOST:-}" TURN_RELAY_TLS_PORT="${TURN_RELAY_TLS_PORT:-5349}" TLS_BY_PROXY="${TLS_BY_PROXY:-false}" APP_BIND_ADDR="${APP_BIND_ADDR:-127.0.0.1}" @@ -149,6 +153,8 @@ install.sh — установка glchat (AGENT.md 10). клиенты получают его в списке turn_servers --turn-relay-port UDP-порт внешнего релея (по умолчанию 3478) --turn-relay-tls-port TLS-порт внешнего релея (по умолчанию 5349) + --turn-relay-tls-host имя хоста для TURN/TLS (по умолчанию turn.<домен>): + должно совпадать с сертификатом релея --tls-terminated-by-proxy TLS терминирует внешний прокси: свои 80/443 не занимаем, но ссылки в API отдаются как https/wss --app-bind-addr адрес app (по умолчанию 127.0.0.1); для прокси по @@ -215,6 +221,7 @@ parse_args() { --turn-relay-host) TURN_RELAY_HOST="${2:?}"; shift 2 ;; --turn-relay-port) TURN_RELAY_PORT="${2:?}"; shift 2 ;; --turn-relay-tls-port) TURN_RELAY_TLS_PORT="${2:?}"; shift 2 ;; + --turn-relay-tls-host) TURN_RELAY_TLS_HOST="${2:?}"; shift 2 ;; --tls-terminated-by-proxy) TLS_BY_PROXY="true"; shift ;; --app-bind-addr) APP_BIND_ADDR="${2:?}"; shift 2 ;; --allow-port) ALLOW_PORTS="${ALLOW_PORTS} ${2:?}"; shift 2 ;; @@ -326,6 +333,15 @@ resolve_derived_values() { fi TURN_CERT_DIR="${TARGET_DIR}/certs" TURN_RELAY_HOST_RESOLVED="${TURN_RELAY_HOST}" + if [ -z "$TURN_RELAY_TLS_HOST" ] && [ -n "$TURN_RELAY_HOST" ]; then + # TURN/TLS анонсируем по имени с сертификатом, если DNS уже настроен. + if getent hosts "turn.${DOMAIN}" >/dev/null 2>&1; then + TURN_RELAY_TLS_HOST="turn.${DOMAIN}" + else + TURN_RELAY_TLS_HOST="$TURN_RELAY_HOST" + fi + fi + [ -n "$TURN_RELAY_TLS_HOST" ] || TURN_RELAY_TLS_HOST="$TURN_RELAY_HOST" TURN_RELAY_USER="${TURN_RELAY_USER:-glchat}" tun_relay_password_from_env="" if [ -f "$GLCHAT_ENV_FILE" ]; then @@ -378,7 +394,7 @@ resolve_derived_values() { PROFILE_LIVEKIT_DISABLE_SIMULCAST PROFILE_LIVEKIT_USE_EXTERNAL_IP \ GLCHAT_DATA_DIR GLCHAT_CADDY_PROFILE GLCHAT_TURN_CERT_DIR \ GLCHAT_APP_BIND GLCHAT_LIVEKIT_BIND TLS_ENABLED \ - TURN_DOMAIN_RESOLVED TURN_CERT_DIR TURN_RELAY_HOST_RESOLVED \ + TURN_DOMAIN_RESOLVED TURN_CERT_DIR TURN_RELAY_HOST_RESOLVED TURN_RELAY_TLS_HOST \ TURN_RELAY_USER TURN_RELAY_PASSWORD } @@ -741,6 +757,7 @@ TURN_RELAY_HOST=@TURN_RELAY_HOST@ LIVEKIT_PUBLIC_URL=@LIVEKIT_PUBLIC_URL@ TURN_RELAY_PORT=@TURN_RELAY_PORT@ TURN_RELAY_TLS_PORT=@TURN_RELAY_TLS_PORT@ +TURN_RELAY_TLS_HOST=@TURN_RELAY_TLS_HOST@ # --- секреты (генерируются один раз) --- SESSION_PEPPER=@SESSION_PEPPER@ @@ -831,6 +848,7 @@ TURN_RELAY_END=${TURN_RELAY_END} TURN_RELAY_HOST=${TURN_RELAY_HOST_RESOLVED} TURN_RELAY_PORT=${TURN_RELAY_PORT} TURN_RELAY_TLS_PORT=${TURN_RELAY_TLS_PORT} +TURN_RELAY_TLS_HOST=${TURN_RELAY_TLS_HOST} TURN_RELAY_USER=${TURN_RELAY_USER} TURN_RELAY_PASSWORD=${TURN_RELAY_PASSWORD} SESSION_PEPPER=${SESSION_PEPPER} @@ -985,8 +1003,9 @@ render_turn_relay_servers() { printf ' turn_servers:\n' printf ' - host: %s\n port: %s\n protocol: udp\n username: %s\n credential: %s\n' \ "$TURN_RELAY_HOST" "$TURN_RELAY_PORT" "$TURN_RELAY_USER" "$TURN_RELAY_PASSWORD" + # TURN/TLS — по имени хоста: сертификат выписан на домен, не на IP. printf ' - host: %s\n port: %s\n protocol: tls\n username: %s\n credential: %s\n' \ - "$TURN_RELAY_HOST" "$TURN_RELAY_TLS_PORT" "$TURN_RELAY_USER" "$TURN_RELAY_PASSWORD" + "$TURN_RELAY_TLS_HOST" "$TURN_RELAY_TLS_PORT" "$TURN_RELAY_USER" "$TURN_RELAY_PASSWORD" } diff --git a/scripts/test-install.sh b/scripts/test-install.sh index 26b8fd8..9c5e390 100755 --- a/scripts/test-install.sh +++ b/scripts/test-install.sh @@ -71,7 +71,21 @@ secrets_before="$(docker exec "$CONTAINER" bash -lc ' ')" printf '%s\n' "$secrets_before" -run_install "4/5 идемпотентность: повторный запуск с --reconfigure" --reconfigure +# Внешний TURN-релей: в livekit.yaml должны попасть UDP-адрес и TLS-имя хоста +# (сертификат выписан на домен, поэтому TLS-эндпоинт анонсируется именем). +run_install "4/5 идемпотентность: повторный запуск с --reconfigure" --reconfigure \ + --turn-relay-host 203.0.113.10 --turn-relay-tls-host turn.gl.test.local + +log "4b/5 адреса TURN-релея в livekit.yaml" +relay_rendered="$(docker exec "$CONTAINER" bash -lc 'cat /opt/glchat/livekit/livekit.yaml')" +printf '%s\n' "$relay_rendered" | grep -A 3 "turn_servers" | head -12 +for expected in "host: 203.0.113.10" "protocol: udp" "host: turn.gl.test.local" "protocol: tls"; do + if ! printf '%s\n' "$relay_rendered" | grep -q "$expected"; then + echo "ОШИБКА: в livekit.yaml нет строки \"$expected\"" >&2 + exit 1 + fi +done +echo "адреса TURN-релея отрендерены: ok" log "5/5 секреты после повторного запуска" secrets_after="$(docker exec "$CONTAINER" bash -lc '