Skip to main content

Deployment

Guide for deploying LLMRTC backend in production environments.


Architecture Overview

A production deployment typically includes:


Prerequisites

System Requirements

ComponentMinimumRecommended
CPU2 cores4+ cores
Memory2 GB4+ GB
Storage10 GB20+ GB SSD
Node.js20.x20.x LTS
FFmpegRequired for streaming TTSLatest stable

Network Requirements

PortProtocolPurpose
443TCPHTTPS/WSS
8787TCPBackend (internal)
3478UDP/TCPTURN server
10000-20000UDPWebRTC media (if direct)

Docker Deployment

Dockerfile

FROM node:20-slim

# Install FFmpeg for streaming TTS
RUN apt-get update && \
apt-get install -y --no-install-recommends ffmpeg && \
rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Install dependencies
COPY package*.json ./
RUN npm ci --only=production

# Copy application
COPY . .

# Non-root user
RUN useradd -r llmrtc && chown -R llmrtc:llmrtc /app
USER llmrtc

EXPOSE 8787

CMD ["npx", "llmrtc-backend"]

Docker Compose

version: '3.8'

services:
llmrtc:
build: .
ports:
- "8787:8787"
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- ELEVENLABS_API_KEY=${ELEVENLABS_API_KEY}
- PORT=8787
- HOST=0.0.0.0
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8787/health"]
interval: 30s
timeout: 10s
retries: 3

nginx:
image: nginx:alpine
ports:
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
depends_on:
- llmrtc
restart: unless-stopped

Process Managers

PM2

// ecosystem.config.js
module.exports = {
apps: [{
name: 'llmrtc',
script: 'npx',
args: 'llmrtc-backend',
instances: 'max', // Or specific number
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 8787
},
env_file: '.env',
max_memory_restart: '1G',
error_file: '/var/log/llmrtc/error.log',
out_file: '/var/log/llmrtc/out.log',
merge_logs: true,
time: true
}]
};
# Start
pm2 start ecosystem.config.js

# Monitor
pm2 monit

# Logs
pm2 logs llmrtc

# Restart on file changes (dev)
pm2 start ecosystem.config.js --watch

systemd

# /etc/systemd/system/llmrtc.service
[Unit]
Description=LLMRTC Voice AI Server
After=network.target

[Service]
Type=simple
User=llmrtc
Group=llmrtc
WorkingDirectory=/opt/llmrtc
EnvironmentFile=/opt/llmrtc/.env
ExecStart=/usr/bin/npx llmrtc-backend
Restart=always
RestartSec=10
StandardOutput=append:/var/log/llmrtc/output.log
StandardError=append:/var/log/llmrtc/error.log

# Security
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ReadWritePaths=/var/log/llmrtc

[Install]
WantedBy=multi-user.target
# Enable and start
systemctl enable llmrtc
systemctl start llmrtc

# Status
systemctl status llmrtc

# Logs
journalctl -u llmrtc -f

Reverse Proxy

NGINX

# /etc/nginx/sites-available/llmrtc
upstream llmrtc_backend {
server 127.0.0.1:8787;
keepalive 32;
}

server {
listen 80;
server_name voice.example.com;
return 301 https://$server_name$request_uri;
}

server {
listen 443 ssl http2;
server_name voice.example.com;

# SSL
ssl_certificate /etc/letsencrypt/live/voice.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/voice.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;

# WebSocket
location / {
proxy_pass http://llmrtc_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;

# Timeouts for long-lived connections
proxy_read_timeout 86400;
proxy_send_timeout 86400;
proxy_connect_timeout 60;

# Buffer settings
proxy_buffering off;
proxy_buffer_size 4k;
}

# Health check
location /health {
proxy_pass http://llmrtc_backend/health;
proxy_read_timeout 5s;
}
}

Caddy

voice.example.com {
reverse_proxy localhost:8787 {
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}

# WebSocket support
header_up Connection {http.request.header.Connection}
header_up Upgrade {http.request.header.Upgrade}

# Timeouts
transport http {
read_timeout 0
write_timeout 0
}
}

log {
output file /var/log/caddy/llmrtc.log
}
}

Load Balancing

Sticky Sessions

WebSocket connections need sticky sessions:

upstream llmrtc_backend {
ip_hash; # Sticky sessions by IP
server 127.0.0.1:8787;
server 127.0.0.2:8787;
server 127.0.0.3:8787;
}

Health Checks

upstream llmrtc_backend {
server 127.0.0.1:8787 max_fails=3 fail_timeout=30s;
server 127.0.0.2:8787 max_fails=3 fail_timeout=30s;
}

TURN Server

Metered.ca Integration

# Environment variables
METERED_APP_NAME=your-app
METERED_API_KEY=your-api-key
METERED_REGION=global # or specific region

Self-Hosted coturn

# /etc/turnserver.conf
listening-port=3478
tls-listening-port=5349
fingerprint
lt-cred-mech
use-auth-secret
static-auth-secret=your-secret-here
realm=voice.example.com
cert=/etc/letsencrypt/live/voice.example.com/fullchain.pem
pkey=/etc/letsencrypt/live/voice.example.com/privkey.pem
log-file=/var/log/turnserver/turn.log

Pass to LLMRTC:

const server = new LLMRTCServer({
iceServers: [
{ urls: 'stun:turn.example.com:3478' },
{
urls: 'turn:turn.example.com:3478',
username: generateUsername(),
credential: generateCredential()
}
]
});

Monitoring

Health Endpoint

# Basic health check
curl https://voice.example.com/health
# {"ok":true}

Prometheus Metrics

import { Registry, collectDefaultMetrics } from 'prom-client';

const register = new Registry();
collectDefaultMetrics({ register });

// Expose metrics endpoint
app.get('/metrics', async (_req, res) => {
res.set('Content-Type', register.contentType);
res.send(await register.metrics());
});

Log Aggregation

# Ship logs to centralized logging
journalctl -u llmrtc -f | fluent-bit -c /etc/fluent-bit/llmrtc.conf

Scaling

Horizontal Scaling

For session persistence across instances, use Redis:

import Redis from 'ioredis';

const redis = new Redis(process.env.REDIS_URL);

// Store session state
server.on('connection', async ({ id }) => {
await redis.hset(`session:${id}`, 'server', process.env.INSTANCE_ID);
});

Vertical Scaling

Concurrent UsersRecommended Specs
10-502 CPU, 4GB RAM
50-2004 CPU, 8GB RAM
200-5008 CPU, 16GB RAM
500+Multiple instances

Kubernetes

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: llmrtc
spec:
replicas: 3
selector:
matchLabels:
app: llmrtc
template:
metadata:
labels:
app: llmrtc
spec:
containers:
- name: llmrtc
image: your-registry/llmrtc:latest
ports:
- containerPort: 8787
envFrom:
- secretRef:
name: llmrtc-secrets
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health
port: 8787
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8787
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: llmrtc
spec:
selector:
app: llmrtc
ports:
- port: 8787
targetPort: 8787
sessionAffinity: ClientIP # Sticky sessions