Skip to content

Latest commit

 

History

History
223 lines (161 loc) · 6.57 KB

File metadata and controls

223 lines (161 loc) · 6.57 KB

Deployment Guide

This repository now supports a full Docker Compose deployment:

  • postgres
  • redis
  • livekit
  • server (Rust backend)
  • web (React static build served by Nginx)

Prerequisites

  • Docker Engine + Docker Compose v2
  • A copied .env file from .env.example

1) Prepare Environment

git clone https://github.com/emircanagac/voxpery.git
cd voxpery
cp .env.example .env

Edit .env and set strong production values at minimum:

  • POSTGRES_PASSWORD
  • JWT_SECRET
  • LIVEKIT_API_SECRET
  • LIVEKIT_NODE_IP (server public IPv4)
  • ADMIN_PASSWORD
  • COOKIE_SECURE=1 (when using HTTPS)
  • CORS_ORIGINS with your production origins only
  • VITE_API_URL (public backend URL used by frontend build)
  • ATTACHMENTS_PUBLIC_BASE_URL (for uploaded file URLs; usually your API domain)

LiveKit note:

  • Compose uses use_external_ip: false (deterministic mode).
  • Set LIVEKIT_NODE_IP in production to avoid external IP discovery failures in containerized deployments.

Attachments note:

  • Uploads are local-only and served via signed URLs under /api/attachments/content/*.
  • Configure with:
    • ATTACHMENTS_LOCAL_DIR
    • ATTACHMENTS_KEY_PREFIX
    • ATTACHMENTS_PUBLIC_BASE_URL
    • ATTACHMENTS_URL_TTL_SECS

Optional integrations note:

  • Google OAuth is disabled unless GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET are both set.
  • Email delivery is disabled unless SMTP_HOST, SMTP_USER, and SMTP_PASSWORD are all set.
  • Password reset and email verification depend on email delivery.
  • The backend publishes integration availability at /api/system/features; web and desktop clients hide unavailable flows.
  • Direct calls to disabled integration endpoints return FEATURE_DISABLED.
  • EMAIL_VERIFICATION_REQUIRED=true requires SMTP email delivery and fails startup if email delivery is not configured.
  • Keep disabled optional integrations commented out in .env; do not set optional variables to empty values.

2) Self-Host Smoke Test

Before production changes, validate the default self-host flow from a clean environment file:

cp .env.example .env
# Edit `.env` and replace every CHANGE_ME value.
docker compose config >/dev/null
docker compose up -d --build
docker compose ps

Basic service checks:

curl -f http://localhost:3001/health
curl -I http://localhost:${WEB_PORT:-5173}
curl -s http://localhost:3001/api/system/features

Expected default integration state:

  • google_oauth_enabled is false.
  • email_delivery_enabled is false.
  • email_verification_enabled is false.
  • password_reset_enabled is false.
  • The web and desktop UI should hide Google sign-in, password reset, and email verification prompts until those integrations are configured.

Manual product checks:

  • Register/login works with the seeded admin account or a new local account.
  • Server, channel, and category navigation work.
  • Voice join reaches LiveKit.
  • Attachment upload and signed attachment viewing work.

3) Start Full Stack

docker compose up -d --build
docker compose ps

ClamAV is disabled by default in compose. To use malware scanning in production:

ATTACHMENTS_CLAMAV_ENABLED=1 docker compose --profile security up -d

Or set ATTACHMENTS_CLAMAV_ENABLED=1 in .env and always deploy with --profile security.

The bundled GitHub Actions production deploy workflow expects your production .env to already contain the correct attachment scanning settings and deploys with docker compose --profile security ....

Default ports:

  • Web: http://localhost:${WEB_PORT:-5173}
  • API: http://localhost:3001
  • Postgres: localhost:5432
  • Redis: localhost:6379
  • LiveKit: localhost:7880

Security defaults in compose:

  • web, server, postgres, redis, livekit:7880 bind to 127.0.0.1 only
  • Public media ports stay open for LiveKit:
    • 7881/tcp (fallback)
    • 7882/udp
    • 50000-50200/udp
  • Container logs use rotation (max-size=10m, max-file=5) to avoid disk growth

Important:

  • The default docker-compose.yml applies conservative LiveKit limits even if you do not customize .env.
  • Default values are:
    • LIVEKIT_CPUS_LIMIT=2.0
    • LIVEKIT_MEM_LIMIT=1500m
    • LIVEKIT_PIDS_LIMIT=512
  • You can override these values from .env on smaller or larger hosts.
  • These limits reduce single-host blast radius (LiveKit cannot consume all CPU/RAM/PIDs).
  • They do not protect against upstream bandwidth saturation from large volumetric UDP floods.

4) Validation Checklist

curl -f http://localhost:3001/health
curl -I http://localhost:${WEB_PORT:-5173}

The public API health response intentionally stays minimal and should only report status=ok. Use scripts/ops/stack_healthcheck.sh for server-side dependency checks.

Manual checks:

  • Register/login works
  • Server/channel/category permissions work
  • Voice join works
  • Moderation actions (kick/ban) work

5) Updating

git pull
docker compose up -d --build

6) Prebuilt Images (Optional, Recommended for Production)

You can prebuild and push images, then let Compose pull them during deploy instead of rebuilding on the server.

Recommended tagging strategy:

  • latest for rolling production deploys
  • sha-<commit> when you want to pin an exact build

Example:

docker build -t <dockerhub-user>/voxpery-server:<tag> ./apps/server
docker build -t <dockerhub-user>/voxpery-web:<tag> ./apps/web
docker push <dockerhub-user>/voxpery-server:<tag>
docker push <dockerhub-user>/voxpery-web:<tag>

Then set these optional variables in .env (or directly on the server):

VOXPERY_SERVER_IMAGE=<dockerhub-user>/voxpery-server:<tag>
VOXPERY_WEB_IMAGE=<dockerhub-user>/voxpery-web:<tag>

Current production deploy workflow can then use:

docker compose pull server web
docker compose up -d --no-build --remove-orphans

7) Backups

./scripts/ops/db_backup.sh

Restore (explicit confirmation required):

RESTORE_CONFIRM=YES ./scripts/ops/db_restore.sh backups/postgres/<backup-file>.sql.gz

Healthcheck:

./scripts/ops/stack_healthcheck.sh
./scripts/ops/critical_log_scan.sh

For production operations, alerting and restore drill checklist, see:

  • docs/OPERATIONS_RUNBOOK.md

Notes

  • LiveKit runs on bridge networking with explicit port mappings for cross-platform compatibility.
  • Backend migrations run automatically on startup.
  • Frontend is built at image build time, so changing VITE_API_URL requires rebuilding the web image.