WebRTC with Livekit

The WebRTC conversation service and its componen

This guide walks you through deploying webrtc-server using https://github.com/Conv-AI/webrtc-server/tree/main . You’ll need two domains:

  1. vm.example.com – main WebRTC server

  2. vm-turn.example.com – TURN server

The repo supports two deployment methods and includes the build_vm_init.sh helper script to generate a vm_init.sh setup script.

TLS with Caddy

1. Networking Requirements

Please ensure the following ports are accessible on the server

  • 443 - primary HTTPS and TURN/TLS

  • 7881 - for WebRTC over TCP

  • 3478/UDP - for TURN/UDP

  • 50000-60000/UDP - for WebRTC over UDP

2. Configure TLS certificates for caddy

mkdir /opt/livekit/certs

Place certificates and configure caddy.yaml with cert locations and configure domains

3. Configure livekit.yaml

set turn domain, api key and api secret

Example generated script

#!/bin/sh
# generated by build_vm_init.sh
# This script will write all of your configurations to /opt/livekit.
# It'll also install LiveKit as a systemd service that will run at startup
# LiveKit will be started automatically at machine startup.

# create directories for LiveKit
mkdir -p /opt/livekit/caddy_data
mkdir -p /usr/local/bin

# Docker & Docker Compose will need to be installed on the machine
curl -fsSL https://get.docker.com -o /tmp/get-docker.sh
sh /tmp/get-docker.sh
curl -L "https://github.com/docker/compose/releases/download/v2.20.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod 755 /usr/local/bin/docker-compose

sudo systemctl enable docker

# docker-compose.yaml
cat << 'EOF' > /opt/livekit/docker-compose.yaml
# This docker-compose requires host networking, which is only available on Linux
# This compose will not function correctly on Mac or Windows
services:
 caddy:
   image: convaitech/caddyl4
   command: run --config /etc/caddy.yaml --adapter yaml
   restart: unless-stopped
   network_mode: "host"
   volumes:
     - ./caddy.yaml:/etc/caddy.yaml
     - ./caddy_data:/data
     - ./certs:/certs 
 livekit:
   image: convaitech/webrtc-server:v1.9.0
   command: --config /etc/livekit.yaml
   restart: unless-stopped
   network_mode: "host"
   volumes:
     - ./livekit.yaml:/etc/livekit.yaml
 redis:
   image: redis:7-alpine
   command: redis-server /etc/redis.conf
   restart: unless-stopped
   network_mode: "host"
   volumes:
     - ./redis.conf:/etc/redis.conf

EOF

# livekit config
cat << 'EOF' > /opt/livekit/livekit.yaml
port: 7880
bind_addresses:
   - ""
rtc:
   tcp_port: 7881
   port_range_start: 50000
   port_range_end: 60000
   use_external_ip: true
   enable_loopback_candidate: false
redis:
   address: localhost:6379
   username: ""
   password: ""
   db: 0
   use_tls: false
   sentinel_master_name: ""
   sentinel_username: ""
   sentinel_password: ""
   sentinel_addresses: []
   cluster_addresses: []
   max_redirects: null
turn:
   enabled: true
   domain: lk-vm-turn.convai.com
   tls_port: 5349
   udp_port: 3478
   external_tls: true
keys:
   APITqAGB9qhyLvV: yzIAelkGy24QcPcJVNh8WGkObHFFK5JJIz2pXku3lsE

EOF

# caddy config
cat << 'EOF' > /opt/livekit/caddy.yaml
logging:
 logs:
   default:
     level: INFO
storage:
 "module": "file_system"
 "root": "/data"
