Retire the shared coturn service — every WebRTC/SIP service now runs its own
Shared coturn (services/coturn.sh, ensure_coturn_user in lib/common.sh) is no longer an installable or usable option anywhere in this repo. It's moved to attic/coturn.sh (with tools/coturn-test-check.sh alongside it), which is outside setup.sh's services/*.sh glob, so it never registers, never appears in the menu, and `sudo ./setup.sh coturn` now fails with "unknown service". Asterisk and Mattermost each already had an opt-out to run their own dedicated coturn instead of the shared one; that opt-out is now the only behavior — the shared-coturn preference, the opt-out prompt, and every ensure_coturn_user() call site are gone. find_free_coturn_range() (lib/common.sh) is what makes unconditional dedicated coturn safe: it scans every coturn-owning service's own .env on the box for already-claimed relay ranges and picks one that can't collide, so Asterisk + any number of Mattermost instances can each run their own coturn on one box without the relay-port collisions this repo's coturn history warns about. Existing installs still pointed at a shared coturn container are left running as-is on `update` (no silent migration attempt against a service that no longer exists to heal against) — a full/fresh reinstall is the migration path, which generates a new dedicated coturn with fresh credentials and says so. Also updates CLAUDE.md's coturn guidance for future service authors, attic/README.md with the retirement rationale, and stale services/coturn.sh path references in services/asterisk.sh, tools/pstn-test-check.sh, README.md, and docs/vps-sizing-recommendations.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Crt4ymNEHEbWqscB1qvZgC
This commit is contained in:
-116
@@ -1038,119 +1038,3 @@ CADDY_BLOCK
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ── Shared coturn (TURN/STUN) wiring ──────────────────────────────────────────
|
||||
# Usage: ensure_coturn_user "<consumer-name>"
|
||||
#
|
||||
# Installs the shared coturn service (services/coturn.sh) if this is the
|
||||
# first service on the box that needs TURN, then registers (or reuses) a
|
||||
# dedicated long-term-credential user for the caller — one coturn instance,
|
||||
# one relay port range, shared by every consumer instead of each service
|
||||
# running its own and fighting over host ports (see services/coturn.sh's
|
||||
# header for why that used to be a real, confirmed-live problem).
|
||||
#
|
||||
# Out-params (not `local` — read them after the call returns), same
|
||||
# convention as configure_caddy_for_service's CADDY_SERVICE_* above:
|
||||
# COTURN_HOST host/IP TURN clients should connect to
|
||||
# COTURN_PORT coturn's listening port
|
||||
# COTURN_USERNAME this consumer's long-term-credential username
|
||||
# COTURN_PASSWORD this consumer's long-term-credential password
|
||||
# COTURN_HOST is left empty if coturn couldn't be installed or reached —
|
||||
# callers should treat that as "no TURN available" and degrade gracefully,
|
||||
# same as checking CADDY_SERVICE_CONFIGURED after configure_caddy_for_service.
|
||||
#
|
||||
# Credentials are cached per-consumer in coturn's own users/<name>.env so a
|
||||
# service re-running its own installer reuses the same one instead of
|
||||
# minting a new credential and orphaning the old one (which would silently
|
||||
# break already-configured clients still holding it).
|
||||
ensure_coturn_user() {
|
||||
local _consumer="$1"
|
||||
COTURN_HOST="" COTURN_PORT="" COTURN_USERNAME="" COTURN_PASSWORD=""
|
||||
|
||||
if [ ! -d "$DOCKER_DIR/coturn" ]; then
|
||||
if declare -F install_coturn >/dev/null 2>&1; then
|
||||
log_info "No shared coturn (TURN/STUN) server yet — setting one up for $_consumer..."
|
||||
# install_coturn cd's into $DOCKER_DIR/coturn and never cd's back —
|
||||
# the caller (e.g. asterisk.sh, already cd'd into its own install
|
||||
# directory) would otherwise return here with the wrong cwd and go
|
||||
# on to write ITS docker-compose.yml/.env into coturn's directory
|
||||
# instead of its own. Confirmed live: this clobbered coturn's
|
||||
# compose file and left the consumer's own directory without one,
|
||||
# so its later `docker compose up --build` failed with "Dockerfile:
|
||||
# no such file or directory" (no Dockerfile in coturn's directory).
|
||||
local _caller_pwd
|
||||
_caller_pwd="$(pwd)"
|
||||
install_coturn
|
||||
local _coturn_rc=$?
|
||||
cd "$_caller_pwd" || true
|
||||
[ "$_coturn_rc" -ne 0 ] && { log_warning "coturn setup failed — $_consumer will run without TURN."; return 1; }
|
||||
else
|
||||
log_warning "services/coturn.sh not loaded — $_consumer will run without TURN."
|
||||
log_warning "Run: sudo ./setup.sh coturn"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$DRY_RUN" = true ]; then
|
||||
echo "[DRY-RUN] Would register coturn user '$_consumer'"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local _env="$DOCKER_DIR/coturn/.env"
|
||||
[ -f "$_env" ] || { log_warning "coturn installed but $_env missing — cannot register '$_consumer'."; return 1; }
|
||||
local _realm _host _port
|
||||
_realm="$(grep '^COTURN_REALM=' "$_env" | cut -d= -f2-)"
|
||||
_host="$(grep '^COTURN_HOST=' "$_env" | cut -d= -f2-)"
|
||||
_port="$(grep '^COTURN_PORT=' "$_env" | cut -d= -f2-)"; _port="${_port:-3478}"
|
||||
|
||||
local _userdir="$DOCKER_DIR/coturn/users"
|
||||
local _userfile="$_userdir/${_consumer}.env"
|
||||
mkdir -p "$_userdir"
|
||||
|
||||
if [ -f "$_userfile" ]; then
|
||||
local _u _p
|
||||
_u="$(grep '^COTURN_USER=' "$_userfile" | cut -d= -f2-)"
|
||||
_p="$(grep '^COTURN_PASS=' "$_userfile" | cut -d= -f2-)"
|
||||
COTURN_USERNAME="$_u" COTURN_PASSWORD="$_p"
|
||||
|
||||
# The cache file surviving doesn't mean the username still exists in
|
||||
# coturn's own live database — confirmed live: a coturn
|
||||
# container/volume recreated without preserving ./db wipes the
|
||||
# database while this file (a separate directory) survives
|
||||
# untouched, silently orphaning every consumer's credentials until
|
||||
# something re-registers them. Without this check, re-running the
|
||||
# consumer's installer (fresh or update) never re-registers anything
|
||||
# since it only ever hits the else branch below on a MISSING cache
|
||||
# file — a stale-but-present one looked identical to a healthy one.
|
||||
# A real "user[realm]" line never contains a space; turnadmin -l's
|
||||
# own startup log lines do (confirmed live, at least one coturn
|
||||
# build writes them to stdout, not stderr), so filtering on that
|
||||
# keeps this robust across builds without needing to match a
|
||||
# specific log format.
|
||||
local _db_users
|
||||
_db_users="$(docker exec coturn turnadmin -l -b /var/lib/coturn/turndb 2>/dev/null | grep -v ' ' | sed -E 's/\[.*//' | awk 'NF')"
|
||||
if ! grep -qx "$_u" <<< "$_db_users"; then
|
||||
log_warning "coturn user '$_u' ($_consumer) has cached credentials but isn't in coturn's live database — re-registering with the same password."
|
||||
if docker exec coturn turnadmin -a -u "$_u" -p "$_p" -r "$_realm" -b /var/lib/coturn/turndb >/dev/null 2>&1; then
|
||||
log_success "Re-registered coturn user '$_u' for $_consumer"
|
||||
else
|
||||
log_warning "Could not re-register coturn user '$_u' for $_consumer — is the coturn container running?"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
COTURN_USERNAME="$_consumer"
|
||||
COTURN_PASSWORD="$(generate_password 24)"
|
||||
if docker exec coturn turnadmin -a -u "$COTURN_USERNAME" -p "$COTURN_PASSWORD" \
|
||||
-r "$_realm" -b /var/lib/coturn/turndb >/dev/null 2>&1; then
|
||||
{ echo "COTURN_USER=$COTURN_USERNAME"; echo "COTURN_PASS=$COTURN_PASSWORD"; } > "$_userfile"
|
||||
chmod 600 "$_userfile"
|
||||
log_success "Registered coturn user '$COTURN_USERNAME' for $_consumer"
|
||||
else
|
||||
log_warning "Could not register a coturn user for $_consumer — is the coturn container running?"
|
||||
COTURN_USERNAME="" COTURN_PASSWORD=""
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
COTURN_HOST="$_host"
|
||||
COTURN_PORT="$_port"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user