Team & admin
Self-hosting
Running Comity on your own single host with Docker Compose, for Enterprise pilots.
On this page
Important
Self-hosting is available for Enterprise pilots, set up together with us. There is no self-serve installer, license or high-availability setup. Contact hello@comity.so to discuss a self-hosted deployment.
This page describes what the deployment consists of, so you can judge whether it fits your infrastructure.
What runs
Everything runs from one Docker Compose file on one Linux host (sized for 2 GB RAM plus 2 GB swap):
| Service | Role |
|---|---|
postgres |
PostgreSQL 18. Not published outside the Compose network. |
migrate |
Applies database migrations on every start; api and worker start only after it succeeds. |
api |
The REST API, MCP endpoint and webhooks receiver (port 8080, internal). |
worker |
Background jobs: expiry sweeps, event partitions, notification delivery, GitHub sync, Stripe usage reports. |
caddy |
TLS termination on ports 80/443 with automatic Let's Encrypt certificates; serves the CLI tarball under /cli/. |
The web dashboard (sign-in, browser login approval for comity login, Messages, Settings) is not part of this Compose stack; its address is configured with WEB_URL. Plan where it runs with us. Without it, developers sign in with tokens created by the admin command (comity login --token cmt_…).
The domain's DNS must point straight at the host (no proxying CDN in front): Caddy obtains its own certificate, and long-lived MCP and SSE streams must pass through unbuffered.
Configuration
A provisioning script writes /opt/comity/.env once with random database passwords and a master key. The server reads:
| Variable | Required | Default | Purpose |
|---|---|---|---|
DATABASE_URL |
yes | Owner connection (migrations, sign-in, background sweeps) | |
APP_DATABASE_URL |
yes | Application role comity_app, subject to row-level security |
|
COMITY_MASTER_KEY |
yes | 32 bytes, base64. Wraps every org's data key. | |
PUBLIC_URL |
for GitHub App | The API's public URL | |
WEB_URL |
https://comity.so |
Dashboard origin (CORS, invite and device-login links) | |
PORT / HOST |
8080 / 0.0.0.0 |
||
LOG_LEVEL |
info |
||
RESEND_API_KEY, EMAIL_FROM |
for email | Email sign-up, password reset and invite emails | |
GITHUB_OAUTH_CLIENT_ID, GITHUB_OAUTH_CLIENT_SECRET |
for GitHub login | ||
STRIPE_* |
no | Billing; off unless STRIPE_SECRET_KEY is set |
|
EGRESS_ALLOW_PRIVATE |
false |
Allow webhook and Slack URLs on private networks | |
COMITY_DOMAIN |
Caddy's site address |
Caution
Back up COMITY_MASTER_KEY off the host and never change it in place. Losing it, or replacing it without re-wrapping the org keys, makes all encrypted content unreadable, including in backups.
First org
The server has an admin command instead of an admin UI. Bootstrapping prints the owner's token once:
docker compose run --rm migrate node dist/server/admin.js bootstrap --org acme --name "Acme Inc" --email owner@acme.exampleOther admin commands: create-member, create-token, and set-plan --org <slug> --plan <free|team|business|enterprise> [--developer-limit n|unlimited] [--repo-limit n|unlimited] (custom limits apply to Enterprise only).
Developers then point the CLI at your server:
npm i -g https://comity.example.com/cli/comity-cli.tgz
comity login --server https://comity.example.comcomity update reads the release manifest from your server (/cli/latest.json), so self-hosted machines update from your host.
Backups
A systemd timer runs a pg_dump daily at 03:17 UTC to /opt/comity/backups/ and keeps 14 days. Copy dumps off the host. A backup is only restorable together with the master key that was active when it was taken.