A self-hosted Peerweave reference app with authenticated signaling, room authorization and short-lived TURN credentials.
Four browser examples, an application-owned backend, and standalone Traefik/Coturn deployment projects show how to take Peerweave beyond localhost. The source is MIT licensed; the deployed application uses private, operator-managed access.
Quick start · Architecture · Deployment guide · Security · Contributing
A browser framework and a deployed calling application have different responsibilities. This repo demonstrates the application work around WebRTC: identifying users, authorizing rooms, issuing expiring ICE credentials, routing WSS, operating TURN and checking the real packet path.
The framework repo owns library APIs, native contracts and one minimal vanilla video sample. This repo owns the richer app, operational policy, container images and infrastructure. The framework keeps one small vanilla TypeScript video example. This app consumes packaged public APIs and can build without a sibling framework checkout.
| Component | Responsibility |
|---|---|
apps/web |
Four Gyral 0.3.6 pages: calls/chat, media preflight, accepted file transfers and support invitations |
apps/server |
Trusted proxy identity, explicit room membership, authorized ICE leases and two-member signaling |
compose.yaml |
Prebuilt static-web and backend images; no published app ports |
compose.traefik.yaml |
HTTPS/WSS, ACME state, private BasicAuth and restricted Docker discovery |
compose.turn.yaml |
Authenticated Coturn, TLS, relay restrictions and allocation/bandwidth limits |
vendor/peerweave |
Reviewed private package archives with checksums and source provenance |
tools, tests, docs |
Isolated checks, image builds, plans, architecture and operating guidance |
This is a single-host, private-access reference. It does not include public signup, room discovery, recording, SFU conferencing or durable sessions. Review the product scope and measured quality; local tests do not establish public reachability.
Use Node 24+ and the pnpm version pinned in package.json:
git clone https://github.com/peerweavejs/peerweave-deployment-example.git
cd peerweave-deployment-example
pnpm install --frozen-lockfile
pnpm exec playwright install --with-deps chromium
pnpm devOpen http://127.0.0.1:5173 in two tabs and use room hello. Join both, then start the call in
each tab. The other pages are /media/, /transfer/ and /support/. Development is explicitly
loopback-only, with one local identity and direct-only ICE when no TURN fixture is configured.
Production mode requires real identity, membership and TURN configuration; it never silently
falls back to development access. See development.
flowchart LR
Browser[Browser participants] -->|HTTPS and WSS| Edge[Traefik: authentication and TLS]
Edge --> Web[Static web app]
Edge --> Backend[Backend: rooms, ICE and signaling]
Backend -. signs temporary credentials .-> Turn[Coturn]
Browser <-->|Direct WebRTC when reachable| Peer[Remote participant]
Browser <-->|Encrypted TURN relay path| Turn
Turn <-->|UDP relay endpoints| Peer
- Traefik authenticates the HTTP request and supplies verified identity to the unpublished backend.
- The backend authorizes the requested room and returns a short-lived ICE lease without its shared secret.
- The browser validates the lease, then joins that room over same-origin WSS.
- ICE selects a working direct or relay path; signaling does not carry media/file contents.
- Leaving cancels pending setup and disposes owned resources. Session expiry requires rejoining.
Rooms and rate limits live in one backend process. The architecture, security boundary and reliability contract explain the limits.
Follow the ordered production guide for DNS, firewall/NAT rules, private file permissions, certificates, membership, startup, verification and renewal. Start with:
cp .env.example .env
cp .env.traefik.example .env.traefik
cp .env.turn.example .env.turnEdit these files and provision their private files before starting containers:
| Configuration | Key values |
|---|---|
App .env |
Public hostname, image tag, shared network, room-policy file, backend secret copy and public TURN URLs |
Traefik .env.traefik |
Shared Docker network, Docker socket path and bcrypt user-file path |
Coturn .env.turn |
TURN hostname, public/local relay IPv4, certificate directory, secret file and quotas |
| Room policy | Exact usernames per room; the template includes hello, support-hello and files-hello |
All three Compose projects deploy images only. The shell script builds app images separately; the image guide covers registry transfer and updates.
./tools/build-images.sh
# After completing the guide's bootstrap and private-file configuration:
docker compose --env-file .env.traefik -f compose.traefik.yaml up -d --wait
docker compose --env-file .env.turn -f compose.turn.yaml up -d --wait
docker compose up -d --waitOn one public IP, Traefik owns TCP 80/443; Coturn uses UDP/TCP 3478, TCP 5349 and a bounded UDP relay range. Optional SNI passthrough shares TCP 443 with TURN/TLS. A TURN hostname must have a native DNS/network path; a normal HTTP tunnel does not carry its UDP relay traffic.
pnpm exec playwright install --with-deps chromium firefox webkit
pnpm build # Compile the web app and backend
pnpm check # Lint, boundaries, types, coverage, browser regressions and native app smoke
pnpm build:images # Build the two runtime images
pnpm test:deployment # Linux/Docker: actual authenticated Traefik HTTPS/WSS
pnpm test:turn:deployment # Linux/Docker: UDP/TCP/TLS, SNI and relay-only app trafficThe tests verify denied credentials/rooms, native video/chat/hangup, exact file bytes and selected relay candidates. TURN checks exercise invalid/expired auth, blocked peers, TLS and ICE restart. Fixtures clean up their temporary Docker resources. Read testing and the quality record for coverage scope, screenshots and external acceptance gaps.
The framework packages are unpublished previews. This repo includes versioned archives so a fresh clone remains reproducible. The manifest records their source and SHA-256 hashes.
pnpm vendor:peerweave /absolute/path/to/peerweave
pnpm install --frozen-lockfile
pnpm checkThe update command requires clean framework package sources, builds/packs public exports and updates dependency versions, overrides and the lockfile. Review that diff explicitly. Normal install/build never imports framework sources; npm publication remains a separate framework release decision.
Keep production auth and room policy in this app, import installed Peerweave exports, keep secrets
outside images/logs, and let disposable controllers own browser resources. UI models remain pure.
Use behavior-first tests, preserve regressions, and record decisions/results in versioned docs.
The short AGENTS.md, design index and plans
provide the harness navigation map.
Read CONTRIBUTING.md, follow the code of conduct, and use GitHub Issues for non-sensitive bugs and proposals. Report vulnerabilities privately using SECURITY.md.
Application source and vendored Peerweave packages are MIT licensed. Fonts retain their OFL notices; external references and dependency licenses retain their owners' terms. See third-party notices.