LiveKit Configuration¶
LiveKit is the WebRTC media server at the heart of La Suite Meet. Every deployment needs a properly configured LiveKit instance.
TLS requirement — important¶
Browsers running on HTTPS pages cannot connect to unencrypted WebSocket endpoints (ws://). They require wss:// (WebSocket over TLS). LiveKit on port 7880 serves plain WebSocket with no TLS.
You must put TLS in front of LiveKit. The recommended way in a Docker Compose deployment is to proxy LiveKit through nginx-proxy on a dedicated subdomain (e.g., livekit.example.com). nginx-proxy terminates TLS and forwards traffic to LiveKit's port 7880 inside Docker.
This means you need three DNS records pointing to your server:
visio.example.com → <server-IP> (Meet frontend + API)
auth.example.com → <server-IP> (Keycloak)
livekit.example.com → <server-IP> (LiveKit WebSocket, TLS-terminated by nginx-proxy)
LiveKit configuration file¶
Create livekit-server.yaml:
port: 7880
rtc:
tcp_port: 7881
udp_port: 7882
use_external_ip: true # required on cloud VMs behind NAT
keys:
meetapikey: your-livekit-api-secret-here # must match LIVEKIT_API_KEY / LIVEKIT_API_SECRET
redis:
address: redis:6379
logging:
level: info
Key settings¶
rtc.use_external_ip: Set to true on any cloud server behind NAT. LiveKit auto-detects and announces its public IP via STUN.
keys: API key → API secret map. Must match LIVEKIT_API_KEY and LIVEKIT_API_SECRET in your .env.
redis: LiveKit uses Redis for distributed room state. Point this to the same Redis instance as Meet.
TURN server (optional but recommended)¶
For participants on restrictive corporate networks where UDP is blocked:
rtc:
turn_servers:
- host: turn.example.com
port: 443
protocol: tls
username: turnuser
credential: turnpassword
Docker Compose service¶
LiveKit is added to both the proxy network (for nginx-proxy TLS termination) and the internal network (for Redis access). Port 7880 is not exposed on the host — it is proxied by nginx-proxy. Ports 7881 and 7882 are still exposed directly for media transport.
livekit:
image: livekit/livekit-server:latest
restart: unless-stopped
command: --config /config.yaml
environment:
- VIRTUAL_HOST=livekit.example.com
- VIRTUAL_PORT=7880
- LETSENCRYPT_HOST=livekit.example.com
- LETSENCRYPT_EMAIL=you@example.com
ports:
- "7881:7881" # TCP media fallback (direct, no TLS needed)
- "7882:7882/udp" # UDP RTP/RTCP media (direct, must stay open)
volumes:
- ./livekit-server.yaml:/config.yaml:ro
depends_on:
- redis
networks:
- proxy
- internal
Meet backend configuration¶
LIVEKIT_API_URL serves dual purpose — it is used by the backend for server-to-server API calls AND returned to browser clients as the WebSocket URL. It must be the public WSS URL:
LIVEKIT_API_KEY=meetapikey
LIVEKIT_API_SECRET=your-livekit-api-secret
LIVEKIT_API_URL=wss://livekit.example.com
The backend resolves livekit.example.com via extra_hosts in the compose file:
Do not use
http://livekit:7880forLIVEKIT_API_URL. That Docker-internal address is returned to browser clients who cannot resolve it.
Firewall requirements¶
| Port | Protocol | Purpose |
|---|---|---|
| 443 | TCP | LiveKit WebSocket via nginx-proxy (already open) |
| 7881 | TCP | LiveKit TCP media fallback |
| 7882 | UDP | LiveKit RTP/RTCP media (critical) |
Port 7880 no longer needs to be open on the host firewall.
Verifying the setup¶
# Check LiveKit is reachable via HTTPS/WSS (after cert is issued)
curl -s -o /dev/null -w "%{http_code}" https://livekit.example.com/
# Expected: 200
# Test with LiveKit CLI
lk room list \
--url wss://livekit.example.com \
--api-key meetapikey \
--api-secret your-secret
LiveKit Egress (for recording)¶
LiveKit Egress is a separate service required for recording. See Advanced: Recording & Transcription.
Production tips¶
- Run LiveKit on a server with sufficient bandwidth — it forwards all media streams
- Monitor LiveKit memory and CPU — each participant track consumes resources
- Keep the LiveKit API secret 32+ characters and treat it like a database password
- The UDP buffer warning (
UDP receive buffer is too small) is informational — setnet.core.rmem_max=5000000on the host for production