Commit Graph
8 Commits
Author SHA1 Message Date
mats 0b2c5ca4c9 pwa
Build and Publish / Metadata (push) Successful in 1s
Build and Publish / BuildAndDeployAmd64 (push) Successful in 37s
2026-09-22 13:55:06 +02:00
matsandClaude Sonnet 5 78d97ee733 Add a second, LAN-only TURN relay to avoid hairpin NAT entirely
Build and Publish / Metadata (push) Successful in 1s
Build and Publish / BuildAndDeployAmd64 (push) Successful in 25s
The existing coturn instance advertises the router's public IP as its
relay address (external-ip=94.255.139.35) — correct for real external
users, but when both peers are on the same home network as the router,
relay traffic has to hairpin through the router's own WAN IP. That only
worked with hwnat (hardware NAT offload) disabled, which pegged the
router's CPU at 93% for well under half its rated throughput — not an
acceptable trade for the whole household's network.

Instead of touching hwnat, added a second coturn deployment
(coturn-lan, own secret, own relay port range 49210-49220) exposed via
its own MetalLB LoadBalancer IP (10.10.3.46) on the same LAN segment.
That address is answered directly via L2 ARP — no NAT, no hairpin,
hwnat never touches it — and it's deliberately not port-forwarded from
WAN, so it's LAN-only by construction.

iceConfig() now appends this as an extra iceServers entry whenever
TURN_LAN_HOST/TURN_LAN_SECRET are set. It's harmless for anyone not on
that network — the address is simply unreachable and ICE ignores it —
and WebRTC tries every configured server, using whichever candidates
actually connect.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 13:13:25 +02:00
matsandClaude Sonnet 5 3517bdf52b fix(webrtc): rebuild the RTCPeerConnection on failure instead of restartIce()
"restarting ICE" on a connection that has reached 'failed' only restarts
ICE gathering — it reuses the same DTLS transport and certificate. If
that transport is what's actually broken, the next renegotiation throws
"Failed to set SSL role for the transport" (DTLS role can't be flipped
on an established transport), which is exactly what showed up in the
console on a LAN test, ruling out NAT/TURN as the cause.

Fix: on 'failed', fully close and recreate the RTCPeerConnection (fresh
certificate, nothing to conflict with) via recreatePeerConnection().
Since ICE/DTLS failure isn't guaranteed to fire on both ends at once,
the side that notices sends a new 'reset' signal (relayed by the
server like offer/answer/candidate) telling the other side to tear
down and wait for a fresh offer too — otherwise its old, now-mismatched
transport would just fail the same way against our new one. Capped at
3 rebuild attempts per peer before giving up with a toast, reset on any
successful 'connected' state.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 12:08:07 +02:00
matsandClaude Sonnet 5 664417c6da fix(server): raise keepAliveTimeout above ingress-nginx's upstream idle timeout
Build and Publish / Metadata (push) Successful in 1s
Build and Publish / BuildAndDeployAmd64 (push) Successful in 1m2s
Node's default keepAliveTimeout (5s) is shorter than ingress-nginx's
default upstream keepalive idle timeout (60s). Under that mismatch,
nginx can forward a request onto a pooled connection Node has *just*
closed, which the browser sees as a 502 — and it never shows up in
this process's own traces because Node never received the request.
/api/rooms is polled every 5s from idle clients, landing almost
exactly on that 5s boundary, which is why it was the one showing up
for external users.

Also add abort/slow-request logging (tagged with the active trace ID
so it can be pivoted to from RUM) and a clientError handler, so a
genuine backend-side failure is now visible instead of indistinguishable
from the proxy-side race.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 11:21:52 +02:00
mats dee8ef4f7c Show users in voice channels before joining
Build and Publish / Metadata (push) Successful in 1s
Build and Publish / BuildAndDeployAmd64 (push) Successful in 24s
2026-09-22 10:45:08 +02:00
mats b6cc9f3465 feat(build): bundle frontend with vite and matrix-js-sdk, fix HOST in server.js
Build and Publish / Metadata (push) Successful in 1s
Build and Publish / BuildAndDeployAmd64 (push) Successful in 22s
2026-09-22 10:29:03 +02:00
mats a2be7cf6a5 feat(ui): move users to channel list with hover volume popup, dedicate main stage to screenshares, add ws ping
Build and Publish / Metadata (push) Successful in 1s
Build and Publish / BuildAndDeployAmd64 (push) Successful in 17s
2026-09-22 10:02:03 +02:00
mats 5757156843 feat: migrate voice app, add otel/rum, dockerfile, k8s deployment with ingress
Build and Publish / Metadata (push) Successful in 1s
Build and Publish / BuildAndDeployAmd64 (push) Successful in 18s
2026-09-22 09:43:47 +02:00