{"id":38052848,"url":"https://github.com/simonzander/peerwave","last_synced_at":"2026-02-20T21:26:51.795Z","repository":{"id":243192261,"uuid":"811734467","full_name":"simonzander/PeerWave","owner":"simonzander","description":"WebRTC share peer to peer to peer","archived":false,"fork":false,"pushed_at":"2026-02-13T20:05:44.000Z","size":32306,"stargazers_count":17,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-02-13T23:26:54.385Z","etag":null,"topics":["android-app","chat","filesharing","livekit","meeting","meetings","message","messaging","nodejs","signal","socket","socket-io","stun","video-streaming","webrtc","webrtc-audio","webrtc-video","windows-app"],"latest_commit_sha":null,"homepage":"https://peerwave.org","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simonzander.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":"CLA.md"}},"created_at":"2024-06-07T07:36:46.000Z","updated_at":"2026-02-13T20:05:41.000Z","dependencies_parsed_at":"2024-06-19T21:03:11.364Z","dependency_job_id":"3e355414-e271-40f2-89d8-054baefdb596","html_url":"https://github.com/simonzander/PeerWave","commit_stats":null,"previous_names":["simonzander/peerwave"],"tags_count":61,"template":false,"template_full_name":null,"purl":"pkg:github/simonzander/PeerWave","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonzander%2FPeerWave","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonzander%2FPeerWave/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonzander%2FPeerWave/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonzander%2FPeerWave/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simonzander","download_url":"https://codeload.github.com/simonzander/PeerWave/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonzander%2FPeerWave/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29487772,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-15T19:29:10.908Z","status":"ssl_error","status_checked_at":"2026-02-15T19:29:10.419Z","response_time":118,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android-app","chat","filesharing","livekit","meeting","meetings","message","messaging","nodejs","signal","socket","socket-io","stun","video-streaming","webrtc","webrtc-audio","webrtc-video","windows-app"],"created_at":"2026-01-16T20:15:14.375Z","updated_at":"2026-02-15T20:00:59.860Z","avatar_url":"https://github.com/simonzander.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\u003e\n  \u003cimg src=\"https://github.com/simonzander/PeerWave/blob/main/client/assets/images/peerwave.png?raw=true\" height=\"100px\" width=\"100px\"\u003e\n  \u003ch1\u003e\n  PeerWave\u003c/h1\u003e\n  \u003cstrong\u003e\n    Self-hosted, end-to-end encrypted communication platform\n  \u003c/strong\u003e\n  \u003cbr\u003e\n  \u003cspan\u003e\n    Messaging, file sharing, and real-time meetings built on WebRTC, Signal Protocol, and zero-trust principles.\n  \u003c/span\u003e\n\u003c/div\u003e\n\u003cbr\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/simonzander/PeerWave/actions/workflows/release.yml\"\u003e\n    \u003cimg src=\"https://github.com/simonzander/PeerWave/actions/workflows/release.yml/badge.svg\" alt=\"Build Status\"\u003e\n  \u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/github/last-commit/simonzander/peerwave\" alt=\"GitHub last commit\"\u003e\n  \u003ca href=\"https://github.com/simonzander/PeerWave/issues?q=is:issue+is:open+label:bug\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/issues-search?query=https%3A%2F%2Fgithub.com%2Fsimonzander%2FPeerWave%2Fissues%3Fq%3Dis%3Aissue%2Bis%3Aopen%2Blabel%3Abug\u0026label=ISSUES\u0026color=red\" alt=\"GitHub issues\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n![License: AGPL-3.0](https://img.shields.io/badge/license-AGPL--3.0-blue.svg)\n![Open Source](https://img.shields.io/badge/Open%20Source-Free%20Forever-green.svg)\n![Support Available](https://img.shields.io/badge/Professional%20Support-Available-orange)\n\n## How it works\n\nPeerWave is a self-hosted communication platform designed around a zero-trust model.  \nAll sensitive data is encrypted on the client before transmission and is never accessible to the server.\n\nPeerWave uses the following core technologies:\n\n- **Signal Protocol** for end-to-end encrypted messaging and key exchange\n- **WebRTC** for peer-to-peer audio, video, and data transport\n- **WebAuthn (Passkeys)** for passwordless authentication\n- **Ephemeral session keys** for media encryption during calls and meetings\n\nThe server is responsible only for:\n- user and channel metadata\n- encrypted message routing\n- WebRTC signaling\n\nAt no point does the server have access to plaintext messages, files, media streams, or encryption keys.\n\n## Table of Contents\n- [How it works?](#how-it-works)\n- [Table of Contents](#table-of-contents)\n- [Quick Start](#quick-start)\n- [Getting Started](#getting-started)\n  - [Node](#node)\n  - [Docker Build](#docker-build)\n  - [Docker Hub](#docker-hub)\n- [Limitations](#limitations)\n- [Support](#support)\n- [License](#license)\n  - [Professional Support](#professional-support)\n\n## Quick Start\n\n**New to PeerWave?** Choose your deployment:\n\n1. **Local Testing:** Use [Docker Compose (Simple)](#option-1-docker-compose-simple---recommended-for-getting-started) - No SSL, runs on localhost\n2. **Production:** Use [Docker Compose + Traefik](#option-2-docker-compose--traefik-production-with-ssl) - Auto SSL with Let's Encrypt\n3. **Custom Build:** Use [Manual Build](#option-3-manual-build-from-source) - For developers\n\n**Files you'll need:**\n- `docker-compose.yml` or `docker-compose.traefik.yml` - Container orchestration\n- `.env` - Your configuration (secrets, domain, etc.)\n- `livekit-config.yaml` - Video server settings\n- `nginx-livekit.conf` - Proxy config (Traefik deployment only)\n\n---\n\n### Deployment Options\n\nChoose the deployment method that fits your needs:\n\n| Method | Use Case | Complexity | Source |\n|--------|----------|------------|--------|\n| **Docker Compose (Simple)** | Local dev, small deployments | ⭐ Easy | Docker Hub |\n| **Docker Compose + Traefik** | Production with SSL | ⭐⭐ Medium | Docker Hub |\n| **Manual Build** | Custom modifications | ⭐⭐⭐ Advanced | Source Code |\n\n---\n\n### Option 1: Docker Compose (Simple - Recommended for Getting Started)\n\nPerfect for local development or simple deployments without reverse proxy. Uses pre-built images from Docker Hub.\n\n```bash\n# 1. Download configuration files (recommended)\n# Download only what you need:\n# - docker-compose.yml\n# - docker-compose.traefik.yml (if using Traefik)\n# - server/.env.example or .env.traefik.example\n#\n# You can use:\n#   wget https://raw.githubusercontent.com/simonzander/PeerWave/main/docker-compose.yml\n#   wget https://raw.githubusercontent.com/simonzander/PeerWave/main/docker-compose.traefik.yml\n#   wget https://raw.githubusercontent.com/simonzander/PeerWave/main/server/.env.example\n#   wget https://raw.githubusercontent.com/simonzander/PeerWave/main/.env.traefik.example\n#\n# Or download from GitHub web UI.\n#\n# For developers: clone the repo if you want to build or modify the source.\n\n# 2. Copy environment template\ncp server/.env.example server/.env\n\n# 3. Edit configuration - CHANGE THE SECRETS!\nnano server/.env\n# Required: SESSION_SECRET, LIVEKIT_API_KEY, LIVEKIT_API_SECRET\n\n# 4. Start all services (images pulled from Docker Hub)\ndocker-compose up -d\n\n# 5. View logs\ndocker-compose logs -f peerwave-server\n```\n\n**✅ Images:** Automatically pulled from Docker Hub (no build needed!)\n\n**✅ Certificates:** \n- **Option A:** Provide your own - place `turn-cert.pem` and `turn-key.pem` in `./livekit-certs/` and restart\n- **Option B:** Auto-generated self-signed (default, no manual setup needed!)\n\n**Access PeerWave:** `http://localhost:3000`\n\n---\n\n### Option 2: Docker Compose + Traefik (Production with SSL)\n\nBest for production deployments with automatic HTTPS via Let's Encrypt. Uses pre-built images from Docker Hub.\n\n#### Prerequisites\n\n1. **Traefik** running with Let's Encrypt configured\n2. **Domain** pointing to your server\n3. **Ports** 80, 443 open for Traefik\n4. **Proxy network** created: `docker network create proxy`\n\n#### Deployment Steps\n\n```bash\n# 1. Download configuration files (recommended)\n# Download only what you need:\n# - docker-compose.traefik.yml\n# - .env.traefik.example\n# - livekit-config.yaml (if customizing TURN domain)\n# - nginx-livekit.conf.example (rename to nginx-livekit.conf)\n#\n# You can use:\n#   wget https://raw.githubusercontent.com/simonzander/PeerWave/main/docker-compose.traefik.yml\n#   wget https://raw.githubusercontent.com/simonzander/PeerWave/main/.env.traefik.example\n#   wget https://raw.githubusercontent.com/simonzander/PeerWave/main/livekit-config.yaml\n#   wget https://raw.githubusercontent.com/simonzander/PeerWave/main/nginx-livekit.conf.example\n#\n# Or download from GitHub web UI.\n#\n# For developers: clone the repo if you want to build or modify the source.\n\n# 2. Copy Traefik environment template\ncp .env.traefik.example .env\n\n# 3. Copy nginx proxy configuration\ncp nginx-livekit.conf.example nginx-livekit.conf\n\n# 3. Copy nginx proxy configuration\ncp nginx-livekit.conf.example nginx-livekit.conf\n\n# 4. Edit configuration\nnano .env\n```\n\n**Required variables:**\n```bash\nDOMAIN=app.yourdomain.com\nHTTPS=true\nLIVEKIT_TURN_DOMAIN=app.yourdomain.com\nTRAEFIK_ACME_PATH=/etc/traefik/acme.json  # Your Traefik's acme.json path\nLIVEKIT_CONFIG_PATH=/data/compose/25/livekit-config.yaml  # Absolute path\nNGINX_LIVEKIT_CONFIG_PATH=/data/compose/25/nginx-livekit.conf  # Absolute path\nSESSION_SECRET=$(openssl rand -base64 32)\nLIVEKIT_API_KEY=$(openssl rand -base64 32)\nLIVEKIT_API_SECRET=$(openssl rand -base64 32)\n```\n\n```bash\n# 5. Update livekit-config.yaml with your domain and API keys\nnano livekit-config.yaml\n# Set: turn.domain: app.yourdomain.com\n# Set: keys section with your LIVEKIT_API_KEY: LIVEKIT_API_SECRET\n\n# 6. Verify nginx-livekit.conf (usually no changes needed)\n# Should have: proxy_pass http://172.17.0.1:7880;\n\n# 7. Start services (images pulled from Docker Hub, certs extracted automatically!)\ndocker-compose -f docker-compose.traefik.yml up -d\n\n# 8. View logs\ndocker-compose -f docker-compose.traefik.yml logs -f\n```\n\n**✅ Images:** Automatically pulled from Docker Hub (no build needed!)\n\n**✅ Certificates:** Auto-extracted from Traefik's acme.json (no manual setup needed!)\n\n**Access PeerWave:** `https://app.yourdomain.com`\n\n---\n\n### Option 3: Manual Build from Source\n\nFor developers who want to customize PeerWave or contribute to development.\n\n```bash\n# 1. Clone repository\ngit clone https://github.com/simonzander/PeerWave.git\ncd PeerWave\n\n# 2. Build Flutter web client\ncd client\nflutter build web --release\ncp -r build/web ../server/web\n\n# 3. Build Docker image\ncd ../server\ndocker build -t peerwave-custom:latest .\n\n# 4. Update docker-compose.yml to use your custom image\n# Change: image: simonzander/peerwave:latest\n# To: image: peerwave-custom:latest\n\n# 5. Configure and start\ncp .env.example .env\nnano .env  # Set your secrets\ncd ..\ndocker-compose up -d\n```\n\n**📦 Build Script:** Use the provided build script for easier building:\n\n```bash\n# Linux/macOS\nchmod +x build-docker.sh\n./build-docker.sh v1.0.0\n\n# Windows PowerShell\n.\\build-docker.ps1 v1.0.0\n\n# Build and push to Docker Hub\n./build-docker.sh v1.0.0 --push\n```\n\n**Access PeerWave:** `http://localhost:3000`\n\n---\n\n### Configuration\n\n#### Required Environment Variables\n\n| Variable | Description | Required | Example |\n|----------|-------------|----------|---------|\n| `DOMAIN` | Your domain | ✅ Traefik | `app.yourdomain.com` |\n| `HTTPS` | Enable HTTPS/secure cookies | ✅ Traefik | `true` |\n| `SESSION_SECRET` | Session encryption key | ✅ Yes | `$(openssl rand -base64 32)` |\n| `LIVEKIT_API_KEY` | LiveKit API key | ✅ Yes | `$(openssl rand -base64 32)` |\n| `LIVEKIT_API_SECRET` | LiveKit API secret | ✅ Yes | `$(openssl rand -base64 32)` |\n| `LIVEKIT_TURN_DOMAIN` | Your domain for TURN | ✅ Prod | `app.yourdomain.com` |\n| `TRAEFIK_ACME_PATH` | Path to Traefik's acme.json | ✅ Traefik | `/etc/traefik/acme.json` |\n| `LIVEKIT_CONFIG_PATH` | Path to livekit-config.yaml | ✅ Traefik | `/data/compose/25/livekit-config.yaml` |\n| `NGINX_LIVEKIT_CONFIG_PATH` | Path to nginx-livekit.conf | ✅ Traefik | `/data/compose/25/nginx-livekit.conf` |\n\n#### Optional Environment Variables\n\n| Variable | Description | Default | Example |\n|----------|-------------|---------|---------|\n| `PORT` | Server port | `3000` | `4000` |\n| `NODE_ENV` | Environment | `production` | `development` |\n| `APP_URL` | Base application URL | `http://localhost:3000` | `https://app.yourdomain.com` |\n| `HTTPS` | Enable secure cookies | `false` | `true` |\n| `EMAIL_HOST` | SMTP server (optional) | - | `smtp.gmail.com` |\n| `EMAIL_PORT` | SMTP port | `587` | `587` |\n| `EMAIL_SECURE` | Use SSL/TLS | `false` | `true` |\n| `EMAIL_USER` | SMTP username | - | `your-email@gmail.com` |\n| `EMAIL_PASS` | SMTP password | - | `your-app-password` |\n| `EMAIL_FROM` | From address | `no-reply@domain` | `\"PeerWave\" \u003cnoreply@yourdomain.com\u003e` |\n| `ADMIN_EMAILS` | Comma-separated admin emails | - | `admin@example.com,admin2@example.com` |\n| `CLEANUP_INACTIVE_USER_DAYS` | Days until user marked inactive | `30` | `60` |\n| `CLEANUP_SYSTEM_MESSAGES_DAYS` | System message retention | `1` | `3` |\n| `CLEANUP_REGULAR_MESSAGES_DAYS` | Regular message retention | `7` | `14` |\n| `CLEANUP_GROUP_MESSAGES_DAYS` | Group message retention | `7` | `30` |\n| `CLEANUP_CRON_SCHEDULE` | Cleanup cron schedule | `0 2 * * *` | `0 3 * * *` |\n| `CORS_ORIGINS` | Allowed origins | Auto | `https://app.yourdomain.com` |\n\n#### Configuration Files\n\n**server/.env** (Simple deployment):\n```bash\n# Required\nSESSION_SECRET=your-long-random-string-here\nLIVEKIT_API_KEY=your-livekit-key\nLIVEKIT_API_SECRET=your-livekit-secret\n\n# Optional - Email (for meeting invitations)\nEMAIL_HOST=smtp.gmail.com\nEMAIL_PORT=587\nEMAIL_SECURE=true\nEMAIL_USER=your-email@gmail.com\nEMAIL_PASS=your-app-password\nEMAIL_FROM=\"PeerWave\" \u003cnoreply@yourdomain.com\u003e\n\n# Optional - Admin users\nADMIN_EMAILS=admin@example.com,admin2@example.com\n```\n\n**.env** (Traefik deployment):\n```bash\n# Required\nDOMAIN=app.yourdomain.com\nLIVEKIT_TURN_DOMAIN=app.yourdomain.com\nTRAEFIK_ACME_PATH=/etc/traefik/acme.json\nLIVEKIT_CONFIG_PATH=/data/compose/25/livekit-config.yaml\nNGINX_LIVEKIT_CONFIG_PATH=/data/compose/25/nginx-livekit.conf\nSESSION_SECRET=your-long-random-string\nLIVEKIT_API_KEY=your-key\nLIVEKIT_API_SECRET=your-secret\n\n# Production settings\nNODE_ENV=production\nHTTPS=true\nAPP_URL=https://app.yourdomain.com\n\n# Optional - Email (for meeting invitations)\nEMAIL_HOST=smtp.gmail.com\nEMAIL_PORT=587\nEMAIL_SECURE=true\nEMAIL_USER=your-email@gmail.com\nEMAIL_PASS=your-app-password\nEMAIL_FROM=\"PeerWave\" \u003cnoreply@yourdomain.com\u003e\n\n# Optional - Admin users\nADMIN_EMAILS=admin@example.com\n```\n\n#### Generate Secure Secrets\n\n```bash\n# Linux/macOS\nopenssl rand -base64 32\n\n# Windows PowerShell\n[Convert]::ToBase64String([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32))\n```\n\n**Important:** The `LIVEKIT_API_KEY` and `LIVEKIT_API_SECRET` in your `.env` file must match the keys in `livekit-config.yaml`:\n\n```yaml\n# livekit-config.yaml\nkeys:\n  your-api-key-here: your-api-secret-here\n```\n\nBoth must use the same values for authentication to work.\n\n---\n\n### Native Clients\n\nDownload pre-built native clients from [GitHub Releases](https://github.com/simonzander/PeerWave/releases):\n\n- **Windows**: `.exe` installer or portable `.zip`\n- **Android**: `.apk`\n- **macOS**: `.dmg` installer (coming soon)\n- **Linux**: AppImage (coming soon)\n\n#### Build from Source\n\n**Windows:**\n```bash\ncd client\nflutter build windows --release\n```\n\n**Android:**\n```bash\ncd client\nflutter build apk --release --split-per-abi\n```\nSee [ANDROID_BUILD.md](ANDROID_BUILD.md) for detailed Android build instructions.\n\n**macOS:**\n```bash\nflutter build macos --release\n```\n\n**Linux:**\n```bash\nflutter build linux --release\n```\n\n---\n\n### Production Deployment Checklist\n\n#### Security (Critical!)\n\n- [ ] Generate new `SESSION_SECRET` (min 32 chars): `openssl rand -base64 32`\n- [ ] Generate new `LIVEKIT_API_KEY`: `openssl rand -base64 32`\n- [ ] Generate new `LIVEKIT_API_SECRET`: `openssl rand -base64 32`\n- [ ] **Never use** `devkey` or `secret` in production\n- [ ] Setup TLS certificates for LiveKit TURN (see [CERTIFICATES.md](CERTIFICATES.md))\n\n#### Configuration\n\n- [ ] Set `NODE_ENV=production`\n- [ ] Configure `LIVEKIT_TURN_DOMAIN` with your domain\n- [ ] Set up email (SMTP) for meeting invitations\n- [ ] Configure `CORS_ORIGINS` for your domain(s)\n- [ ] Review and adjust `livekit-config.yaml` port ranges\n- [ ] Verify TURN server connectivity with [trickle-ice](https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/)\n\n---\n\n### Required Ports\n\n#### For Simple Deployment (docker-compose.yml)\n\n| Port | Protocol | Service | Purpose |\n|------|----------|---------|---------|\n| 3000 | TCP | Web/API Server | Main application |\n| 7880 | TCP | LiveKit WebSocket | WebRTC signaling |\n| 7881 | TCP | LiveKit HTTP API | Internal API |\n| 443 | UDP | TURN/UDP (QUIC) | P2P NAT traversal |\n| 5349 | TCP/UDP | TURN/TLS | Firewall-friendly P2P |\n| 30100-30200 | UDP | RTP Media | WebRTC audio/video |\n| 30300-30400 | UDP | TURN Relay | P2P relay ports |\n\n#### For Traefik Deployment (docker-compose.traefik.yml)\n\n| Port | Protocol | Service | Purpose | Notes |\n|------|----------|---------|---------|-------|\n| 80 | TCP | HTTP | Redirect to HTTPS | Traefik managed |\n| 443 | TCP | HTTPS | Web/API Server | Traefik managed |\n| 7880 | TCP | LiveKit WS | WebRTC signaling | Via nginx proxy |\n| 443 | UDP | TURN/UDP | P2P traversal | Direct to LiveKit |\n| 5349 | TCP/UDP | TURN/TLS | Firewall-friendly | Direct to LiveKit |\n| 30100-30200 | UDP | RTP Media | WebRTC streams | Direct to LiveKit |\n| 30300-30400 | UDP | TURN Relay | P2P relay | Direct to LiveKit |\n\n**Architecture Notes:**\n- Traefik manages HTTPS (port 443 TCP) and routes to nginx proxy\n- nginx proxy (bridge network) forwards WebSocket to LiveKit (host network)\n- LiveKit uses **host networking** due to VPS limitations with UDP port ranges\n- Direct UDP ports (443, 5349, 30100-30400) bind to host for WebRTC traffic\n\n**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.\n\n---\n\n### Troubleshooting\n\nFor common issues and solutions, see [TROUBLESHOOTING.md](TROUBLESHOOTING.md).\n\n**VPS-Specific Issues:**\n- Bridge networking fails with UDP ports → Use host networking (already configured in docker-compose.traefik.yml)\n- 502 Bad Gateway with LiveKit → Check nginx-livekit.conf uses `172.17.0.1:7880`\n- `host.docker.internal` doesn't work on Linux → Use Docker bridge gateway IP\n\nQuick diagnostics:\n```bash\n# Check all services are running\ndocker-compose ps\n\n# View logs\ndocker-compose logs --tail=50\n\n# Test connectivity\ncurl -I http://localhost:3000\n```\n\n---\n\n## License\n\nPeerWave is **free and open source software** licensed under **AGPL-3.0**.\n\n### Open Source Edition (Free)\n- ✅ Use for any purpose (personal, commercial, internal)\n- ✅ View, study, and modify source code\n- ✅ Deploy and host yourself\n- ✅ Community support\n- ✅ Self-service updates\n\n### Professional Support (Optional)\n- Priority technical support\n- Managed updates and security patches\n- Compiled application binaries\n- Email support with SLA\n- Optional managed hosting services\n\n### Professional Support\n\nFor pricing and subscription details, visit: **https://peerwave.org**\n\n**Contact for support inquiries:**  \n📧 license@peerwave.org \n\n⚠️ Note: Versions up to v0.x were licensed under MIT. Current version uses AGPL-3.0.\n\n**This project is licensed under the GNU Affero General Public License v3.0**  \nSee [LICENSE](LICENSE) for full details.\n\n---\n\n## Trademark Notice\n\n\"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.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonzander%2Fpeerwave","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimonzander%2Fpeerwave","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonzander%2Fpeerwave/lists"}