5.4 KiB
5.4 KiB
MatrixRTC / LiveKit — Element X Calls
Last updated: 2026-03-19
MatrixRTC enables voice/video calls in Element X using a LiveKit SFU backend. Both homeservers (mx.vish.gg and matrix.thevish.io) share the same LiveKit SFU on matrix-ubuntu.
Service Overview
| Property | Value |
|---|---|
| Host | matrix-ubuntu (192.168.0.154) |
| Matrix homeservers | mx.vish.gg (synapse-mx.service) and matrix.thevish.io (synapse.service) — both on Synapse 1.148.0 |
| Compose file | hosts/vms/matrix-ubuntu/livekit.yml (deployed manually at /opt/livekit/) |
| LiveKit version | 1.9.12 |
| JWT service | ghcr.io/element-hq/lk-jwt-service:latest-ci |
Architecture
Element X ──→ mx.vish.gg (.well-known) ──→ livekit.mx.vish.gg/livekit/jwt (JWT service)
──→ matrix.thevish.io (.well-known) ──→ livekit.mx.vish.gg/livekit/sfu (LiveKit SFU)
livekit.mx.vish.gg/ (LiveKit WS)
Both homeservers share the same LiveKit backend.
- NPM on Calypso proxies
livekit.mx.vish.gg→ matrix-ubuntu/livekit/jwt/→ JWT service port 8089 (container 8080)/livekit/sfu/→ LiveKit SFU port 7880/→ LiveKit SFU port 7880 (WebSocket for direct connections)
- DNS:
livekit.mx.vish.ggA record unproxied →184.23.52.14(home WAN) - TLS: Let's Encrypt cert issued via Cloudflare DNS challenge on matrix-ubuntu, copied to NPM as
npm-7
Endpoints
| Endpoint | URL | Purpose |
|---|---|---|
| JWT service healthz | https://livekit.mx.vish.gg/livekit/jwt/healthz |
Health check |
| JWT service SFU get | https://livekit.mx.vish.gg/livekit/jwt/sfu/get |
Token exchange |
| LiveKit SFU WS | wss://livekit.mx.vish.gg/livekit/sfu/ |
WebSocket signalling |
| LiveKit HTTP | https://livekit.mx.vish.gg/ |
SFU API |
| .well-known | https://mx.vish.gg/.well-known/matrix/client |
RTC foci advertisement |
Configuration Files on matrix-ubuntu
| File | Purpose |
|---|---|
/opt/livekit/docker-compose.yml |
LiveKit + JWT service deployment |
/opt/livekit/livekit.yaml |
LiveKit SFU config (keys, RTC ports, external IP) |
/opt/synapse-mx/homeserver.yaml |
Synapse config (MSCs, rate limits) |
/etc/nginx/sites-available/mx-vish-gg |
nginx serving .well-known and Element static files |
/etc/letsencrypt/live/livekit.mx.vish.gg/ |
TLS cert (auto-renews, copies to NPM via deploy hook) |
Synapse homeserver.yaml additions
# MatrixRTC / Element Call support
experimental_features:
msc3266_enabled: true # Room Summary API (knocking over federation)
msc4222_enabled: true # state_after in sync v2
msc4140_enabled: true # Delayed events (call participation signalling)
max_event_delay_duration: 24h
rc_message:
per_second: 0.5
burst_count: 30
rc_delayed_event_mgmt:
per_second: 1
burst_count: 20
.well-known/matrix/client
Served by nginx at https://mx.vish.gg/.well-known/matrix/client:
{
"m.homeserver": {"base_url": "https://mx.vish.gg"},
"org.matrix.msc4143.rtc_foci": [
{
"type": "livekit",
"livekit_service_url": "https://livekit.mx.vish.gg/livekit/jwt"
}
]
}
LiveKit SFU config (/opt/livekit/livekit.yaml)
Key settings:
use_external_ip: true— auto-detects WAN IP184.23.52.14use_ice_lite: true— optimised for server-side NAT traversalroom.auto_create: false— only lk-jwt-service creates rooms (security)- RTC ports: 7880 TCP (API/WS), 7881 TCP (RTC), 50000-60000 UDP (media)
- Note: UDP 50000-60000 port range is NOT currently forwarded on the router — TURN relay is used instead via coturn at
turn:mx.vish.gg:3479
TLS Certificate Renewal
Cert is issued on matrix-ubuntu via certbot + Cloudflare DNS plugin. A deploy hook copies it to NPM on Calypso after renewal:
/etc/letsencrypt/renewal-hooks/deploy/copy-to-npm.sh
If the hook fails, manually copy:
ssh matrix-ubuntu
sudo cp /etc/letsencrypt/live/livekit.mx.vish.gg/fullchain.pem \
/tmp/lk.crt
sudo cp /etc/letsencrypt/live/livekit.mx.vish.gg/privkey.pem \
/tmp/lk.key
scp -P 62000 /tmp/lk.crt Vish@100.103.48.78:/volume1/docker/nginx-proxy-manager/data/custom_ssl/npm-7/fullchain.pem
scp -P 62000 /tmp/lk.key Vish@100.103.48.78:/volume1/docker/nginx-proxy-manager/data/custom_ssl/npm-7/privkey.pem
ssh -p 62000 Vish@100.103.48.78 'sudo /usr/local/bin/docker exec nginx-proxy-manager nginx -s reload'
Troubleshooting
Calls not working in Element X
- Check
.well-knownis advertising foci:curl https://mx.vish.gg/.well-known/matrix/client - Check JWT service:
curl https://livekit.mx.vish.gg/livekit/jwt/healthz - Check LiveKit is running:
ssh matrix-ubuntu "sudo docker ps | grep livekit" - Check LiveKit logs:
ssh matrix-ubuntu "sudo docker logs livekit 2>&1 | tail -20"
Stuck calls
See How to resolve stuck MatrixRTC calls — usually caused by delayed events not cleaning up.
JWT service returns 400
Normal for unauthenticated requests. Means the service is running correctly.
Restarting services
ssh matrix-ubuntu
cd /opt/livekit
sudo docker compose restart
Restarting Synapse
ssh matrix-ubuntu
sudo systemctl restart synapse-mx.service