Examples for how to set up continuwuity in docker.
This commit is contained in:
238
continuwuity/README.md
Normal file
238
continuwuity/README.md
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
# Matrix Self-Hosted Stack — Setup Guide
|
||||||
|
|
||||||
|
## File Overview
|
||||||
|
|
||||||
|
```
|
||||||
|
matrix-stack/
|
||||||
|
├── docker-compose.yml # All services: Continuwuity, Traefik, Coturn, LiveKit, lk-jwt-service
|
||||||
|
├── continuwuity.toml # Homeserver config: TURN URIs, LiveKit foci
|
||||||
|
├── livekit.yaml # LiveKit media server config
|
||||||
|
├── coturn.conf # TURN/STUN server config
|
||||||
|
└── README.md # This file
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
1. Two DNS A records pointing to your server's public IP:
|
||||||
|
- `matrix.example.com`
|
||||||
|
- `livekit.example.com`
|
||||||
|
(If you want your Matrix IDs as `@user:example.com` rather than
|
||||||
|
`@user:matrix.example.com`, also point `example.com` to your server.)
|
||||||
|
|
||||||
|
2. Docker + Docker Compose installed.
|
||||||
|
|
||||||
|
3. Create the external proxy network Traefik uses:
|
||||||
|
```bash
|
||||||
|
docker network create proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## One-Time Secret Generation
|
||||||
|
|
||||||
|
### Coturn secret
|
||||||
|
```bash
|
||||||
|
# Install pwgen if needed: apt install pwgen
|
||||||
|
pwgen -s 64 1
|
||||||
|
```
|
||||||
|
Paste the output into both `coturn.conf` (static-auth-secret)
|
||||||
|
and `continuwuity.toml` (turn_secret). They MUST match.
|
||||||
|
|
||||||
|
### LiveKit keys
|
||||||
|
```bash
|
||||||
|
docker run --rm livekit/livekit-server:latest generate-keys
|
||||||
|
```
|
||||||
|
This outputs a key (~20 chars) and secret (~64 chars).
|
||||||
|
Paste them into:
|
||||||
|
- `livekit.yaml` → keys section
|
||||||
|
- `docker-compose.yml` → lk-jwt-service LIVEKIT_KEY / LIVEKIT_SECRET
|
||||||
|
|
||||||
|
### Registration token (for invite-only signup)
|
||||||
|
```bash
|
||||||
|
pwgen -s 32 1
|
||||||
|
```
|
||||||
|
Paste into docker-compose.yml → CONTINUWUITY_REGISTRATION_TOKEN.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Starting Up
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# First boot — creates admin user automatically
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# Get your admin password
|
||||||
|
docker compose logs homeserver | grep "Created user"
|
||||||
|
|
||||||
|
# IMPORTANT: Edit docker-compose.yml and remove the --execute flag
|
||||||
|
# from the homeserver command, then restart:
|
||||||
|
docker compose up -d homeserver
|
||||||
|
```
|
||||||
|
|
||||||
|
Log in with any Matrix client (Element, Cinny, etc.) using
|
||||||
|
`@admin:example.com` and the generated password.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Firewall Rules
|
||||||
|
|
||||||
|
Open these ports on your server's firewall (ufw examples shown).
|
||||||
|
|
||||||
|
### HTTP/HTTPS — handled by Traefik
|
||||||
|
```bash
|
||||||
|
ufw allow 80/tcp # HTTP (redirected to HTTPS by Traefik)
|
||||||
|
ufw allow 443/tcp # HTTPS for matrix.example.com and livekit.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Coturn — TURN/STUN (raw UDP/TCP, NOT proxied by Traefik)
|
||||||
|
```bash
|
||||||
|
ufw allow 3478/tcp # STUN + TURN
|
||||||
|
ufw allow 3478/udp
|
||||||
|
ufw allow 5349/tcp # TURN over TLS (if you configured TLS in coturn.conf)
|
||||||
|
ufw allow 5349/udp
|
||||||
|
ufw allow 50201:65535/udp # Coturn media relay port range
|
||||||
|
```
|
||||||
|
|
||||||
|
### LiveKit — RTC media (raw UDP/TCP, NOT proxied by Traefik)
|
||||||
|
```bash
|
||||||
|
ufw allow 7881/tcp # LiveKit direct TCP (for clients that can't UDP)
|
||||||
|
ufw allow 50100:50200/udp # LiveKit media relay port range
|
||||||
|
```
|
||||||
|
|
||||||
|
### Summary table
|
||||||
|
|
||||||
|
| Port(s) | Protocol | Service | Via Traefik? |
|
||||||
|
|----------------|-----------|--------------------|--------------|
|
||||||
|
| 80 | TCP | HTTP (→ HTTPS) | Yes |
|
||||||
|
| 443 | TCP | HTTPS | Yes |
|
||||||
|
| 3478 | TCP + UDP | Coturn TURN/STUN | No — direct |
|
||||||
|
| 5349 | TCP + UDP | Coturn TURN TLS | No — direct |
|
||||||
|
| 7881 | TCP | LiveKit direct TCP | No — direct |
|
||||||
|
| 50100–50200 | UDP | LiveKit media | No — direct |
|
||||||
|
| 50201–65535 | UDP | Coturn media relay | No — direct |
|
||||||
|
|
||||||
|
**Key point**: Traefik only handles ports 80 and 443. The Matrix
|
||||||
|
homeserver (6167) and LiveKit HTTP (7880) are never exposed directly
|
||||||
|
— Traefik proxies them internally. Coturn and LiveKit's RTC ports
|
||||||
|
bypass Traefik entirely and are opened directly to the internet.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Can I use an External NGINX Proxy Manager instead of Traefik?
|
||||||
|
|
||||||
|
**Short answer: yes, but with important caveats.**
|
||||||
|
|
||||||
|
### What NPM can handle
|
||||||
|
- `matrix.example.com` → proxy to `http://YOUR_SERVER_IP:6167`
|
||||||
|
- Enable WebSockets
|
||||||
|
- Set `X-Forwarded-For`, `Host`, `X-Real-IP` headers
|
||||||
|
- `livekit.example.com` with path splitting:
|
||||||
|
- `/sfu/get`, `/healthz`, `/get_token` → `http://YOUR_SERVER_IP:8081`
|
||||||
|
- Everything else → `http://YOUR_SERVER_IP:7880`
|
||||||
|
- Enable WebSockets on both
|
||||||
|
- NPM handles Let's Encrypt TLS automatically
|
||||||
|
|
||||||
|
### What NPM cannot handle
|
||||||
|
- **Coturn** — raw UDP/TCP, not HTTP. NPM (like Traefik) can't proxy it.
|
||||||
|
You just open ports 3478/5349 directly and point DNS at your server IP.
|
||||||
|
- **LiveKit RTC ports** (7881/tcp, 50100-50200/udp) — same story.
|
||||||
|
These bypass any reverse proxy entirely.
|
||||||
|
|
||||||
|
### Changes needed to docker-compose.yml for NPM
|
||||||
|
|
||||||
|
1. **Remove the entire `traefik:` service block.**
|
||||||
|
|
||||||
|
2. **Remove all `labels:` blocks** from homeserver and lk-jwt-service.
|
||||||
|
|
||||||
|
3. **Expose the ports NPM needs to reach:**
|
||||||
|
```yaml
|
||||||
|
homeserver:
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:6167:6167" # NPM proxies this
|
||||||
|
|
||||||
|
lk-jwt-service:
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8081:8081" # NPM proxies this
|
||||||
|
|
||||||
|
# livekit already uses network_mode: host, so 7880 is available
|
||||||
|
# on the host at 127.0.0.1:7880 automatically
|
||||||
|
```
|
||||||
|
Using `127.0.0.1:` prefix means only NPM (on the same host or
|
||||||
|
your network) can reach them — not the open internet.
|
||||||
|
|
||||||
|
4. **Remove the `acme:` volume** (NPM handles TLS).
|
||||||
|
|
||||||
|
5. In NPM, configure two proxy hosts:
|
||||||
|
|
||||||
|
**matrix.example.com**
|
||||||
|
- Forward to: `http://YOUR_SERVER_IP:6167`
|
||||||
|
- Websockets: ON
|
||||||
|
- Custom nginx config:
|
||||||
|
```nginx
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header Host $http_host;
|
||||||
|
```
|
||||||
|
|
||||||
|
**livekit.example.com**
|
||||||
|
- Forward to: `http://YOUR_SERVER_IP:7880` (default)
|
||||||
|
- Websockets: ON
|
||||||
|
- Advanced tab — add this custom config for path splitting:
|
||||||
|
```nginx
|
||||||
|
location ~ ^/(sfu/get|healthz|get_token) {
|
||||||
|
proxy_pass http://YOUR_SERVER_IP:8081$request_uri;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header Host $http_host;
|
||||||
|
proxy_buffering off;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### NPM on a separate machine?
|
||||||
|
If NPM runs on a different server, replace `127.0.0.1` with your
|
||||||
|
Matrix server's internal IP, and make sure port 6167 is firewalled
|
||||||
|
to only allow connections from NPM's IP.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
### Test TURN credentials
|
||||||
|
```bash
|
||||||
|
curl "https://matrix.example.com/_matrix/client/r0/voip/turnServer" \
|
||||||
|
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" | jq
|
||||||
|
```
|
||||||
|
Should return a JSON object with `uris`, `username`, `password`.
|
||||||
|
|
||||||
|
### Test TURN connectivity
|
||||||
|
1. Go to https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
|
||||||
|
2. Paste the credentials from above
|
||||||
|
3. Click "Gather candidates" — look for `relay` type candidates
|
||||||
|
|
||||||
|
### Test LiveKit
|
||||||
|
1. GET `https://livekit.example.com/healthz` — should return 200
|
||||||
|
2. Use https://livekit.io/connection-test with a token from `/get_token`
|
||||||
|
|
||||||
|
### Test federation
|
||||||
|
https://federationtester.matrix.org — enter your domain
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**Federation not working**
|
||||||
|
- Check `.well-known/matrix/server` is reachable:
|
||||||
|
`curl https://example.com/.well-known/matrix/server`
|
||||||
|
- Should return: `{"m.server":"matrix.example.com:443"}`
|
||||||
|
|
||||||
|
**TURN not working**
|
||||||
|
- Verify firewall allows 3478/udp from the internet
|
||||||
|
- Check coturn logs: `docker compose logs coturn`
|
||||||
|
- Confirm `turn_secret` in continuwuity.toml matches `static-auth-secret` in coturn.conf
|
||||||
|
|
||||||
|
**Element Call / group calls failing**
|
||||||
|
- Check lk-jwt-service is reachable: `curl https://livekit.example.com/healthz`
|
||||||
|
- Confirm LiveKit UDP ports (50100-50200) are open
|
||||||
|
- Check `foci` URL in continuwuity.toml matches where lk-jwt-service is deployed
|
||||||
45
continuwuity/continuwuity.toml
Normal file
45
continuwuity/continuwuity.toml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# ============================================================
|
||||||
|
# continuwuity.toml — Continuwuity Homeserver Configuration
|
||||||
|
# Mount this at /etc/continuwuity.toml in the container.
|
||||||
|
#
|
||||||
|
# Most settings are handled via environment variables in
|
||||||
|
# docker-compose.yml. This file handles things that are
|
||||||
|
# easier to express in TOML: TURN and MatrixRTC config.
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
[global]
|
||||||
|
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# TURN / STUN — for legacy 1:1 voice and video calls
|
||||||
|
# Uses shared secret auth (time-limited credentials, more secure
|
||||||
|
# than static username/password).
|
||||||
|
# The turn_secret MUST match static-auth-secret in coturn.conf.
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
turn_uris = [
|
||||||
|
"turn:matrix.example.com?transport=udp",
|
||||||
|
"turn:matrix.example.com?transport=tcp",
|
||||||
|
"turns:matrix.example.com?transport=udp", # TURN over TLS (port 5349)
|
||||||
|
"turns:matrix.example.com?transport=tcp"
|
||||||
|
]
|
||||||
|
|
||||||
|
# Must match `static-auth-secret` in coturn.conf
|
||||||
|
turn_secret = "YOUR_COTURN_SECRET" # EDIT THIS
|
||||||
|
|
||||||
|
# How long TURN credentials are valid (seconds). 24h default.
|
||||||
|
turn_ttl = 86400
|
||||||
|
|
||||||
|
# Set to true only if you want unauthenticated/guest users to
|
||||||
|
# be able to use TURN. Not recommended — leaves TURN open to abuse.
|
||||||
|
turn_allow_guests = false
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# MatrixRTC / Element Call — group calls via LiveKit
|
||||||
|
# Clients discover the LiveKit endpoint via the
|
||||||
|
# /_matrix/client/v1/rtc/transports API (MSC4143).
|
||||||
|
# The URL here points to your lk-jwt-service, NOT LiveKit directly.
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
[global.matrix_rtc]
|
||||||
|
foci = [
|
||||||
|
{ type = "livekit", livekit_service_url = "https://livekit.example.com" },
|
||||||
|
]
|
||||||
51
continuwuity/coturn.conf
Normal file
51
continuwuity/coturn.conf
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# ============================================================
|
||||||
|
# coturn.conf — Coturn TURN/STUN Server Configuration
|
||||||
|
# Mount this at /etc/coturn/turnserver.conf in the container.
|
||||||
|
#
|
||||||
|
# Generate a secret with: pwgen -s 64 1
|
||||||
|
# The secret here MUST match turn_secret in continuwuity.toml.
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# Use time-limited shared-secret auth (more secure than static credentials)
|
||||||
|
use-auth-secret
|
||||||
|
static-auth-secret=YOUR_COTURN_SECRET # EDIT THIS — must match continuwuity.toml
|
||||||
|
|
||||||
|
# realm should match your Matrix domain
|
||||||
|
realm=matrix.example.com # EDIT THIS
|
||||||
|
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# Port ranges
|
||||||
|
# Default coturn range is 49152-65535.
|
||||||
|
# We start at 50201 so it doesn't overlap with LiveKit (50100-50200).
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
min-port=50201
|
||||||
|
max-port=65535
|
||||||
|
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# Optional: TLS support (recommended for production)
|
||||||
|
# You'll need to provide certificates. One approach is to copy
|
||||||
|
# them from your Let's Encrypt store (requires a cron/hook).
|
||||||
|
# Comment these out if you're not setting up TLS on coturn.
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# tls-listening-port=5349
|
||||||
|
# cert=/etc/coturn/certs/fullchain.pem
|
||||||
|
# pkey=/etc/coturn/certs/privkey.pem
|
||||||
|
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# Security hardening
|
||||||
|
# Prevents coturn from being used as an open relay/proxy.
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
# Deny connections to private/loopback IP ranges (prevents SSRF)
|
||||||
|
denied-peer-ip=10.0.0.0-10.255.255.255
|
||||||
|
denied-peer-ip=192.168.0.0-192.168.255.255
|
||||||
|
denied-peer-ip=172.16.0.0-172.31.255.255
|
||||||
|
denied-peer-ip=127.0.0.0-127.255.255.255
|
||||||
|
|
||||||
|
# Only allow relay to public IPs
|
||||||
|
no-multicast-peers
|
||||||
|
|
||||||
|
# Disable the web admin interface (not needed, reduces attack surface)
|
||||||
|
no-cli
|
||||||
|
|
||||||
|
# Log to stdout so Docker captures it
|
||||||
|
log-file=stdout
|
||||||
180
continuwuity/docker-compose.yml
Normal file
180
continuwuity/docker-compose.yml
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
# ============================================================
|
||||||
|
# Matrix Self-Hosted Stack
|
||||||
|
# Services: Continuwuity, Coturn, LiveKit, lk-jwt-service
|
||||||
|
#
|
||||||
|
# Domains (replace throughout):
|
||||||
|
# matrix.example.com — homeserver
|
||||||
|
# livekit.example.com — LiveKit + JWT service
|
||||||
|
#
|
||||||
|
# Before starting:
|
||||||
|
# 1. Fill in all YOUR_* placeholders
|
||||||
|
# 2. Set your email for Let's Encrypt
|
||||||
|
# 3. Run: docker network create proxy
|
||||||
|
# 4. Then: docker compose up -d
|
||||||
|
# 5. Grab admin password: docker compose logs homeserver | grep "Created user"
|
||||||
|
# 6. Remove the --execute flag from homeserver command after first boot
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# Traefik — Reverse Proxy & TLS termination
|
||||||
|
# Handles HTTPS for matrix.example.com and livekit.example.com
|
||||||
|
# Does NOT handle coturn (raw UDP/TCP, not HTTP)
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
traefik:
|
||||||
|
image: traefik:latest
|
||||||
|
container_name: traefik
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
|
- acme:/etc/traefik/acme
|
||||||
|
environment:
|
||||||
|
TRAEFIK_LOG_LEVEL: INFO
|
||||||
|
TRAEFIK_ENTRYPOINTS_WEB_ADDRESS: ":80"
|
||||||
|
TRAEFIK_ENTRYPOINTS_WEB_HTTP_REDIRECTIONS_ENTRYPOINT_TO: websecure
|
||||||
|
TRAEFIK_ENTRYPOINTS_WEBSECURE_ADDRESS: ":443"
|
||||||
|
TRAEFIK_ENTRYPOINTS_WEBSECURE_HTTP_TLS_CERTRESOLVER: letsencrypt
|
||||||
|
# Allow encoded characters needed by Matrix
|
||||||
|
TRAEFIK_ENTRYPOINTS_WEBSECURE_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDSLASH: "true"
|
||||||
|
TRAEFIK_ENTRYPOINTS_WEBSECURE_HTTP_ENCODEDCHARACTERS_ALLOWENCODEDHASH: "true"
|
||||||
|
TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT: "true"
|
||||||
|
TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_EMAIL: "you@example.com" # EDIT THIS
|
||||||
|
TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_KEYTYPE: EC384
|
||||||
|
TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_HTTPCHALLENGE: "true"
|
||||||
|
TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_HTTPCHALLENGE_ENTRYPOINT: web
|
||||||
|
TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_ACME_STORAGE: /etc/traefik/acme/acme.json
|
||||||
|
TRAEFIK_PROVIDERS_DOCKER: "true"
|
||||||
|
TRAEFIK_PROVIDERS_DOCKER_EXPOSEDBYDEFAULT: "false"
|
||||||
|
networks:
|
||||||
|
- proxy
|
||||||
|
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# Continuwuity — Matrix Homeserver
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
homeserver:
|
||||||
|
image: forgejo.ellis.link/continuwuation/continuwuity:latest
|
||||||
|
container_name: continuwuity
|
||||||
|
restart: unless-stopped
|
||||||
|
# Remove the --execute flag after first boot once you have your admin password
|
||||||
|
command: /sbin/conduwuit --execute "users create-user admin"
|
||||||
|
depends_on:
|
||||||
|
- traefik
|
||||||
|
volumes:
|
||||||
|
- db:/var/lib/continuwuity
|
||||||
|
- ./continuwuity.toml:/etc/continuwuity.toml:ro
|
||||||
|
# Use host DNS to avoid Docker's resolver causing federation issues
|
||||||
|
- /etc/resolv.conf:/etc/resolv.conf:ro
|
||||||
|
networks:
|
||||||
|
- proxy
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
# Serve matrix.example.com AND well-known paths on example.com for delegation
|
||||||
|
- "traefik.http.routers.continuwuity.rule=(Host(`matrix.example.com`) || (Host(`example.com`) && PathPrefix(`/.well-known/matrix`)))"
|
||||||
|
- "traefik.http.routers.continuwuity.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.continuwuity.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.services.continuwuity.loadbalancer.server.port=6167"
|
||||||
|
environment:
|
||||||
|
CONTINUWUITY_SERVER_NAME: "example.com" # Your Matrix ID domain (@user:example.com)
|
||||||
|
CONTINUWUITY_DATABASE_PATH: /var/lib/continuwuity
|
||||||
|
CONTINUWUITY_ADDRESS: 0.0.0.0
|
||||||
|
CONTINUWUITY_PORT: 6167
|
||||||
|
CONTINUWUITY_MAX_REQUEST_SIZE: "20000000" # ~20 MB
|
||||||
|
CONTINUWUITY_ALLOW_REGISTRATION: "false" # Enable with a token for invite-only
|
||||||
|
CONTINUWUITY_REGISTRATION_TOKEN: "YOUR_INVITE_TOKEN" # EDIT THIS
|
||||||
|
CONTINUWUITY_ALLOW_FEDERATION: "true"
|
||||||
|
CONTINUWUITY_ALLOW_CHECK_FOR_UPDATES: "true"
|
||||||
|
CONTINUWUITY_TRUSTED_SERVERS: '["matrix.org"]'
|
||||||
|
CONTINUWUITY_CONFIG: /etc/continuwuity.toml
|
||||||
|
# Well-known delegation so clients and servers find your homeserver
|
||||||
|
CONTINUWUITY_WELL_KNOWN: |
|
||||||
|
{
|
||||||
|
client=https://matrix.example.com,
|
||||||
|
server=matrix.example.com:443
|
||||||
|
}
|
||||||
|
ulimits:
|
||||||
|
nofile:
|
||||||
|
soft: 1048567
|
||||||
|
hard: 1048567
|
||||||
|
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# Coturn — TURN/STUN server for legacy 1:1 calls
|
||||||
|
# Uses host networking — Traefik does NOT proxy this.
|
||||||
|
# Reachable directly on the host IP via UDP/TCP ports 3478/5349
|
||||||
|
# and the relay port range 50201-65535.
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
coturn:
|
||||||
|
image: coturn/coturn:latest
|
||||||
|
container_name: coturn
|
||||||
|
restart: unless-stopped
|
||||||
|
network_mode: host
|
||||||
|
volumes:
|
||||||
|
- ./coturn.conf:/etc/coturn/turnserver.conf:ro
|
||||||
|
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# LiveKit — Media server for MatrixRTC / Element Call
|
||||||
|
# Also uses host networking for RTC performance.
|
||||||
|
# Traefik proxies HTTP/WS on port 7880 via livekit.example.com.
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
livekit:
|
||||||
|
image: livekit/livekit-server:latest
|
||||||
|
container_name: livekit
|
||||||
|
restart: unless-stopped
|
||||||
|
command: --config /etc/livekit.yaml
|
||||||
|
network_mode: host
|
||||||
|
volumes:
|
||||||
|
- ./livekit.yaml:/etc/livekit.yaml:ro
|
||||||
|
# Note: with network_mode: host, Traefik cannot directly label this container.
|
||||||
|
# The livekit.example.com routing is handled via the lk-jwt-service container
|
||||||
|
# labels, with LiveKit itself accessed at 127.0.0.1:7880 from that container's
|
||||||
|
# perspective. See lk-jwt-service labels below.
|
||||||
|
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# lk-jwt-service — Issues JWT tokens for LiveKit
|
||||||
|
# Matrix users authenticate here before joining calls.
|
||||||
|
# Traefik routes livekit.example.com here, with path-based
|
||||||
|
# splitting: /sfu/get, /healthz, /get_token go to this service;
|
||||||
|
# everything else is reverse-proxied onward to LiveKit on :7880.
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
lk-jwt-service:
|
||||||
|
image: ghcr.io/element-hq/lk-jwt-service:latest
|
||||||
|
container_name: lk-jwt-service
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- LIVEKIT_JWT_BIND=:8081
|
||||||
|
- LIVEKIT_URL=wss://livekit.example.com # EDIT: your LiveKit domain
|
||||||
|
- LIVEKIT_KEY=YOUR_LK_KEY # EDIT: from generate-keys
|
||||||
|
- LIVEKIT_SECRET=YOUR_LK_SECRET # EDIT: from generate-keys
|
||||||
|
- LIVEKIT_FULL_ACCESS_HOMESERVERS=example.com # EDIT: your Matrix domain
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8081:8081" # Only bind to localhost; Traefik reaches it here
|
||||||
|
networks:
|
||||||
|
- proxy
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
# High-priority rule: JWT paths go to lk-jwt-service
|
||||||
|
- "traefik.http.routers.livekit-jwt.rule=Host(`livekit.example.com`) && (PathPrefix(`/sfu/get`) || PathPrefix(`/healthz`) || PathPrefix(`/get_token`))"
|
||||||
|
- "traefik.http.routers.livekit-jwt.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.livekit-jwt.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.livekit-jwt.priority=10"
|
||||||
|
- "traefik.http.services.livekit-jwt.loadbalancer.server.port=8081"
|
||||||
|
# Low-priority rule: everything else on livekit.example.com goes to LiveKit itself
|
||||||
|
- "traefik.http.routers.livekit.rule=Host(`livekit.example.com`)"
|
||||||
|
- "traefik.http.routers.livekit.entrypoints=websecure"
|
||||||
|
- "traefik.http.routers.livekit.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.routers.livekit.priority=1"
|
||||||
|
- "traefik.http.services.livekit.loadbalancer.server.url=http://127.0.0.1:7880"
|
||||||
|
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
# Volumes & Networks
|
||||||
|
# ----------------------------------------------------------
|
||||||
|
volumes:
|
||||||
|
db:
|
||||||
|
acme:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
proxy:
|
||||||
|
external: true
|
||||||
68
continuwuity/livekit.yaml
Normal file
68
continuwuity/livekit.yaml
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# ============================================================
|
||||||
|
# livekit.yaml — LiveKit Media Server Configuration
|
||||||
|
# Mount this at /etc/livekit.yaml in the livekit container.
|
||||||
|
#
|
||||||
|
# Replace LK_MATRIX_KEY and LK_MATRIX_SECRET with the values
|
||||||
|
# generated by:
|
||||||
|
# docker run --rm livekit/livekit-server:latest generate-keys
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
# HTTP/WebSocket port (proxied by Traefik)
|
||||||
|
port: 7880
|
||||||
|
|
||||||
|
# Bind to all interfaces (Traefik reaches it on 127.0.0.1:7880
|
||||||
|
# since both livekit and the host share the network stack)
|
||||||
|
bind_addresses:
|
||||||
|
- ""
|
||||||
|
|
||||||
|
rtc:
|
||||||
|
# Direct TCP port for clients that can't use UDP
|
||||||
|
tcp_port: 7881
|
||||||
|
|
||||||
|
# UDP port range for media relay
|
||||||
|
# Starts at 50100 to leave room below for coturn if needed.
|
||||||
|
# Coturn is configured with min-port=50201 to avoid overlap.
|
||||||
|
port_range_start: 50100
|
||||||
|
port_range_end: 50200
|
||||||
|
|
||||||
|
# Required when running behind NAT — LiveKit advertises your
|
||||||
|
# public IP to clients rather than the internal Docker IP
|
||||||
|
use_external_ip: true
|
||||||
|
|
||||||
|
# Disable loopback candidates — not useful in production
|
||||||
|
enable_loopback_candidate: false
|
||||||
|
|
||||||
|
# Optional: Use your coturn server as a TURN relay for LiveKit.
|
||||||
|
# This improves connectivity for clients behind strict firewalls.
|
||||||
|
# Uncomment and fill in if you want LiveKit to use coturn:
|
||||||
|
#
|
||||||
|
# turn_servers:
|
||||||
|
# - host: matrix.example.com
|
||||||
|
# port: 3478
|
||||||
|
# protocol: udp
|
||||||
|
# secret: "YOUR_COTURN_SECRET" # Same secret as coturn.conf
|
||||||
|
# - host: matrix.example.com
|
||||||
|
# port: 3478
|
||||||
|
# protocol: tcp
|
||||||
|
# secret: "YOUR_COTURN_SECRET"
|
||||||
|
# - host: matrix.example.com
|
||||||
|
# port: 5349
|
||||||
|
# protocol: tls
|
||||||
|
# secret: "YOUR_COTURN_SECRET"
|
||||||
|
|
||||||
|
# API keys — must match LIVEKIT_KEY and LIVEKIT_SECRET
|
||||||
|
# in the lk-jwt-service environment variables
|
||||||
|
keys:
|
||||||
|
YOUR_LK_KEY: YOUR_LK_SECRET # EDIT BOTH OF THESE
|
||||||
|
|
||||||
|
# Optional: enable LiveKit's built-in TURN server.
|
||||||
|
# Only useful for LiveKit connections — cannot be used by coturn
|
||||||
|
# or legacy Matrix calls. Use this if you don't want a separate
|
||||||
|
# coturn deployment and only care about group calls.
|
||||||
|
#
|
||||||
|
# turn:
|
||||||
|
# enabled: true
|
||||||
|
# udp_port: 3478
|
||||||
|
# relay_range_start: 50300
|
||||||
|
# relay_range_end: 50400
|
||||||
|
# domain: livekit.example.com
|
||||||
Reference in New Issue
Block a user