apps:
 tls:
   certificates:
     load_files:
       - certificate: "/certs/fullchain.pem"
         key: "/certs/privkey.pem"
       # - certificate: "/certs/lk-vm.convai.com.crt"
       #   key: "/certs/lk-vm.convai.com.key"
 layer4:
   servers:
     main:
       listen: [":443"]
       routes:
         - match:
           - tls:
               sni:
                 - "lk-vm-turn.convai.com"
           handle:
             - handler: tls
             - handler: proxy
               upstreams:
                 - dial: ["localhost:5349"]
         - match:
             - tls:
                 sni:
                   - "lk-vm.convai.com"
           handle:
             - handler: tls
               connection_policies:
                 - alpn: ["http/1.1"]
             - handler: proxy
               upstreams:
                 - dial: ["localhost:7880"]

EOF

# update ip script
cat << 'EOF' > /opt/livekit/update_ip.sh
#!/usr/bin/env bash
ip=`ip addr show |grep "inet " |grep -v 127.0.0. |head -1|cut -d" " -f6|cut -d/ -f1`
sed -i.orig -r "s/\\\"(.+)(\:5349)/\\\"$ip\2/" /opt/livekit/caddy.yaml


EOF

# redis config
cat << 'EOF' > /opt/livekit/redis.conf
bind 127.0.0.1 ::1
protected-mode yes
port 6379
timeout 0
tcp-keepalive 300

EOF

# systemd service file
cat << 'EOF' > /etc/systemd/system/livekit-docker.service
[Unit]
Description=LiveKit Server Container
After=docker.service
Requires=docker.service

[Service]
LimitNOFILE=500000
Restart=always
WorkingDirectory=/opt/livekit
# Shutdown container (if running) when unit is started
ExecStartPre=/usr/local/bin/docker-compose -f docker-compose.yaml down
ExecStart=/usr/local/bin/docker-compose -f docker-compose.yaml up
ExecStop=/usr/local/bin/docker-compose -f docker-compose.yaml down

[Install]
WantedBy=multi-user.target
EOF

# Make update_ip.sh executable and run it
chmod 755 /opt/livekit/update_ip.sh
/opt/livekit/update_ip.sh

# Enable and start the service
systemctl enable livekit-docker
systemctl start livekit-docker
cat /opt/livekit/livekit.yaml

NLB terminated TLS

  1. Configure livekit.yaml turn domain, api key and secret

  2. Networking Requirements Please ensure the following ports are accessible on the vm

  • 7880 - primary server - tcp

  • 5349 - TURN/TLS - tcp

  • 7881 - for WebRTC over TCP

  • 3478/UDP - for TURN/UDP

  • 50000-60000/UDP - for WebRTC over UDP

3. VM target groups:

  1. 7880:TCP

  2. 5349:TCP

4. Create NLBs

  1. NLB1- vm.example.com - Listening on TLS 443 - forward to 7880:TCP

  2. NLB2- vm-turn.example.com - Listening on TLS 443 - 5349:TCP

Example generated script

#!/bin/sh
# generated by build_vm_init.sh
# This script will write all of your configurations to /opt/livekit.
# It'll also install LiveKit as a systemd service that will run at startup
# LiveKit will be started automatically at machine startup.

# create directories for LiveKit
mkdir -p /opt/livekit
mkdir -p /usr/local/bin

# Docker & Docker Compose will need to be installed on the machine
curl -fsSL https://get.docker.com -o /tmp/get-docker.sh
sh /tmp/get-docker.sh
curl -L "https://github.com/docker/compose/releases/download/v2.20.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod 755 /usr/local/bin/docker-compose

sudo systemctl enable docker

# docker-compose.yaml
cat << 'EOF' > /opt/livekit/docker-compose.yaml
# This docker-compose requires host networking, which is only available on Linux
# This compose will not function correctly on Mac or Windows
services:
  livekit:
    image: convaitech/webrtc-server:v1.9.0
    command: --config /etc/livekit.yaml
    restart: unless-stopped
    network_mode: "host"
    volumes:
      - ./livekit.yaml:/etc/livekit.yaml
  redis:
    image: redis:7-alpine
    command: redis-server /etc/redis.conf
    restart: unless-stopped
    network_mode: "host"
    volumes:
      - ./redis.conf:/etc/redis.conf

