prosody: offer STUN and TURN #13

Merged
asxpi merged 2 commits from infra/prosody-turn into main 2026-11-09 01:14:14 +00:00
Member

The prosody test server answered XEP-0215 with service-unavailable, so calls between two NATed clients had only host candidates and ICE failed (#9, P2).

  • coturn beside prosody (nix/turn.nix): 3478 udp/tcp, 5349 TLS with the ACME cert, relay udp 49160-49299, no relaying into loopback/private ranges; shared secret created on the host, kept in the restic state, never in git.
  • prosody: mod_turn_external → XEP-0215 lists stun/turn udp+tcp and turns 5349 with 24 h credentials.
  • Deployed and checked: TURN allocations succeed over udp/tcp/tls; an aim ↔ Dino audio call on prosody in the VMs now connects with audio both ways.

Fixes P2 of #9.

🤖 Generated with Claude Code

The prosody test server answered XEP-0215 with service-unavailable, so calls between two NATed clients had only host candidates and ICE failed (#9, P2). - coturn beside prosody (`nix/turn.nix`): 3478 udp/tcp, 5349 TLS with the ACME cert, relay udp 49160-49299, no relaying into loopback/private ranges; shared secret created on the host, kept in the restic state, never in git. - prosody: `mod_turn_external` → XEP-0215 lists stun/turn udp+tcp and turns 5349 with 24 h credentials. - Deployed and checked: TURN allocations succeed over udp/tcp/tls; an aim ↔ Dino audio call on prosody in the VMs now connects with audio both ways. Fixes P2 of #9. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Prosody answered the XEP-0215 query with service-unavailable, so Jingle
calls between two NATed clients had only host candidates and ICE failed
(issue #9). ejabberd has its built-in STUN/TURN (mod_stun_disco);
Prosody needs an external server.

Run coturn on the same host (nix/turn.nix) with time-limited
credentials (use-auth-secret) on 3478 udp/tcp and TLS on 5349 with the
host's ACME certificate, relaying over udp 49160-49299. Relaying into
loopback and private networks is denied. mod_turn_external announces
stun and turn on udp and tcp and turns on 5349.

The shared secret never enters git: turn-secret.service makes it on the
server at first start, after the restic restore, and the state backup
keeps it, so a rebuilt server comes back with the same secret. Prosody
reads it through LoadCredential and Credential(). The interop Hetzner
project has no cloud firewall, so the host firewall is the only one to
open.

Deployed to prosody.asxp.io on 2026-11-09: the extdisco query lists
the five services, and turnutils_uclient allocates and relays through
udp, tcp and tls with the announced credential.

Assisted-by: Claude:opus-5-5
vms: note that prosody calls get STUN/TURN now
All checks were successful
/ check (pull_request) Successful in 4m9s
e83b4a59b7
The pitfall said ICE fails on prosody for lack of STUN/TURN. With
coturn on prosody.asxp.io, an unrecorded calls.py run of aim and Dino
(2026-11-09) gathered srflx and relay candidates on both sides and
connected audio both ways. Its video call connected but aim heard no
audio from Dino, the same failure as on ejabberd.

Assisted-by: Claude:opus-5-5
asxpi merged commit 590bb36d19 into main 2026-11-09 01:14:14 +00:00
asxpi referenced this pull request from a commit 2026-11-09 05:30:17 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
another-im/interop!13
No description provided.