Skip to the content.
← Back to Home Documentation Index

Deployment Guide

This guide covers deploying the WebRTC project in production environments using Docker Compose with HTTPS and TURN server support.


Table of Contents


Quick Start

Deploy all services with a single command:

1
2
3
4
5
6
7
8
9
10
11
12
# Clone repository
git clone https://github.com/LessUp/webrtc.git
cd webrtc

# Set your domain
export DOMAIN=your-domain.com

# Start all services
docker compose up -d

# View logs
docker compose logs -f

Visit https://your-domain.com and start calling!


Architecture

The deployment consists of three services:

Service Purpose Exposed Ports
webrtc Go signaling server + static frontend 8080 (internal)
caddy HTTPS reverse proxy with auto TLS 80, 443
coturn TURN/STUN server for NAT traversal 3478, 5349
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
                    ┌─────────────┐
                    │   Client    │
                    └──────┬──────┘
                           │ HTTPS (443)
                    ┌──────▼──────┐
                    │    Caddy    │ ← Let's Encrypt auto TLS
                    └──────┬──────┘
                           │ HTTP (8080)
                    ┌──────▼──────┐
                    │   webrtc    │ ← Go server + frontend
                    └──────┬──────┘
                           │ WebSocket
                    ┌──────▼──────┐
                    │    coturn   │ ← TURN/STUN (3478)
                    └─────────────┘

Docker Compose Deployment

Prerequisites

Step 1: Configure Environment

Create environment file:

1
2
3
4
# .env file
DOMAIN=your-domain.com
WS_ALLOWED_ORIGINS=your-domain.com
RTC_CONFIG_JSON={"iceServers":[{"urls":"turn:your-domain.com:3478","username":"webrtc","credential":"your-secure-password"}]}

Step 2: Configure TURN Server

Copy and edit TURN configuration:

1
cp turnserver.conf.example turnserver.conf

Edit turnserver.conf:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# TURN server configuration
listening-port=3478
listening-ip=0.0.0.0
relay-ip=YOUR_SERVER_IP
external-ip=YOUR_SERVER_IP/YOUR_SERVER_IP

# Authentication
user=webrtc:your-secure-password
realm=your-domain.com

# Security
no-cli
no-tlsv1
no-tlsv1_1

⚠️ Security Note: turnserver.conf is in .gitignore to prevent credential leaks.

Step 3: Launch Services

1
2
3
4
5
6
7
8
9
10
11
# Start all services
docker compose up -d

# Check status
docker compose ps

# View logs
docker compose logs -f

# Stop all services
docker compose down

Step 4: Verify Deployment

1
2
3
4
5
6
7
8
9
# Test HTTPS endpoint
curl -I https://your-domain.com

# Test health check
curl https://your-domain.com/healthz

# Test WebSocket (using wscat)
npm install -g wscat
wscat -c wss://your-domain.com/ws

Local Development

For local development without HTTPS or TURN:

Option 1: Direct Go Run

1
2
go run ./cmd/server
# Open http://localhost:8080

Option 2: Docker (webrtc only)

1
2
docker compose up -d webrtc
# Open http://localhost:8080

Development with Hot Reload

1
2
3
4
5
# Install air (live reload for Go)
go install github.com/air-verse/air@latest

# Run with hot reload
air

Configuration Reference

Environment Variables

Variable Service Default Description
DOMAIN caddy localhost Domain for HTTPS certificate
ADDR webrtc :8080 HTTP listen address
WS_ALLOWED_ORIGINS webrtc * Allowed WebSocket origins
RTC_CONFIG_JSON webrtc Public STUN ICE/TURN server configuration

ICE/TURN Configuration Format

1
2
3
4
5
6
7
8
9
10
11
12
{
  "iceServers": [
    {
      "urls": ["stun:stun.l.google.com:19302"]
    },
    {
      "urls": ["turn:your-domain.com:3478"],
      "username": "webrtc",
      "credential": "your-password"
    }
  ]
}

Port Reference

Port Protocol Service Purpose
80 TCP caddy HTTP (redirects to HTTPS)
443 TCP/UDP caddy HTTPS
8080 TCP webrtc Direct access (development)
3478 TCP/UDP coturn TURN/STUN
5349 TCP/UDP coturn TURN/TLS
10000-20000 UDP coturn Relay ports (dynamic)

Production Checklist

Before going live, verify:

Security

Performance

Reliability

DNS & SSL


Troubleshooting

Issue: HTTPS not working

Symptoms: Browser shows “Not Secure” or can’t connect

Solutions:

  1. Check DNS propagation: dig your-domain.com
  2. Verify port 80 is open for Let’s Encrypt
  3. Check Caddy logs: docker compose logs caddy
  4. Ensure DOMAIN environment variable is set correctly

Issue: WebSocket connection fails

Symptoms: “Connection failed” in browser console

Solutions:

  1. Check WS_ALLOWED_ORIGINS includes your domain
  2. Verify firewall allows port 443
  3. Check webrtc logs: docker compose logs webrtc
  4. Test with browser dev tools Network tab

Issue: No video/audio in calls

Symptoms: Black video, no sound

Solutions:

  1. Check browser camera/microphone permissions
  2. Verify TURN server is running: docker compose ps coturn
  3. Check TURN credentials in RTC_CONFIG_JSON
  4. Test TURN connectivity with Trickle ICE
  5. Check coturn logs: docker compose logs coturn

Issue: High CPU/memory usage

Symptoms: Server becomes unresponsive

Solutions:

  1. Check for goroutine leaks: Review hub.go cleanup sequence
  2. Monitor room/client limits: Max 1000 rooms, 50 clients/room
  3. Check for memory leaks in browser (F12 → Memory tab)
  4. Consider using SFU instead of Mesh for large rooms

Advanced Topics

Scaling with Load Balancer

For high availability, deploy multiple webrtc instances behind a load balancer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# docker-compose.scale.yml
services:
  webrtc-1:
    build: .
    environment:
      - ADDR=:8080
  
  webrtc-2:
    build: .
    environment:
      - ADDR=:8080
  
  nginx:
    image: nginx:alpine
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    ports:
      - "8080:80"

Note: WebSocket connections are stateful; use sticky sessions or shared hub backend.

Custom TURN Server

If using external TURN server (e.g., Twilio, Xirsys):

1
2
3
4
5
6
7
8
9
export RTC_CONFIG_JSON='{
  "iceServers": [
    {
      "urls": "turn:global.turn.twilio.com:3478?transport=udp",
      "username": "your-twilio-username",
      "credential": "your-twilio-password"
    }
  ]
}'