Why
Browser peers connect peer-to-peer over WebRTC. The relay only carries the signalling. To find a direct path, each browser needs a STUN server to learn its public (server-reflexive) address.
Today nothing is configured, so @libp2p/webrtc falls back to its built-in public list: Google, Twilio, Cloudflare and Mozilla. That is fine for development and tests, and tests may keep using public servers (for example from this public STUN list; comments there report that individual entries go stale). A deployment should not depend on third-party STUN, so this is a planned installation of our own at stun.httpeers.net.
Scope
- Server: a STUN server container (for example upstream
coturn/coturn, STUN-only for now) added to deploy/docker-compose.yml.
- Unlike every other service in the stack, it must bind host ports directly: UDP 3478, plus TCP 3478. Caddy proxies no UDP, so it cannot front it.
- TLS (
stuns: on 5349) is optional and can come later.
- DNS: the zone's wildcard A record should already resolve
stun.httpeers.net; confirm this, or add an explicit record.
- Firewall: open 3478/udp and 3478/tcp on the host.
- Clients: add
stun:stun.httpeers.net:3478 to webRTC({ rtcConfiguration }) in the browser and hub node profiles (statewalker-sandbox: apps/httpeers-stack/src/browser/node-profile.ts, src/hub/node-profile.ts). Keep one public server as a fallback.
- Docs: add the service to
deploy/README.md and to the server runbook, including how to check it is alive.
Acceptance
Related, deliberately out of scope: TURN
The agreed direction is that no application traffic ever crosses the relay or a hub node. When a direct WebRTC connection cannot be made (symmetric NAT, some mobile carriers), ICE must fall back to a TURN server. The same coturn install can provide TURN later, but TURN needs its own decisions, so it gets a separate issue:
- Short-lived credentials. Pages are public, so credentials must be time-limited (coturn
use-auth-secret, the "TURN REST API" scheme). @libp2p/webrtc accepts rtcConfiguration as an async function evaluated on every dial, so pages can fetch fresh credentials just before each connection.
- Who mints them? A hub running in a browser tab cannot hold the secret. The likely answer is a small credential service beside the relay, kept separate from the relay so the relay stays free of application code.
- Who may have one? An open TURN server is a free bandwidth proxy.
- The relay's limits. Once TURN is live, they can go back down from 1 GiB / 6 h to signalling-sized values (
apps/relay/src/limits.ts), because the relayed circuit stops being a data path.
Why
Browser peers connect peer-to-peer over WebRTC. The relay only carries the signalling. To find a direct path, each browser needs a STUN server to learn its public (server-reflexive) address.
Today nothing is configured, so
@libp2p/webrtcfalls back to its built-in public list: Google, Twilio, Cloudflare and Mozilla. That is fine for development and tests, and tests may keep using public servers (for example from this public STUN list; comments there report that individual entries go stale). A deployment should not depend on third-party STUN, so this is a planned installation of our own atstun.httpeers.net.Scope
coturn/coturn, STUN-only for now) added todeploy/docker-compose.yml.stuns:on 5349) is optional and can come later.stun.httpeers.net; confirm this, or add an explicit record.stun:stun.httpeers.net:3478towebRTC({ rtcConfiguration })in the browser and hub node profiles (statewalker-sandbox:apps/httpeers-stack/src/browser/node-profile.ts,src/hub/node-profile.ts). Keep one public server as a fallback.deploy/README.mdand to the server runbook, including how to check it is alive.Acceptance
stun.httpeers.net:3478over UDP returns the caller's public address (for example withturnutils_stunclient stun.httpeers.net).RTCPeerConnectionwith onlystun:stun.httpeers.net:3478gathers asrflxcandidate.stun.httpeers.netin their ICE servers.Related, deliberately out of scope: TURN
The agreed direction is that no application traffic ever crosses the relay or a hub node. When a direct WebRTC connection cannot be made (symmetric NAT, some mobile carriers), ICE must fall back to a TURN server. The same coturn install can provide TURN later, but TURN needs its own decisions, so it gets a separate issue:
use-auth-secret, the "TURN REST API" scheme).@libp2p/webrtcacceptsrtcConfigurationas an async function evaluated on every dial, so pages can fetch fresh credentials just before each connection.apps/relay/src/limits.ts), because the relayed circuit stops being a data path.