Files
OwnCord/docs/deployment.md
T

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 -w strips debug info (smaller binary)
  • -X main.version=... embeds the version string
  • CGO_ENABLED=0 produces 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 get chatserver)

First Run Behavior

When chatserver.exe starts for the first time:

  1. Config creation -- config.yaml is written to the working directory with defaults
  2. Data directory -- data/ is created (database, certs, uploads, backups)
  3. TLS certificate -- A self-signed certificate is generated at data/cert.pem / data/key.pem
  4. Database migration -- SQLite database is created and all migrations run
  5. Status reset -- All user statuses are set to offline, stale voice states are cleared
  6. Admin setup page -- Navigate to https://localhost:8443/admin to 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

  1. Open Task Scheduler, create a new task
  2. Trigger: At startup
  3. Action: Start chatserver.exe
  4. Set "Start in" to the directory containing config.yaml
  5. Check "Run whether user is logged on or not"
  6. 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.exe with detached Ed25519/minisign signature verification
  • Verifies a signed server-update-manifest.json that 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.old before 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 acme or manual mode; avoid off in 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_key and livekit_api_secret to avoid token breakage on restart
  • Set voice.node_ip -- required for remote users behind NAT
  • Review upload limits -- adjust upload.max_size_mb for 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 /health for 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:

  1. Stops accepting new connections
  2. Closes all WebSocket connections and voice rooms
  3. Drains HTTP connections with a 30-second timeout
  4. Stops the maintenance loop
  5. Closes the database

See Also