<div align="center>
PeerWave
Self-hosted, end-to-end encrypted communication platformMessaging, file sharing, and real-time meetings built on WebRTC, Signal Protocol, and zero-trust principles.
<div align="center>
PeerWave is a self-hosted communication platform designed around a zero-trust model.
All sensitive data is encrypted on the client before transmission and is never accessible to the server.
PeerWave uses the following core technologies:
The server is responsible only for:
At no point does the server have access to plaintext messages, files, media streams, or encryption keys.
New to PeerWave? Choose your deployment:
Files you'll need:
docker-compose.yml or docker-compose.traefik.yml - Container orchestration.env - Your configuration (secrets, domain, etc.)livekit-config.yaml - Video server settingsnginx-livekit.conf - Proxy config (Traefik deployment only)Choose the deployment method that fits your needs:
| Method | Use Case | Complexity | Source |
|---|---|---|---|
| Docker Compose (Simple) | Local dev, small deployments | ⭐ Easy | Docker Hub |
| Docker Compose + Traefik | Production with SSL | ⭐⭐ Medium | Docker Hub |
| Manual Build | Custom modifications | ⭐⭐⭐ Advanced | Source Code |
Perfect for local development or simple deployments without reverse proxy. Uses pre-built images from Docker Hub.
# 1. Download configuration files (recommended)
# Download only what you need:
# - docker-compose.yml
# - docker-compose.traefik.yml (if using Traefik)
# - server/.env.example or .env.traefik.example
#
# You can use:
# wget https://raw.githubusercontent.com/simonzander/PeerWave/main/docker-compose.yml
# wget https://raw.githubusercontent.com/simonzander/PeerWave/main/docker-compose.traefik.yml
# wget https://raw.githubusercontent.com/simonzander/PeerWave/main/server/.env.example
# wget https://raw.githubusercontent.com/simonzander/PeerWave/main/.env.traefik.example
#
# Or download from GitHub web UI.
#
# For developers: clone the repo if you want to build or modify the source.
# 2. Copy environment template
cp server/.env.example server/.env
# 3. Edit configuration - CHANGE THE SECRETS!
nano server/.env
# Required: SESSION_SECRET, LIVEKIT_API_KEY, LIVEKIT_API_SECRET
# 4. Start all services (images pulled from Docker Hub)
docker-compose up -d
# 5. View logs
docker-compose logs -f peerwave-server
✅ Images: Automatically pulled from Docker Hub (no build needed!)
✅ Certificates:
turn-cert.pem and turn-key.pem in ./livekit-certs/ and restartAccess PeerWave: http://localhost:3000
Best for production deployments with automatic HTTPS via Let's Encrypt. Uses pre-built images from Docker Hub.
docker network create proxy# 1. Download configuration files (recommended)
# Download only what you need:
# - docker-compose.traefik.yml
# - .env.traefik.example
# - livekit-config.yaml (if customizing TURN domain)
# - nginx-livekit.conf.example (rename to nginx-livekit.conf)
#
# You can use:
# wget https://raw.githubusercontent.com/simonzander/PeerWave/main/docker-compose.traefik.yml
# wget https://raw.githubusercontent.com/simonzander/PeerWave/main/.env.traefik.example
# wget https://raw.githubusercontent.com/simonzander/PeerWave/main/livekit-config.yaml
# wget https://raw.githubusercontent.com/simonzander/PeerWave/main/nginx-livekit.conf.example
#
# Or download from GitHub web UI.
#
# For developers: clone the repo if you want to build or modify the source.
# 2. Copy Traefik environment template
cp .env.traefik.example .env
# 3. Copy nginx proxy configuration
cp nginx-livekit.conf.example nginx-livekit.conf
# 3. Copy nginx proxy configuration
cp nginx-livekit.conf.example nginx-livekit.conf
# 4. Edit configuration
nano .env
Required variables:
DOMAIN=app.yourdomain.com
HTTPS=true
LIVEKIT_TURN_DOMAIN=app.yourdomain.com
TRAEFIK_ACME_PATH=/etc/traefik/acme.json # Your Traefik's acme.json path
LIVEKIT_CONFIG_PATH=/data/compose/25/livekit-config.yaml # Absolute path
NGINX_LIVEKIT_CONFIG_PATH=/data/compose/25/nginx-livekit.conf # Absolute path
SESSION_SECRET=$(openssl rand -base64 32)
LIVEKIT_API_KEY=$(openssl rand -base64 32)
LIVEKIT_API_SECRET=$(openssl rand -base64 32)
# 5. Update livekit-config.yaml with your domain and API keys
nano livekit-config.yaml
# Set: turn.domain: app.yourdomain.com
# Set: keys section with your LIVEKIT_API_KEY: LIVEKIT_API_SECRET
# 6. Verify nginx-livekit.conf (usually no changes needed)
# Should have: proxy_pass http://172.17.0.1:7880;
# 7. Start services (images pulled from Docker Hub, certs extracted automatically!)
docker-compose -f docker-compose.traefik.yml up -d
# 8. View logs
docker-compose -f docker-compose.traefik.yml logs -f
✅ Images: Automatically pulled from Docker Hub (no build needed!)
✅ Certificates: Auto-extracted from Traefik's acme.json (no manual setup needed!)
Access PeerWave: https://app.yourdomain.com
For developers who want to customize PeerWave or contribute to development.
# 1. Clone repository
git clone https://github.com/simonzander/PeerWave.git
cd PeerWave
# 2. Build Flutter web client
cd client
flutter build web --release
cp -r build/web ../server/web
# 3. Build Docker image
cd ../server
docker build -t peerwave-custom:latest .
# 4. Update docker-compose.yml to use your custom image
# Change: image: simonzander/peerwave:latest
# To: image: peerwave-custom:latest
# 5. Configure and start
cp .env.example .env
nano .env # Set your secrets
cd ..
docker-compose up -d
📦 Build Script: Use the provided build script for easier building:
# Linux/macOS
chmod +x build-docker.sh
./build-docker.sh v1.0.0
# Windows PowerShell
.\build-docker.ps1 v1.0.0
# Build and push to Docker Hub
./build-docker.sh v1.0.0 --push
Access PeerWave: http://localhost:3000
| Variable | Description | Required | Example |
|---|---|---|---|
DOMAIN |
Your domain | ✅ Traefik | app.yourdomain.com |
HTTPS |
Enable HTTPS/secure cookies | ✅ Traefik | true |
SESSION_SECRET |
Session encryption key | ✅ Yes | $(openssl rand -base64 32) |
LIVEKIT_API_KEY |
LiveKit API key | ✅ Yes | $(openssl rand -base64 32) |
LIVEKIT_API_SECRET |
LiveKit API secret | ✅ Yes | $(openssl rand -base64 32) |
LIVEKIT_TURN_DOMAIN |
Your domain for TURN | ✅ Prod | app.yourdomain.com |
TRAEFIK_ACME_PATH |
Path to Traefik's acme.json | ✅ Traefik | /etc/traefik/acme.json |
LIVEKIT_CONFIG_PATH |
Path to livekit-config.yaml | ✅ Traefik | /data/compose/25/livekit-config.yaml |
NGINX_LIVEKIT_CONFIG_PATH |
Path to nginx-livekit.conf | ✅ Traefik | /data/compose/25/nginx-livekit.conf |
| Variable | Description | Default | Example |
|---|---|---|---|
PORT |
Server port | 3000 |
4000 |
NODE_ENV |
Environment | production |
development |
APP_URL |
Base application URL | http://localhost:3000 |
https://app.yourdomain.com |
HTTPS |
Enable secure cookies | false |
true |
EMAIL_HOST |
SMTP server (optional) | - | smtp.gmail.com |
EMAIL_PORT |
SMTP port | 587 |
587 |
EMAIL_SECURE |
Use SSL/TLS | false |
true |
EMAIL_USER |
SMTP username | - | [email protected] |
EMAIL_PASS |
SMTP password | - | your-app-password |
EMAIL_FROM |
From address | no-reply@domain |
"PeerWave" <[email protected]> |
ADMIN_EMAILS |
Comma-separated admin emails | - | [email protected],[email protected] |
CLEANUP_INACTIVE_USER_DAYS |
Days until user marked inactive | 30 |
60 |
CLEANUP_SYSTEM_MESSAGES_DAYS |
System message retention | 1 |
3 |
CLEANUP_REGULAR_MESSAGES_DAYS |
Regular message retention | 7 |
14 |
CLEANUP_GROUP_MESSAGES_DAYS |
Group message retention | 7 |
30 |
CLEANUP_CRON_SCHEDULE |
Cleanup cron schedule | 0 2 * * * |
0 3 * * * |
CORS_ORIGINS |
Allowed origins | Auto | https://app.yourdomain.com |
server/.env (Simple deployment):
# Required
SESSION_SECRET=your-long-random-string-here
LIVEKIT_API_KEY=your-livekit-key
LIVEKIT_API_SECRET=your-livekit-secret
# Optional - Email (for meeting invitations)
EMAIL_HOST=smtp.gmail.com
EMAIL_PORT=587
EMAIL_SECURE=true
[email protected]
EMAIL_PASS=your-app-password
EMAIL_FROM="PeerWave" <[email protected]>
# Optional - Admin users
[email protected],[email protected]
.env (Traefik deployment):
# Required
DOMAIN=app.yourdomain.com
LIVEKIT_TURN_DOMAIN=app.yourdomain.com
TRAEFIK_ACME_PATH=/etc/traefik/acme.json
LIVEKIT_CONFIG_PATH=/data/compose/25/livekit-config.yaml
NGINX_LIVEKIT_CONFIG_PATH=/data/compose/25/nginx-livekit.conf
SESSION_SECRET=your-long-random-string
LIVEKIT_API_KEY=your-key
LIVEKIT_API_SECRET=your-secret
# Production settings
NODE_ENV=production
HTTPS=true
APP_URL=https://app.yourdomain.com
# Optional - Email (for meeting invitations)
EMAIL_HOST=smtp.gmail.com
EMAIL_PORT=587
EMAIL_SECURE=true
[email protected]
EMAIL_PASS=your-app-password
EMAIL_FROM="PeerWave" <[email protected]>
# Optional - Admin users
[email protected]
# Linux/macOS
openssl rand -base64 32
# Windows PowerShell
[Convert]::ToBase64String([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32))
Important: The LIVEKIT_API_KEY and LIVEKIT_API_SECRET in your .env file must match the keys in livekit-config.yaml:
# livekit-config.yaml
keys:
your-api-key-here: your-api-secret-here
Both must use the same values for authentication to work.
Download pre-built native clients from GitHub Releases:
.exe installer or portable .zip.apk.dmg installer (coming soon)Windows:
cd client
flutter build windows --release
Android:
cd client
flutter build apk --release --split-per-abi
See ANDROID_BUILD.md for detailed Android build instructions.
macOS:
flutter build macos --release
Linux:
flutter build linux --release
SESSION_SECRET (min 32 chars): openssl rand -base64 32LIVEKIT_API_KEY: openssl rand -base64 32LIVEKIT_API_SECRET: openssl rand -base64 32devkey or secret in productionNODE_ENV=productionLIVEKIT_TURN_DOMAIN with your domainCORS_ORIGINS for your domain(s)livekit-config.yaml port ranges| Port | Protocol | Service | Purpose |
|---|---|---|---|
| 3000 | TCP | Web/API Server | Main application |
| 7880 | TCP | LiveKit WebSocket | WebRTC signaling |
| 7881 | TCP | LiveKit HTTP API | Internal API |
| 443 | UDP | TURN/UDP (QUIC) | P2P NAT traversal |
| 5349 | TCP/UDP | TURN/TLS | Firewall-friendly P2P |
| 30100-30200 | UDP | RTP Media | WebRTC audio/video |
| 30300-30400 | UDP | TURN Relay | P2P relay ports |
| Port | Protocol | Service | Purpose | Notes |
|---|---|---|---|---|
| 80 | TCP | HTTP | Redirect to HTTPS | Traefik managed |
| 443 | TCP | HTTPS | Web/API Server | Traefik managed |
| 7880 | TCP | LiveKit WS | WebRTC signaling | Via nginx proxy |
| 443 | UDP | TURN/UDP | P2P traversal | Direct to LiveKit |
| 5349 | TCP/UDP | TURN/TLS | Firewall-friendly | Direct to LiveKit |
| 30100-30200 | UDP | RTP Media | WebRTC streams | Direct to LiveKit |
| 30300-30400 | UDP | TURN Relay | P2P relay | Direct to LiveKit |
Architecture Notes:
VPS Compatibility: If your VPS doesn't support bridge networking with UDP ports, this configuration uses host networking for LiveKit while keeping other services on bridge networks.
For common issues and solutions, see TROUBLESHOOTING.md.
VPS-Specific Issues:
172.17.0.1:7880host.docker.internal doesn't work on Linux → Use Docker bridge gateway IPQuick diagnostics:
# Check all services are running
docker-compose ps
# View logs
docker-compose logs --tail=50
# Test connectivity
curl -I http://localhost:3000
PeerWave is free and open source software licensed under AGPL-3.0.
For pricing and subscription details, visit: https://peerwave.org
Contact for support inquiries:
📧 [email protected]
⚠️ Note: Versions up to v0.x were licensed under MIT. Current version uses AGPL-3.0.
This project is licensed under the GNU Affero General Public License v3.0
See LICENSE for full details.
"PeerWave" is a trademark of PeerWave Labs (Simon Zander). Use of the AGPL-3.0 licensed code does not grant trademark rights. Modified versions must be rebranded.