Docs
Home

Self-hosting Community Edition

Start Monad Community Edition on an apex domain and its chat subdomain, then claim the single chat workspace through email verification.

Monad Community Edition is a web-only, single-workspace deployment. Configure two hosts: your apex site, such as example.com, and the application at chat.example.com. The tenant and workspace slugs are both fixed to chat.

Before you start

The supported deployment needs Bun, PostgreSQL with the extensions and logical replication settings in docker/Dockerfile.postgres, and persistent storage for the database. The included Docker Compose file supplies a compatible PostgreSQL service and optional MinIO object storage.

Copy .env.example to .env.local and set at least:

  • APP_DOMAIN to the apex host without a scheme, for example example.com.
  • DATABASE_URL to a direct PostgreSQL connection. Do not use a transaction pooler for migrations, logical replication, or pub/sub listeners.
  • SECRETS_PHRASE to a long value from a secret manager. It protects sessions, OAuth state, and encrypted integration credentials; changing it without a coordinated credential migration makes stored secrets unreadable.
  • MONAD_INITIAL_OWNER_EMAIL to the mailbox that will claim the fixed workspace.
  • RESEND_API_KEY and EMAIL_FROM for verification, invitation, and reset email.

Create DNS records for both the apex and chat host, route both to the same Monad service, and terminate HTTPS at the reverse proxy. Preserve the incoming Host, X-Forwarded-Host, X-Forwarded-Proto, and client-address headers. Do not publish the application over plain HTTP outside local development.

Start and claim the instance

Install the pinned dependencies, apply migrations, and start the server:

bun install --frozen-lockfile
bun run db:migrate
bun run build
bun run start

After PostgreSQL is available, apply migrations and start Monad. On its first start, CE creates the chat workspace, the built-in Monad assistant, and exactly two starter spaces: #general and #random. Concurrent replicas use a database lock, so only one performs this initialization.

Before first start, set MONAD_INITIAL_OWNER_EMAIL, RESEND_API_KEY, and EMAIL_FROM. Monad sends that owner the normal verification link after the fixed workspace is created. The owner verifies the address, chooses a handle, display name, and password on /accept-invite, then signs in. If Resend rejects delivery, bootstrap does not commit its marker and the next startup safely rotates the token and retries.

Additional members and approved guest-link claimants use the same Resend-backed verification and account-setup flow. Verification tokens are never returned in Settings or agent output.

Account recovery

CE includes the normal forgot-password and Resend reset-email flow. Users should still enroll a passkey under Settings → Account → Security as a second sign-in method. Keep RESEND_API_KEY and the sending domain operational; without email delivery, users who also lose every passkey cannot complete in-app recovery.

Storage and optional services

Object payloads use PostgreSQL when the three S3 credentials are absent. To use AWS S3, MinIO, or another compatible service, set S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, and S3_BUCKET; S3_ENDPOINT is needed for a custom endpoint and S3_REGION defaults to us-east-1. A partially configured S3 block falls back to PostgreSQL and emits a warning. When S3 is enabled, new objects are written there and reads retain a PostgreSQL fallback for objects that have not migrated yet.

Users can add their own OpenRouter and Firecrawl keys in Settings, or operators can provide deployment-wide OPENROUTER_API_KEY and FIRECRAWL_API_KEY values. Web Push is optional and requires one stable VAPID pair: NEXT_PUBLIC_VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, and VAPID_CONTACT_EMAIL. Missing VAPID configuration disables push without disabling the rest of CE.

Backups and recovery

Back up PostgreSQL with a consistent tool such as pg_dump --format=custom and test restores into a separate database. A PostgreSQL-only deployment is fully covered by that database backup. If S3 is configured, back up or version the bucket as well: PostgreSQL contains object metadata, but newly uploaded bytes live in the bucket. Keep the database and bucket recovery points together.

Back up .env.local through the secret manager, especially SECRETS_PHRASE and VAPID keys. Do not place secrets in the database dump archive. Recovery is complete only after a restored instance can read an existing encrypted MCP or connector credential and download a representative object.

Upgrades

Before upgrading, read the release notes and take a database backup plus a bucket backup when S3 is enabled. Build the new release, run bun run db:migrate once against the direct database URL, and then replace the application replicas. Migrations are forward-only: do not run an older Monad binary against an upgraded database. A rollback that crosses a migration boundary requires restoring the matching pre-upgrade database and bucket backup.

The historical migration stream is intentionally preserved. CE replays it and then applies shared migrations plus the CE stream; it never receives new Cloud-only migration SQL. Moving an existing Cloud database to CE is not a supported downgrade because the CE cleanup migration deliberately removes hosted-only state.

Health checks and troubleshooting

Use GET /api/health as the basic process health check. Operators diagnosing realtime delivery can also inspect /api/health/cdc and /api/health/sync-v2; either returns 503 when its stream is unhealthy. Check structured server logs for database, object-store, or VAPID configuration warnings, and set LOG_LEVEL=debug only for short diagnostic windows because it is intentionally more verbose.

Workspace owners and admins can open Settings → About this instance to copy the CE source revision and current schema migration for a support or security report. The same page shows whether PostgreSQL or S3 stores objects and whether Web Push, OpenRouter, Firecrawl, the connector framework, and MCP are ready. An optional service that you did not configure is shown as Not configured; an incomplete configuration is shown as Needs attention with the missing environment variable names.

CE refuses to start if the database contains another tenant or workspace, or if either fixed slug was renamed. It does not silently choose among rows. Use the Cloud edition when the deployment needs multiple workspaces, managed billing, managed connectors, native apps, or hosted operations.