livekit añadido

This commit is contained in:
2025-11-10 16:16:34 +01:00
parent d13ab16256
commit 20501ab8bc
12 changed files with 446 additions and 18 deletions
+16
View File
@@ -17,6 +17,22 @@ POSTGRES_PORT=5432
MATRIX_NETWORK_SUBNET=10.10.10.0/24
MATRIX_NETWORK_GATEWAY=10.10.10.1
# Element Call / LiveKit backend
MATRIX_SITE_BASE_URL=https://matrix.example.com
MATRIX_RTC_BASE_URL=https://matrix-rtc.example.com
LIVEKIT_WS_URL=wss://matrix-rtc.example.com/livekit/sfu
LIVEKIT_JWT_URL=https://matrix-rtc.example.com/livekit/jwt
LIVEKIT_API_KEY=CHANGE_ME
LIVEKIT_API_SECRET=CHANGE_ME_AT_LEAST_32_CHARS
LIVEKIT_HTTP_PORT=7880
LIVEKIT_TCP_PORT=7881
LIVEKIT_HEALTH_PORT=7882
LIVEKIT_UDP_PORT_RANGE_START=50000
LIVEKIT_UDP_PORT_RANGE_END=50200
LIVEKIT_JWT_PORT=6080
LIVEKIT_JWT_BIND=:6080
LIVEKIT_INSECURE_SKIP_VERIFY_TLS=false
# Element Configuration
ELEMENT_BRAND=Element Local
ELEMENT_DEFAULT_THEME=light
+4
View File
@@ -32,6 +32,10 @@ certs/
*.key
*.crt
# Configuraciones sensibles generadas en tiempo de despliegue
configs/livekit/livekit.yaml
configs/well-known/matrix-client.json
# Archivos de media de Matrix (pueden ser muy grandes)
*/media_store/
*/uploads/
+10
View File
@@ -69,6 +69,16 @@ element_matrix_chat/
- ✅ Panel de administración web
- ✅ Persistencia de datos
## 📞 Element Call + LiveKit
Si quieres habilitar llamadas con Element Call y su backend LiveKit, revisa la
[guía específica](docs/element-call-livekit.md). Explica cómo:
- Ajustar Synapse para MatrixRTC
- Generar la configuración de LiveKit
- Ejecutar los contenedores `livekit` y `livekit-jwt`
- Publicar el `.well-known` y el frontend (opcional)
## 📖 Documentación adicional
Consulta la [documentación oficial de Matrix](https://matrix.org/docs/) para configuraciones avanzadas.
+34
View File
@@ -0,0 +1,34 @@
# LiveKit configuration example for Element Call.
# Copy this file to configs/livekit/livekit.yaml and replace the placeholder
# values before starting the stack.
port: 7880
bind_addresses:
- "0.0.0.0"
log_level: info
region: "us-east-1"
rtc:
tcp_port: 7881
port_range_start: 50000
port_range_end: 50200
use_external_ip: true
force_tcp: false
# Optional TURN forwarding. Enable only if you already operate a TURN server.
turn:
enabled: false
domain: ""
cert_file: ""
key_file: ""
tls_port: 5349
udp_port: 443
external_tls: true
# The keys map controls which API key/secret pairs are valid.
# Generate your own pair with: openssl rand -hex 32
# Secrets must be at least 32 characters long.
keys:
LIVEKIT_API_KEY_PLACEHOLDER: LIVEKIT_API_SECRET_PLACEHOLDER
room:
auto_create: false
+54
View File
@@ -0,0 +1,54 @@
server {
listen 80;
listen 443 ssl;
server_name localhost;
ssl_certificate /etc/nginx/certs/localhost.crt;
ssl_certificate_key /etc/nginx/certs/localhost.key;
add_header Access-Control-Allow-Origin $http_origin always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization" always;
# Handle preflight requests generically
if ($request_method = OPTIONS) {
return 204;
}
# Serve Matrix client well-known metadata
location /.well-known/matrix/client {
default_type application/json;
add_header Access-Control-Allow-Origin $http_origin always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization" always;
alias /var/www/well-known/matrix-client.json;
}
# Optional Matrix server discovery stub (useful for federation later)
location /.well-known/matrix/server {
default_type application/json;
return 200 '{"m.server":"localhost:8008"}';
}
# Proxy Matrix Client/Server and Synapse admin APIs to the Synapse container
location / {
proxy_pass http://synapse:8008;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 50m;
# Hide upstream CORS headers and set our own
proxy_hide_header Access-Control-Allow-Origin;
proxy_hide_header Access-Control-Allow-Methods;
proxy_hide_header Access-Control-Allow-Headers;
proxy_hide_header Access-Control-Expose-Headers;
add_header Access-Control-Allow-Origin $http_origin always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization" always;
}
}
+31
View File
@@ -0,0 +1,31 @@
server {
listen 80;
server_name matrix-rtc.localhost;
# MatrixRTC Authorization Service (lk-jwt-service)
location ^~ /livekit/jwt/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://livekit-jwt:6080/;
}
# LiveKit SFU Websocket (signalling)
location ^~ /livekit/sfu/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Accept-Encoding gzip;
proxy_send_timeout 120;
proxy_read_timeout 120;
proxy_buffering off;
proxy_pass http://livekit:7880/;
}
}
@@ -0,0 +1,12 @@
{
"m.homeserver": {
"base_url": "https://matrix.example.com",
"server_name": "matrix.example.com"
},
"org.matrix.msc4143.rtc_foci": [
{
"type": "livekit",
"livekit_service_url": "https://matrix-rtc.example.com/livekit/jwt"
}
]
}
+48
View File
@@ -0,0 +1,48 @@
services:
livekit:
image: livekit/livekit-server:latest
restart: unless-stopped
command: --config /etc/livekit/livekit.yaml
volumes:
- ./configs/livekit/livekit.yaml:/etc/livekit/livekit.yaml:ro
ports:
- "${LIVEKIT_HTTP_PORT:-7880}:7880/tcp"
- "${LIVEKIT_TCP_PORT:-7881}:7881/tcp"
- "${LIVEKIT_HEALTH_PORT:-7882}:7882/tcp"
- "${LIVEKIT_UDP_PORT_RANGE_START:-50000}-${LIVEKIT_UDP_PORT_RANGE_END:-50200}:${LIVEKIT_UDP_PORT_RANGE_START:-50000}-${LIVEKIT_UDP_PORT_RANGE_END:-50200}/udp"
networks:
default:
ipv4_address: 10.10.10.6
livekit-jwt:
image: ghcr.io/element-hq/lk-jwt-service:latest-ci
restart: unless-stopped
environment:
LIVEKIT_JWT_BIND: ${LIVEKIT_JWT_BIND:-:6080}
LIVEKIT_URL: ${LIVEKIT_WS_URL}
LIVEKIT_KEY: ${LIVEKIT_API_KEY}
LIVEKIT_SECRET: ${LIVEKIT_API_SECRET}
LIVEKIT_FULL_ACCESS_HOMESERVERS: ${MATRIX_SERVER_NAME}
LIVEKIT_INSECURE_SKIP_VERIFY_TLS: ${LIVEKIT_INSECURE_SKIP_VERIFY_TLS:-false}
networks:
default:
ipv4_address: 10.10.10.7
matrix-rtc-proxy:
image: nginx:alpine
restart: unless-stopped
depends_on:
- livekit
- livekit-jwt
volumes:
- ./configs/nginx/matrix-rtc-proxy.conf:/etc/nginx/conf.d/default.conf:ro
ports:
- "${LIVEKIT_JWT_PORT:-6080}:80"
networks:
default:
ipv4_address: 10.10.10.9
networks:
default:
name: matrix_net
external: true
+17 -7
View File
@@ -32,10 +32,7 @@ services:
default:
ipv4_address: 10.10.10.4
volumes:
- matrix_synapse_data:/data
ports:
- "8008:8008"
- "8009:8009"
- ./synapse_data:/data
depends_on:
- postgres
user: "0:0"
@@ -54,13 +51,26 @@ services:
depends_on:
- synapse
matrix-proxy:
image: nginx:alpine
restart: unless-stopped
depends_on:
- synapse
networks:
default:
ipv4_address: 10.10.10.8
ports:
- "8008:80"
- "443:443"
volumes:
- ./configs/nginx/matrix-proxy.conf:/etc/nginx/conf.d/default.conf:ro
- ./configs/well-known:/var/www/well-known:ro
- ./configs/nginx/certs:/etc/nginx/certs:ro
volumes:
matrix_postgres_data:
external: true
name: matrix_postgres_data
matrix_synapse_data:
external: true
name: matrix_synapse_data
networks:
default:
+161
View File
@@ -0,0 +1,161 @@
# Element Call + LiveKit en este stack
Esta guía resume cómo se conecta el repositorio `element-call` incluido en este
proyecto y qué pasos seguir para habilitar el backend MatrixRTC (LiveKit +
lk-jwt-service) dentro del entorno Docker ya existente.
> ️ Para más contexto técnico revisa también `element-call/docs/self-hosting.md`
> y `element-call/backend/dev_nginx.conf`, donde Element documenta la arquitectura
> oficial de referencia.
## 1. Requisitos del homeserver
1. Añade las MSC necesarias en `synapse_data/homeserver.yaml` (o en tu plantilla):
```yaml
experimental_features:
msc3266_enabled: true
msc4222_enabled: true
msc4354_enabled: true
max_event_delay_duration: 24h
rc_message:
per_second: 0.5
burst_count: 30
rc_delayed_event_mgmt:
per_second: 1
burst_count: 20
```
2. Asegúrate de tener un listener `federation` o `openid` expuesto (lo necesita
el `lk-jwt-service` para validar los tokens Matrix).
3. Configura `.well-known/matrix/client` para publicar el backend MatrixRTC:
```json
{
"m.homeserver": {
"base_url": "https://matrix.example.com",
"server_name": "matrix.example.com"
},
"org.matrix.msc4143.rtc_foci": [
{
"type": "livekit",
"livekit_service_url": "https://matrix-rtc.example.com/livekit/jwt"
}
]
}
```
El archivo `configs/well-known/matrix-client.example.json` sirve como plantilla;
cópialo a `configs/well-known/matrix-client.json` y ajústalo con tu dominio.
Sirve este JSON con TLS (Nginx/Caddy) en `https://<tu-dominio>/.well-known/matrix/client`.
## 2. Preparar configuraciones locales
1. **Variables de entorno**
Edita `.env` (o crea uno nuevo desde `.env.example`) y completa los valores:
- `MATRIX_SITE_BASE_URL`, `MATRIX_RTC_BASE_URL`
- `LIVEKIT_WS_URL`, `LIVEKIT_JWT_URL`
- `LIVEKIT_API_KEY`, `LIVEKIT_API_SECRET`
- Puertos `LIVEKIT_*`
2. **LiveKit**
- Copia `configs/livekit/livekit.example.yaml` a
`configs/livekit/livekit.yaml`.
- Cambia región, puertos si es necesario y, sobre todo, define tu par
`keys` con el mismo `LIVEKIT_API_KEY`/`LIVEKIT_API_SECRET` del `.env`.
3. **Reverse proxy**
Expón dos rutas públicas (con TLS) hacia los nuevos contenedores:
| Ruta pública | Proxy interno |
| ------------------------------------------- | ----------------------------------- |
| `https://matrix-rtc.example.com/livekit/jwt` | `http://livekit-jwt:${LIVEKIT_JWT_PORT}` |
| `wss://matrix-rtc.example.com/livekit/sfu` | `http://livekit:${LIVEKIT_HTTP_PORT}` |
Ejemplo básico en Nginx:
```nginx
server {
server_name matrix-rtc.example.com;
listen 443 ssl http2;
location ^~ /livekit/jwt/ {
proxy_pass http://10.10.10.7:${LIVEKIT_JWT_PORT}/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location ^~ /livekit/sfu/ {
proxy_pass http://10.10.10.6:${LIVEKIT_HTTP_PORT}/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 120;
proxy_send_timeout 120;
}
}
```
## 3. Desplegar los servicios LiveKit
1. Levanta la red base y los servicios habituales (`docker-compose up -d`).
2. Arranca los componentes MatrixRTC usando el archivo adicional:
```bash
docker compose -f docker-compose.yml -f docker-compose.livekit.yml up -d livekit livekit-jwt
```
El archivo `docker-compose.livekit.yml` añade:
- `livekit`: SFU oficial (`livekit/livekit-server`) usando `configs/livekit/livekit.yaml`.
- `livekit-jwt`: servicio `ghcr.io/element-hq/lk-jwt-service` que firma los
tokens que consumen los clientes MatrixRTC.
3. Comprueba que los servicios responden:
```bash
# JWT service
curl -sf https://matrix-rtc.example.com/livekit/jwt/healthz
# LiveKit (revisa los logs o escucha el puerto de salud configurado)
docker logs -f element_matrix_chat-livekit-1
```
## 4. Publicar el frontend Element Call (opcional)
El backend LiveKit habilita las llamadas MatrixRTC para Element Web / Element X
una vez que el `.well-known` anuncia el foco. Si además quieres exponer la
aplicación Element Call en modo standalone:
1. Construye el frontend:
```bash
cd element-call
corepack enable
yarn install --immutable
cp config/config.sample.json public/config.json # o personaliza uno nuevo
yarn build
```
2. Sirve los archivos de `element-call/dist/` con el servidor web de tu
preferencia (o crea tu propia imagen Docker basada en `element-call/Dockerfile`).
Recuerda actualizar `public/config.json` para apuntar a tu homeserver y, si lo
quieres forzar, al `livekit_service_url`.
## 5. Verificación final
1. Abre `https://matrix.example.com/.well-known/matrix/client` y valida que el
JSON devuelve correctamente tu `livekit_service_url`.
2. Desde Element Web (usuario registrado en el mismo homeserver) inicia una
llamada en una sala y revisa en los logs del contenedor `livekit-jwt`
que se emite el token (`docker logs -f <contenedor>`).
3. Usa herramientas como [testmatrix](https://codeberg.org/spaetz/testmatrix) para
validar que tu sitio expone MatrixRTC correctamente.
Con estos pasos tendrás tanto el backend MatrixRTC (LiveKit + Authorization
Service) como la referencia para desplegar el frontend Element Call dentro de
tu servidor Matrix.
Submodule
+1
Submodule element-call added at 5afc3c2598
+51 -4
View File
@@ -12,6 +12,10 @@ YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
LIVEKIT_COMPOSE_FILE="docker-compose.livekit.yml"
LIVEKIT_CONFIG_FILE="configs/livekit/livekit.yaml"
LIVEKIT_CONFIG_TEMPLATE="configs/livekit/livekit.example.yaml"
# Verificar Docker
if ! command -v docker &> /dev/null; then
echo -e "${RED}❌ Docker no está instalado${NC}"
@@ -50,6 +54,33 @@ fi
echo -e "${BLUE}📁 Creando directorios...${NC}"
mkdir -p synapse_data/appservices
mkdir -p backups
mkdir -p configs/livekit
# Crear volúmenes externos requeridos por docker-compose si no existen
for volume in matrix_postgres_data; do
if ! docker volume ls --format '{{.Name}}' | grep -qx "$volume"; then
echo -e "${BLUE}🗄️ Creando volumen Docker $volume...${NC}"
docker volume create "$volume" >/dev/null
echo -e "${GREEN}✅ Volumen $volume creado${NC}"
else
echo -e "${YELLOW}️ Volumen $volume ya existe${NC}"
fi
done
# Verificar configuración de LiveKit
if [ ! -f "${LIVEKIT_CONFIG_FILE}" ]; then
if [ -f "${LIVEKIT_CONFIG_TEMPLATE}" ]; then
cp "${LIVEKIT_CONFIG_TEMPLATE}" "${LIVEKIT_CONFIG_FILE}"
fi
echo -e "${RED}❌ No se encontró ${LIVEKIT_CONFIG_FILE}${NC}"
echo -e "${YELLOW} Se creó una plantilla base, edítala antes de continuar.${NC}"
exit 1
fi
if [ ! -f "${LIVEKIT_COMPOSE_FILE}" ]; then
echo -e "${RED}❌ Falta ${LIVEKIT_COMPOSE_FILE}. No se puede iniciar LiveKit.${NC}"
exit 1
fi
# Generar configuración de Synapse si no existe
if [ ! -f synapse_data/homeserver.yaml ]; then
@@ -74,6 +105,8 @@ fi
echo -e "${BLUE}🐳 Iniciando contenedores...${NC}"
docker-compose up -d
echo -e "${BLUE}📡 Iniciando LiveKit + lk-jwt...${NC}"
docker-compose -f "${LIVEKIT_COMPOSE_FILE}" up -d
echo -e "${BLUE}⏳ Esperando que los servicios estén listos...${NC}"
sleep 20
@@ -81,16 +114,30 @@ sleep 20
# Verificar que todos los servicios estén funcionando
echo -e "${BLUE}🔍 Verificando servicios...${NC}"
services=("postgres:5432" "synapse:8008" "element:8081" "synapse-admin:8082")
services=(
"postgres:5432:tcp"
"synapse:8008:http"
"element:8081:http"
"synapse-admin:8082:http"
"livekit:${LIVEKIT_HTTP_PORT:-7880}:http"
"livekit-jwt:${LIVEKIT_JWT_PORT:-6080}:http"
)
for service in "${services[@]}"; do
name=${service%:*}
port=${service#*:}
IFS=":" read -r name port proto <<<"$service"
if curl -s http://localhost:$port > /dev/null 2>&1; then
if [ "$proto" = "http" ]; then
if curl -s --max-time 5 "http://localhost:$port" > /dev/null 2>&1; then
echo -e "${GREEN}$name (puerto $port) - OK${NC}"
else
echo -e "${RED}$name (puerto $port) - ERROR${NC}"
fi
else
if timeout 5 bash -c "cat < /dev/null > /dev/tcp/localhost/$port" > /dev/null 2>&1; then
echo -e "${GREEN}$name (puerto $port) - OK${NC}"
else
echo -e "${RED}$name (puerto $port) - ERROR${NC}"
fi
fi
done
# Crear usuario administrador si no existe