No description
  • JavaScript 88.7%
  • CSS 8.3%
  • HTML 2.1%
  • Dockerfile 0.9%
Find a file
Pavel Oborin 69326ea235 Rewrite e2e tests to use per-test server instances via Playwright fixtures
Each test now spins up its own HTTP+WebSocket server on a random port,
providing full isolation between tests. Shared helpers (connectUser,
waitForConnect) moved to a custom fixture in e2e/fixtures.js.

Also fixes waitForConnect (was waiting for a nonexistent console message,
now waits for #peers article.self DOM element) and exposes
window.localStream via getUserMedia interception for mute tests.

Removes debug console.log from signaling server.
2026-05-08 00:51:59 +03:00
e2e Rewrite e2e tests to use per-test server instances via Playwright fixtures 2026-05-08 00:51:59 +03:00
frontend Manual refactoring 2026-05-08 00:27:59 +03:00
plans Style cleanup: semicolons, mute boolean, remove debug logs and dead code 2026-05-07 22:13:45 +03:00
signaling Rewrite e2e tests to use per-test server instances via Playwright fixtures 2026-05-08 00:51:59 +03:00
specs Manual refactoring 2026-05-08 00:27:59 +03:00
.env.prod Add coturn TURN server to production with HMAC credential generation 2026-05-06 15:30:05 +03:00
.gitignore Manual refactoring 2026-05-08 00:27:59 +03:00
AGENTS.md Manual refactoring 2026-05-08 00:27:59 +03:00
Caddyfile Replace nginx with Caddy reverse proxy 2026-05-05 01:23:48 +03:00
docker-compose.prod.yml Fix coturn config warnings, cert permissions, and logging 2026-05-06 15:37:26 +03:00
docker-compose.yml Replace nginx with Caddy reverse proxy 2026-05-05 01:23:48 +03:00
README.md Add coturn TURN server to production with HMAC credential generation 2026-05-06 15:30:05 +03:00
turnserver.conf Fix coturn config warnings, cert permissions, and logging 2026-05-06 15:37:26 +03:00

Concord

WebRTC voice/video/screen-sharing chat. Static frontend + Node.js WebSocket signaling server + Caddy reverse proxy + Coturn TURN server.

Development

docker compose up

Caddy serves the frontend on http://localhost:8080 and proxies /ws/ to the signaling server. The signaling server runs with nodemon and auto-restarts on changes. No TURN server in dev — the client falls back to Google's public STUN.

Signaling server only

cd signaling
npm install
npm run dev

Tests

cd signaling && npm test          # integration tests
cd e2e && npm test                # E2E tests (Playwright)

Production deployment

Prerequisites

  • A server with Docker and Docker Compose
  • A public domain name pointing to the server's IP address
  • Open firewall ports: 80/tcp, 443/tcp, 3478/tcp, 3478/udp, 5349/tcp, 5349/udp, 49152-65535/udp

Setup

  1. Copy the example env file:
cp .env.prod .env
  1. Edit .env and set your values:
COMPOSE_FILE=docker-compose.prod.yml
DOMAIN=chat.example.com
HTTP_PORT=80
HTTPS_PORT=443
TURN_SECRET=<your-secret>
  1. Generate a strong TURN secret:
openssl rand -base64 32

Use the output as TURN_SECRET.

  1. Start the stack:
docker compose up -d

Caddy automatically provisions TLS certificates via Let's Encrypt for your domain. The coturn server discovers those certificates from Caddy's shared data volume and uses them for TURNS (TLS) on port 5349. If TLS certs are not yet provisioned, coturn starts without TLS — TURN over UDP/TCP on port 3478 still works.

How it works

  • Caddy serves the static frontend, proxies WebSocket connections to the signaling server, and auto-provisions TLS
  • Signaling server manages peer connections, relays WebRTC signaling messages, and generates time-limited TURN credentials (HMAC-SHA1, 24h expiry) sent in the welcome message
  • Coturn provides STUN/TURN relay for WebRTC when direct peer connections are blocked by NATs/firewalls — uses the same TURN_SECRET to validate credentials
  • Frontend uses the ICE servers from the signaling server's welcome message to configure WebRTC peer connections

Architecture

Client ──HTTPS/WSS──▶ Caddy ──WS──▶ Signaling Server
   │                                       │
   │  ◀── welcome + ICE servers ──────────┘
   │
   ├── STUN/TURN (UDP 3478) ──▶ Coturn
   └── TURNS   (TCP 5349) ──▶ Coturn