From e8e063e52d95261147356d506e6fb3e74eec7c12 Mon Sep 17 00:00:00 2001 From: grendervill Date: Sat, 19 Sep 2026 20:28:03 +0300 Subject: [PATCH] =?UTF-8?q?feat(turn):=20=D0=B2=D0=BD=D0=B5=D1=88=D0=BD?= =?UTF-8?q?=D0=B8=D0=B9=20TURN-=D1=80=D0=B5=D0=BB=D0=B5=D0=B9=20=D0=B8=20T?= =?UTF-8?q?LS=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20=D0=BF=D1=80=D0=BE=D0=BA?= =?UTF-8?q?=D1=81=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - install.sh: --tls-terminated-by-proxy (ссылки https/wss без своего 80/443), --turn-relay-host/--turn-relay-port/--turn-relay-tls-port, общий TURN_SECRET для coturn (use-auth-secret) и LiveKit - livekit.yaml.tpl: rtc.turn_servers с внешним релеем (udp + tls) - секрет вычисляется один раз и сохраняется в .env --- deploy/install.sh | 59 +++++++++++++++++++++++++++++++-- deploy/livekit/livekit.yaml.tpl | 3 ++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/deploy/install.sh b/deploy/install.sh index 3d27542..0b42041 100755 --- a/deploy/install.sh +++ b/deploy/install.sh @@ -57,6 +57,10 @@ TURN_RELAY_START="${TURN_RELAY_START:-30000}" TURN_RELAY_END="${TURN_RELAY_END:-40000}" 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_RELAY_TLS_PORT="${TURN_RELAY_TLS_PORT:-5349}" +TLS_BY_PROXY="${TLS_BY_PROXY:-false}" TURN_TLS_PORT="${TURN_TLS_PORT:-5349}" PROXY_MODE="${PROXY_MODE:-embedded}" PROFILE="${PROFILE:-auto}" @@ -116,6 +120,12 @@ install.sh — установка glchat (AGENT.md 10). --turn-domain домен TURN/TLS (по умолчанию turn.) --turn-cert <файл> сертификат для TURN/TLS (нужен при включённом TURN) --turn-key <файл> приватный ключ сертификата TURN/TLS + --turn-relay-host внешний TURN-релей с публичным IP (например, VPS): + клиенты получают его в списке turn_servers + --turn-relay-port UDP-порт внешнего релея (по умолчанию 3478) + --turn-relay-tls-port TLS-порт внешнего релея (по умолчанию 5349) + --tls-terminated-by-proxy TLS терминирует внешний прокси: свои 80/443 не занимаем, + но ссылки в API отдаются как https/wss --turn-tls TURN TLS (по умолчанию 5349) --external-proxy не занимать 80/443: отдать маршруты внешнему прокси (AGENT.md 10.13) --no-files-subdomain не использовать files. (fallback /files/*) @@ -163,6 +173,10 @@ parse_args() { --turn-domain) TURN_DOMAIN_OVERRIDE="${2:?}"; shift 2 ;; --turn-cert) TURN_CERT_SRC="${2:?}"; shift 2 ;; --turn-key) TURN_CERT_SRC_KEY="${2:?}"; shift 2 ;; + --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 ;; + --tls-terminated-by-proxy) TLS_BY_PROXY="true"; shift ;; --turn-tls) TURN_TLS_PORT="${2:?}"; shift 2 ;; --profile) PROFILE="${2:?}"; shift 2 ;; --max-upload) MAX_UPLOAD_MB="${2:?}"; shift 2 ;; @@ -255,6 +269,8 @@ resolve_derived_values() { TURN_DOMAIN_RESOLVED="${TURN_DOMAIN_OVERRIDE:-turn.${DOMAIN}}" TURN_CERT_DIR="${TARGET_DIR}/certs" + TURN_RELAY_HOST_RESOLVED="${TURN_RELAY_HOST}" + turn_shared_secret >/dev/null disable_simulcast="true" if [ "${PROFILE_LIVEKIT_SIMULCAST:-0}" -gt 0 ] 2>/dev/null; then @@ -281,7 +297,7 @@ resolve_derived_values() { livekit_extra_codecs \ PROFILE_LIVEKIT_DISABLE_SIMULCAST PROFILE_LIVEKIT_USE_EXTERNAL_IP \ GLCHAT_DATA_DIR GLCHAT_CADDY_PROFILE GLCHAT_TURN_CERT_DIR \ - TURN_DOMAIN_RESOLVED TURN_CERT_DIR + TURN_DOMAIN_RESOLVED TURN_CERT_DIR TURN_RELAY_HOST_RESOLVED TURN_SECRET_RESOLVED } validate_inputs() { @@ -518,13 +534,24 @@ CADDY_IMAGE_TAG=${CADDY_IMAGE_TAG} LIVEKIT_IMAGE_TAG=${LIVEKIT_IMAGE_TAG} # --- TLS --- -TLS_ENABLED=$([ "$SKIP_TLS" = "1" ] && echo false || echo true) +# TLS считается включённым и когда сертификаты обслуживает внешний прокси +# (--external-proxy --tls-terminated-by-proxy): клиентские ссылки должны быть https/wss. +if [ "$SKIP_TLS" = "1" ] && [ "$TLS_BY_PROXY" != "true" ]; then + TLS_ENABLED=false +else + TLS_ENABLED=true +fi SKIP_TLS=${SKIP_TLS} +TLS_BY_PROXY=${TLS_BY_PROXY} # --- интерполяция compose (пути и профиль) --- GLCHAT_DATA_DIR=${GLCHAT_DATA_DIR} GLCHAT_CADDY_PROFILE=${CADDY_PROFILE} GLCHAT_TURN_CERT_DIR=${GLCHAT_TURN_CERT_DIR} +TURN_RELAY_HOST=${TURN_RELAY_HOST_RESOLVED} +TURN_RELAY_PORT=${TURN_RELAY_PORT} +TURN_RELAY_TLS_PORT=${TURN_RELAY_TLS_PORT} +TURN_SECRET=${TURN_SECRET_RESOLVED} # --- порты --- APP_PORT=${APP_PORT} @@ -666,6 +693,33 @@ ensure_swap() { +# render_turn_relay_servers формирует YAML-список turn_servers для LiveKit: +# UDP и TLS-эндпоинты внешнего релея (VPS), у которого есть публичный IP. +# Секрет уже вычислен в resolve_derived_values (TURN_SECRET_RESOLVED). +render_turn_relay_servers() { + [ -n "$TURN_RELAY_HOST" ] || return 0 + printf ' turn_servers:\n' + printf ' - host: %s\n port: %s\n protocol: udp\n secret: %s\n' \ + "$TURN_RELAY_HOST" "$TURN_RELAY_PORT" "$TURN_SECRET_RESOLVED" + printf ' - host: %s\n port: %s\n protocol: tls\n secret: %s\n' \ + "$TURN_RELAY_HOST" "$TURN_RELAY_TLS_PORT" "$TURN_SECRET_RESOLVED" +} + +# turn_shared_secret — общий секрет для coturn (use-auth-secret) и LiveKit. +# При --reconfigure сохраняется из существующего .env, иначе генерируется. +turn_shared_secret() { + if [ -n "${TURN_SECRET_RESOLVED:-}" ]; then + printf '%s' "$TURN_SECRET_RESOLVED" + return + fi + if [ -f "$GLCHAT_ENV_FILE" ]; then + TURN_SECRET_RESOLVED="$(env_get TURN_SECRET || true)" + fi + [ -n "${TURN_SECRET_RESOLVED:-}" ] || TURN_SECRET_RESOLVED="$(rand_hex 32)" + export TURN_SECRET_RESOLVED + printf '%s' "$TURN_SECRET_RESOLVED" +} + # install_turn_certificate копирует сертификат TURN/TLS туда, где его читает # контейнер LiveKit. Продление выполняет glchat-cert-refresh.timer. install_turn_certificate() { @@ -746,6 +800,7 @@ render_all_templates() { "TURN_RELAY_END=${TURN_RELAY_END}" \ "TURN_CERT_FILE=$([ "$TURN_ENABLED" = "true" ] && echo /etc/certs/turn.crt || echo '')" \ "TURN_KEY_FILE=$([ "$TURN_ENABLED" = "true" ] && echo /etc/certs/turn.key || echo '')" \ + "TURN_RELAY_SERVERS=$(render_turn_relay_servers)" \ "TURN_UDP_PORT=${TURN_UDP_PORT}" \ "TURN_TLS_PORT=${TURN_TLS_PORT}" \ "TURN_EXTERNAL_TLS=${turn_external_tls}" \ diff --git a/deploy/livekit/livekit.yaml.tpl b/deploy/livekit/livekit.yaml.tpl index 7b5a07f..7779712 100644 --- a/deploy/livekit/livekit.yaml.tpl +++ b/deploy/livekit/livekit.yaml.tpl @@ -11,6 +11,9 @@ rtc: use_external_ip: ${LIVEKIT_USE_EXTERNAL_IP} # TCP-fallback, когда UDP заблокирован сетью клиента (AGENT.md 7.14). allow_tcp_fallback: true + # Внешний TURN-релей с публичным IP (VPS): даёт рабочий путь клиентам за + # NAT/CGNAT, когда у самого инстанса белого адреса нет. +${TURN_RELAY_SERVERS} keys: {}