EOF

# livekit config
cat << 'EOF' > /opt/livekit/livekit.yaml
port: 7880
bind_addresses:
    - ""
rtc:
    tcp_port: 7881
    port_range_start: 50000
    port_range_end: 60000
    use_external_ip: true
    enable_loopback_candidate: false
redis:
    address: localhost:6379
    username: ""
    password: ""
    db: 0
    use_tls: false
    sentinel_master_name: ""
    sentinel_username: ""
    sentinel_password: ""
    sentinel_addresses: []
    cluster_addresses: []
    max_redirects: null
turn:
    enabled: true
    domain: lk-vm-turn.convai.com
    tls_port: 5349
    udp_port: 3478
    external_tls: true
keys:
    APIfQ95orRbMckX: ebKy3EMXG6kYqjUSWXFMUkr4Ad64DAAyX5Oi2fAtpD9

EOF

# update ip script
cat << 'EOF' > /opt/livekit/update_ip.sh
#!/usr/bin/env bash
ip=`ip addr show |grep "inet " |grep -v 127.0.0. |head -1|cut -d" " -f6|cut -d/ -f1`
sed -i.orig -r "s/\\\"(.+)(\:5349)/\\\"$ip\2/" /opt/livekit/caddy.yaml


EOF

# redis config
cat << 'EOF' > /opt/livekit/redis.conf
bind 127.0.0.1 ::1
protected-mode yes
port 6379
timeout 0
tcp-keepalive 300

EOF

# systemd service file
cat << 'EOF' > /etc/systemd/system/livekit-docker.service
[Unit]
Description=LiveKit Server Container
After=docker.service
Requires=docker.service

[Service]
LimitNOFILE=500000
Restart=always
WorkingDirectory=/opt/livekit
# Shutdown container (if running) when unit is started
ExecStartPre=/usr/local/bin/docker-compose -f docker-compose.yaml down
ExecStart=/usr/local/bin/docker-compose -f docker-compose.yaml up
ExecStop=/usr/local/bin/docker-compose -f docker-compose.yaml down

[Install]
WantedBy=multi-user.target
EOF

# Make update_ip.sh executable and run it
chmod 755 /opt/livekit/update_ip.sh
/opt/livekit/update_ip.sh

# Enable and start the service
systemctl enable livekit-docker
systemctl start livekit-docker

WrbRTC Server

Once we have livekit setup completed, we can continue with the WebRTC Core service setup.

Image:

convaitech/onprem-webrtc-backend-service:latest

Environment Variable Setup

Create a .env file in your system. Lets assume a webrtc-server.env file exists at /var/secrets. Fill the file with the required configurations as specified by the team. Here is some sample data..

// webrtc-server.env
OPENAI_API_KEY=sk-svcacct-HZBr4Pko...
GEMINI_API_KEY=AIz...
CLAUDE_API_KEY=sk-ant-api03-X...

MEM0_API_KEY=m0-nrnOH...

DATABASE_URL=postgresql+asyncpg://convai_user:<passowrd>@localhost:5432/convai_db
REDIS_URL=redis://localhost:6379

...

LIVEKIT_URL=ws://localhost:7880
LIVEKIT_API_KEY=devkey
LIVEKIT_API_SECRET=secret

# App Config
ENABLE_ACTOR_POOLING=false
ENABLE_ROOM_POOLING=false
BOT_IMPLEMENTATION=openai
ENV=production
...

Container Deployment:

Run the following docker command to start the server:

$ sudo docker run --rm  \
--name core-service \
-p 8002:8000  \
-v "/home/convai/secrets/webrtc-secrets.env:/app/secrets/secrets.env:ro"  \
convaitech/onprem-webrtc-backend-service:latest  \
bash -lc "ray start --head && serve start --http-host 0.0.0.0 --http-port 8000 && serve run --route-prefix / server:api_server"

Last updated