Started as gitea + relay atomic check. The gitea fix surfaced surviving
<domain> placeholders across 8 other component READMEs that prior sweeps
(Pass 29: canonical docs, Pass 32: image registries) hadn't covered.
Catalyst control-plane DNS fixes (-> {component}.<location-code>.<sovereign-domain>):
- gitea: GITEA_INSTANCE_URL.
- external-secrets: openbao ClusterSecretStore + gitea Flux GitRepository.
Application DNS fixes (-> {app}.<env>.<sovereign-domain>):
- temporal: had two drift items in one line — temporal.fuse.<domain>
(old "fuse" product name + wrong placeholder shape). Pass 32 fixed
the image ref on the same file but missed this. Now fully de-drifted.
- valkey: --replicaof valkey.region1.<domain> (non-canonical region1
segment — Catalyst encodes regions in location-code).
- strimzi: kafka-kafka-bootstrap.region1.<domain>:9092 — same.
- cnpg: postgres.region1.<domain> cross-region replica host — same.
- stunner: STUN/TURN realm — kept canonical Application form for
consistency even though STUN realms are nominally opaque.
- k8gb: Gslb ingress host app.gslb.<domain> -> app.gslb.<sovereign-domain>.
Other illustrative k8gb refs (dnsZone, nslookup examples) preserved
as they describe behavior generically.
products/relay/README.md: clean.
Preserved as correctly-generic: external-dns illustrative refs,
cert-manager <domain> (customer-supplied cert names), stalwart <domain>
(customer email-receiving domain).
Validation log Pass 35 entry: third end-to-end DNS sweep iteration
(29 -> 32 -> 35). Future passes should grep for bare <domain> early to
catch new instances introduced during edits.
|
||
|---|---|---|
| .. | ||
| README.md | ||
STUNner
K8s-native TURN/STUN for WebRTC NAT traversal. Application Blueprint (see docs/PLATFORM-TECH-STACK.md §4.5 — Communication). Used by bp-relay to make LiveKit (WebRTC SFU) reachable from clients behind NATs.
Status: Accepted | Updated: 2026-04-27
Overview
STUNner provides WebRTC connectivity:
- Kubernetes-native STUN/TURN server
- Gateway API integration
- Scalable media relay
- NAT traversal for video/audio
Architecture
flowchart TB
subgraph External["External"]
Client[WebRTC Client]
end
subgraph K8s["Kubernetes"]
subgraph STUNner["STUNner"]
GW[Gateway]
TURN[TURN Servers]
end
subgraph Apps["Applications"]
SFU[Media Server/SFU]
end
end
Client -->|"STUN/TURN"| GW
GW --> TURN
TURN --> SFU
Client -->|"Media"| TURN
TURN -->|"Media"| SFU
Why STUNner
| Factor | STUNner | Traditional TURN |
|---|---|---|
| Deployment | Kubernetes-native | Separate VMs |
| Scaling | HPA/KEDA | Manual |
| Configuration | Gateway API CRDs | Config files |
| Integration | Native K8s | External |
Configuration
Gateway
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: stunner-gateway
namespace: stunner
spec:
gatewayClassName: stunner-gatewayclass
listeners:
- name: udp-listener
port: 3478
protocol: TURN-UDP
- name: tcp-listener
port: 3478
protocol: TURN-TCP
UDPRoute
apiVersion: stunner.l7mp.io/v1
kind: UDPRoute
metadata:
name: media-route
namespace: stunner
spec:
parentRefs:
- name: stunner-gateway
rules:
- backendRefs:
- name: media-server
namespace: apps
GatewayConfig
apiVersion: stunner.l7mp.io/v1
kind: GatewayConfig
metadata:
name: stunner-config
namespace: stunner
spec:
realm: stunner.<env>.<sovereign-domain>
authType: longterm
userName: stunner
password:
name: stunner-credentials
namespace: stunner
key: password
TURN Authentication
STUNner supports long-term credentials:
# Generate time-limited credentials
apiVersion: stunner.l7mp.io/v1
kind: GatewayConfig
spec:
authType: longterm
authLifetime: 86400 # 24 hours
Scaling
STUNner scales with KEDA based on connection count:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: stunner-scaler
namespace: stunner
spec:
scaleTargetRef:
name: stunner
minReplicaCount: 2
maxReplicaCount: 10
triggers:
- type: prometheus
metadata:
serverAddress: http://mimir.monitoring.svc:8080/prometheus
metricName: stunner_allocations_active
query: sum(stunner_allocations_active)
threshold: "100"
Monitoring
| Metric | Description |
|---|---|
stunner_allocations_active |
Active TURN allocations |
stunner_bytes_received_total |
Received bytes |
stunner_bytes_sent_total |
Sent bytes |
stunner_connections_total |
Total connections |
Part of OpenOva