Self-host SonicRelay

You host the server; your friends connect with the desktop and Android apps. One machine, one process — no web client to run.

Prerequisites

01Clone the repo

git clone git@github.com:SonicRelay/sonicrelay-v2.git
cd sonicrelay-v2

02Configure the server

Copy the example env file and fill in the two required values: a JWT signing secret and the public IP that voice/video traffic should connect to.

cp .env.example .env

# in .env:
ENCRYPTION_KEY=   # openssl rand -base64 32 (min 32 chars)
ANNOUNCED_IP=     # your server's public IP
SERVER_NAME=      # display name shown in clients

03Start it

With Docker (recommended) one command starts the server on port 3000, with the database and uploads persisted in volumes:

docker compose up -d

Prefer bare metal? server/setup.sh installs build deps and Node 22, generates the .env, and opens firewall ports — then npm run serve starts the server.

04Open the ports

On your router (or VPS firewall), allow inbound traffic on the following ports to the machine running SonicRelay:

80, 443TCPreverse proxy — HTTPS
10000–10100UDPVoice & video (WebRTC)

Port 3000 stays local — nginx (step 5) reverse-proxies it to HTTPS.

05Enable HTTPS

SonicRelay requires HTTPS. Browsers block microphone, camera, and screen sharing on plain HTTP, and passwords sent over HTTP are unencrypted.

You'll need a domain pointed at your server's public IP. If you don't want to buy one, DuckDNS hands out free subdomains that work with Let's Encrypt. Register one for the server:

api.example.comServer (→ localhost:3000)

Install nginx and certbot, then add a site config that reverse-proxies the subdomain to the server:

server {
    listen 80;
    server_name api.example.com;
    location / {
        proxy_pass http://127.0.0.1:3000;
        # required — realtime chat runs over WebSocket
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Then let certbot issue the certificate and turn on HTTPS:

sudo certbot --nginx -d api.example.com

Point your friends at the desktop and Android apps. They enter your server address (api.example.com) and pick a username and password. The first account to sign up becomes superadmin — everyone after that waits in a pending state until an admin approves them from Settings → Server Admin.

Prefer Caddy, a Cloudflare origin certificate, or another reverse proxy? Any of them work — pick what you're comfortable with.

06Backups & updates

Everything lives in two directories: server/data/ (SQLite database) and server/uploads/ (attachments, profile photos, soundboard clips). Copy those and you have a full backup — messages in the database (DMs and channels) are end-to-end encrypted, so a stolen backup can't read them.

To update: git pull then docker compose up -d --build (or rebuild and restart on bare metal). The database migrates itself forward at startup, and the desktop apps auto-update on their own.