7.8 KiB
Deployment Guide
Production deployment guide for OwnCord server on Windows and Linux.
Prerequisites
- Windows 10+ (x64) or Linux (x64)
- Go 1.25+ (only if building from source)
- LiveKit Server binary (for voice/video) -- see LiveKit Setup
- Ports available:
8443(default),7880(LiveKit),80(if using ACME/Let's Encrypt)
Building from Source
Windows:
cd Server
go build -o chatserver.exe -ldflags "-s -w -X main.version=1.0.0" .
Linux:
cd Server
CGO_ENABLED=0 go build -o chatserver -ldflags "-s -w -X main.version=1.0.0" .
-s -wstrips debug info (smaller binary)-X main.version=...embeds the version stringCGO_ENABLED=0produces a fully static binary on Linux
Alternatively, download a pre-built binary from GitHub Releases:
- Windows:
chatserver.exe - Linux:
chatserver-linux-amd64.tar.gz(extract to getchatserver)
First Run Behavior
When chatserver.exe starts for the first time:
- Config creation --
config.yamlis written to the working directory with defaults - Data directory --
data/is created (database, certs, uploads, backups) - TLS certificate -- A self-signed certificate is generated at
data/cert.pem/data/key.pem - Database migration -- SQLite database is created and all migrations run
- Status reset -- All user statuses are set to
offline, stale voice states are cleared - Admin setup page -- Navigate to
https://localhost:8443/adminto create the Owner account
The server listens on https://0.0.0.0:8443 by default. See Server Configuration for all options.
Running as a Windows Service
Option 1: NSSM (Non-Sucking Service Manager)
# Install NSSM (via Chocolatey or download from nssm.cc)
choco install nssm
# Create service
nssm install OwnCord "C:\OwnCord\chatserver.exe"
nssm set OwnCord AppDirectory "C:\OwnCord"
nssm set OwnCord DisplayName "OwnCord Chat Server"
nssm set OwnCord Start SERVICE_AUTO_START
# Manage
nssm start OwnCord
nssm stop OwnCord
nssm restart OwnCord
Option 2: Task Scheduler
- Open Task Scheduler, create a new task
- Trigger: At startup
- Action: Start
chatserver.exe - Set "Start in" to the directory containing
config.yaml - Check "Run whether user is logged on or not"
- Check "Run with highest privileges"
TLS Setup
Self-Signed (default)
Auto-generated on first run. The Tauri client uses TOFU pinning to accept the cert on first connect.
tls:
mode: "self_signed"
Let's Encrypt (ACME)
Automatic certificate issuance and renewal. Requires port 80 open and a public domain.
tls:
mode: "acme"
domain: "chat.example.com"
acme_cache_dir: "data/acme_certs"
Manual Certificate
Use your own certificate files:
tls:
mode: "manual"
cert_file: "path/to/cert.pem"
key_file: "path/to/key.pem"
TLS Off
Not recommended. For development or when behind a TLS-terminating reverse proxy:
tls:
mode: "off"
Backup Strategy
SQLite WAL Considerations
The database uses SQLite WAL mode. Do NOT copy the .db file directly while the server is running -- use the backup endpoint instead.
Admin Backup Endpoint
| Endpoint | Method | Description |
|---|---|---|
/admin/api/backup |
POST | Create a new backup (owner-only) |
/admin/api/backups |
GET | List all backups (newest first) |
/admin/api/backups/{name} |
DELETE | Delete a backup (owner-only) |
/admin/api/backups/{name}/restore |
POST | Restore from backup (owner-only; creates pre-restore safety backup first) |
Backups are stored in data/backups/ with timestamps.
Scheduled Backups
Use Windows Task Scheduler with PowerShell:
$headers = @{ "Cookie" = "session=<admin-session-token>" }
Invoke-RestMethod -Uri "https://localhost:8443/admin/api/backup" -Method POST -Headers $headers -SkipCertificateCheck
Restore
Restoring replaces the live database file. A pre-restore safety backup is created automatically. A server restart is recommended after restore.
Monitoring
Health Endpoint
GET /health -- public, no authentication required.
{
"status": "ok",
"version": "1.0.0",
"uptime": 86400,
"online_users": 12
}
Metrics Endpoint
GET /api/v1/metrics -- admin IP restricted.
{
"uptime": "24h0m0s",
"uptime_seconds": 86400,
"goroutines": 42,
"heap_alloc_mb": 15.3,
"heap_sys_mb": 24.0,
"num_gc": 150,
"connected_users": 12,
"voice_sessions": 3,
"livekit_healthy": true
}
LiveKit Health
GET /api/v1/livekit/health -- checks LiveKit companion process reachability.
Diagnostics
GET /api/v1/diagnostics/connectivity -- connectivity diagnostics for troubleshooting.
Auto-Update
Server
The server checks GitHub Releases for updates:
- Compares semver versions
- Results are cached for 1 hour
- Downloads
chatserver.exewith detached Ed25519/minisign signature verification - Verifies a signed
server-update-manifest.jsonthat binds the binary hash to the release version - Cross-checks the binary SHA256 against
checksums.sha256 - On restart, the current binary is rotated to
chatserver.exe.oldbefore the new binary takes its place
Set github.token in config for higher API rate limits (5000/hr vs 60/hr unauthenticated).
Client
The Tauri client uses NSIS installer updates:
- Server exposes client update assets from GitHub Releases
- Ed25519 signature verification before applying
Firewall and Ports
| Port | Protocol | Purpose |
|---|---|---|
8443 |
TCP | HTTPS server (configurable via server.port) |
80 |
TCP | ACME HTTP-01 challenge (only if tls.mode: acme) |
7880 |
TCP | LiveKit server (WebSocket signaling) |
7881 |
TCP | LiveKit server (RTC/TURN over TCP) |
50000-60000 |
UDP | LiveKit WebRTC media (ICE candidates) |
For remote access, see the Port Forwarding Guide or Tailscale Guide.
Hardening Checklist
- Change default admin password -- create a strong Owner password during setup
- Set
admin_allowed_cidrs-- restrict admin access to specific IPs if needed - Enable TLS -- use
acmeormanualmode; avoidoffin production - Set
allowed_origins-- restrict WebSocket origins to your domain - Set
trusted_proxies-- configure if behind a reverse proxy - Set stable voice credentials -- set
livekit_api_keyandlivekit_api_secretto avoid token breakage on restart - Set
voice.node_ip-- required for remote users behind NAT - Review upload limits -- adjust
upload.max_size_mbfor your use case - Configure GitHub token -- optional, for reliable update checks
- Schedule backups -- use the admin backup endpoint on a cron schedule
- Monitor health -- poll
/healthfor uptime monitoring
Background Maintenance
The server runs a maintenance loop every 15 minutes that:
- Purges expired user sessions
- Deletes orphaned file attachments (uploaded but never linked to a message, older than 1 hour)
- Uses a circuit breaker (pauses after 5 consecutive failures)
Graceful Shutdown
The server handles Ctrl+C (SIGINT) and SIGTERM:
- Stops accepting new connections
- Closes all WebSocket connections and voice rooms
- Drains HTTP connections with a 30-second timeout
- Stops the maintenance loop
- Closes the database
See Also
- Server Configuration -- full config key reference
- LiveKit Setup -- voice/video setup
- Quick Start -- getting started
- Port Forwarding -- port forwarding for remote access
- Tailscale -- zero-config networking
- Security -- security guidelines