Relay Overview
bilbycast-relay is a stateless opaque per-path forwarder for NAT traversal between bilbycast-edge nodes behind NAT, with an optional stateful viewer-distribution role alongside it. As a forwarder it pairs the two ends of each path by tunnel ID and forwards [tunnel_id][ciphertext] verbatim between them. It cannot read tunnel payloads (end-to-end ChaCha20-Poly1305 encryption between edges), and it never terminates or combines the streams it carries. Statelessness is a property of that role: the viewer-distribution role below keeps per-viewer WHEP sessions in memory and an on-disk segment store it re-adopts on restart.
It forwards three logically distinct path types, all the same opaque way:
- QUIC tunnels — TCP streams + UDP datagrams over QUIC / TLS 1.3 (
:4433). - Native SRT / RIST over relay — plain UDP, no QUIC (
:4434), so SRT/RIST keep their own ARQ + congestion control without QUIC’s overhead. - Individual bond legs — a relayed multi-path bond leg is just a native plain-UDP tunnel. Bond aggregation, cross-leg ARQ, FEC, and reordering run end-to-end edge↔edge; the relay forwards each leg opaquely. There is no “bond bridge” — the relay does not terminate or combine bonds.
A relay can also run as a viewer-distribution node — reaching browser viewers directly with a WHEP SFU (sub-second WebRTC) plus an LL-HLS/CMAF origin (CDN-scale), with no external streaming server and no ports opened on the edge. The opaque forwarding described above is unaffected either way.
Default-off describes the build, not the box. The Cargo feature is off by default, so a plain forwarder build carries no distribution surface at all — but the shipped -distribution artefact comes up with the role enabled and listening on :4485 (TCP — browser-facing HTTP signaling + origin) and :4486 (UDP/QUIC ingest), both dual-stack, unless relay.json says "distribution": { "enabled": false }. install-relay.sh installs that variant by default; pass --variant default for the lean forwarder. The same tarball also carries a second binary, bilbycast-portal — the DVR viewer portal — installed only with --with-portal and deliberately left stopped until you issue it a manager service token.
Key Features
Section titled “Key Features”- Zero-config startup — Runs with no config file, self-signed TLS certificate auto-generated
- QUIC/TLS 1.3 — QUIC-tunnel traffic encrypted in transit
- Native-UDP carrier — Plain-UDP data plane (
:4434, on by default) for native SRT/RIST and bond legs over relay; both ends dial out, so a bond can work with both ends behind NAT - End-to-end encryption — ChaCha20-Poly1305 between edges; relay sees only ciphertext
- Optional API auth — Bearer token authentication for REST API
- Optional tunnel auth — Per-tunnel HMAC-SHA256 bind tokens managed via manager
- Manager integration — Optional WebSocket connection for centralized monitoring
- Lock-free design — DashMap registries, AtomicU64 stats, zero Mutex usage
- Viewer distribution (optional) — WHEP SFU + LL-HLS origin to reach browser viewers natively; the Cargo feature is default-off, but the
-distributionrelease variant ships it enabled on:4485/:4486unlessrelay.jsondisables it
Security Layers
Section titled “Security Layers”| Layer | Mechanism |
|---|---|
| Transport | TLS 1.3 via QUIC |
| End-to-end | ChaCha20-Poly1305 between edges |
| REST API | Optional Bearer token |
| Tunnel binding | Optional HMAC-SHA256 bind tokens |
| ALPN | bilbycast-relay protocol enforced |
REST API
Section titled “REST API”| Endpoint | Description |
|---|---|
GET /health |
Health check (always public) |
GET /metrics |
Prometheus metrics |
GET /api/v1/tunnels |
List active QUIC tunnels |
GET /api/v1/udp-sessions |
List active native-UDP relay sessions |
GET /api/v1/edges |
List connected edges |
GET /api/v1/stats |
Bandwidth, throughput, peaks, uptime |
Two administrative teardown routes exist for orphan cleanup when the manager is unavailable: DELETE /api/v1/tunnels/{id} and DELETE /api/v1/udp-sessions/{id}. Both are fail-closed — they return 403 unless api_token is configured.
Quick Start
Section titled “Quick Start”# Zero-config startcargo build --release./target/release/bilbycast-relay
# With config./target/release/bilbycast-relay -c relay.jsonDefault ports: QUIC on 0.0.0.0:4433, the native-UDP relay on 0.0.0.0:4434, REST API on 0.0.0.0:4480. When edges live outside the relay’s host, also set public_quic_addr (and public_udp_addr if you use the native-UDP carrier) in the config — or pass --public-quic-addr / --public-udp-addr — to the hostname or public IP edges will dial. That’s what gets advertised to the manager and pre-populates the tunnel-creation dropdown.
See Architecture for the full design and connection lifecycle.