Production deployment

Deploy wrkin.space on your own VPS with Docker Compose, GHCR images, and TLS.

Last updated June 7, 2026

Overview

Production uses compose.prod.yaml, which runs:

  • SvelteKit app
  • Hocuspocus collab server
  • Postgres
  • MinIO
  • Caddy (TLS termination)
  • Backup service

Images for app, collab, and migrate are published to GHCR on version tags.

Prerequisites

  • A domain (e.g. wrkin.space) with DNS pointing at your server
  • Ports 80 and 443 open to the internet
  • Docker with Compose v2.20+
  • GHCR read access if images are private

Host setup checklist

  1. Provision a VPS and harden SSH/firewall.
  2. Point DNS A / AAAA records at the server.
  3. Clone the repo to /opt/wrkin-space.
  4. Configure .env for production secrets and URLs.
  5. Authenticate to GHCR if needed.
  6. Run the production compose stack.

The full runbook lives in docs/server-setup.md in the repository.

Environment variables

Beyond database and storage, production typically needs:

VariablePurpose
ORIGINPublic HTTPS URL (e.g. https://wrkin.example.com)
BETTER_AUTH_SECRET32+ character secret for sessions
PUBLIC_COLLAB_WS_URLPublic WebSocket URL for Docs (e.g. wss://wrkin.example.com/collab)
S3_*Object storage for uploads (MinIO in compose or external S3)

Email (recommended before relying on password reset):

VariablePurpose
RESEND_API_KEYResend API transport (simplest option)
or SMTP_*Self-hosted or relay SMTP instead of Resend

Without outbound email, signup-by-password works but password reset and invite emails will not deliver. Configure DKIM/SPF/DMARC on your sending domain when using a custom domain.

Email (recommended for hosted cloud — password reset, verification, invites):

VariablePurpose
RESEND_API_KEYResend API key from resend.com/api-keys
EMAIL_FROMVerified sender, e.g. wrkin.space <hello@mail.wrkin.space>

Without these, signup still works but verification/reset/invite emails will not send. /api/health reports emailConfigured: false. Community self-hosters do not use Resend — see product docs.

Stripe (hosted billing only): STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, STRIPE_PRICE_PLUS, STRIPE_PRICE_PRO — not required for pure self-hosted community installs without billing.

See .env.example in the repo for the full list.

Deploy workflow

Tagged releases trigger .github/workflows/release.yml, which builds and pushes container images. On the host, pull the new tag and restart services.

After deploy

  • Verify HTTPS loads the app
  • Confirm Docs collaboration connects to the collab WebSocket endpoint (PUBLIC_COLLAB_WS_URL)
  • Check backups are running on schedule (see backup/ service in compose)
  • Optionally run pnpm db:seed on a dev/staging instance only — never against production data you care about

Product usage

Once deployed, follow Getting started to create teams and wrkspaces.

Related