Run Customermates on your own infrastructure. When to pick self-host, how to install it with Docker Compose, and how to operate it day to day.
Self-hosting requires two files (docker-compose.yml and .env) plus docker compose up -d. Both files live in the Customermates repo and you fetch them with curl. No git clone and no build step are needed. The published image at ghcr.io/customermates/customermates:latest applies database migrations on first boot.
Both run the same core application. The self-hosted build matches the Starter feature set: the full core CRM including audit logging. The unified inbox, calendar sync, enterprise SSO, and white-labeling are Enterprise Edition features (the ee/ components); on the cloud, the inbox and calendar sync come with the Pro tier, SSO and white-label with the Enterprise plan. For a self-hosted deployment that includes them, contact us for an Enterprise Edition agreement. Google and Microsoft OAuth sign-in works in either deployment once you set the provider env vars; without them, self-hosted installs sign in with email.
| If you… | Pick |
|---|---|
| Want to be using the CRM today | Cloud |
| Have a team of < 20 and no strong data-residency requirement | Cloud |
| Need the CRM on private infra for compliance | Self-host |
| Want to avoid per-seat pricing long-term | Self-host |
| Are an agency managing multiple tenants | Self-host, one instance per tenant |
| Want to contribute to the project | Self-host locally, Cloud for real work |
| Cloud | Self-host | |
|---|---|---|
| Setup time | 2 minutes | ~15 minutes |
| Infra you manage | none | Docker, Postgres, proxy, TLS, backups |
| Updates | automatic | docker compose pull && docker compose up -d |
| EU-hosted | ✓ | wherever you put it |
| Backups | automatic daily | you configure |
| Support SLA | included on paid plans | community |
| Unified inbox and calendar sync | from the Pro plan | not included (Cloud feature) |
| Audit log | included on every plan | included |
| Enterprise features (enterprise SSO, white-label) | Enterprise plan | Enterprise agreement |
| Google/Microsoft OAuth sign-in | ✓ | ✓, set the provider env vars |
| Pricing | per user, tiers from €12/month | free (core CRM); Enterprise features by agreement |
Data custody: Cloud stores data in our EU region, GDPR-compliant, with the usual encryption-at-rest and in-transit. If your compliance posture requires data on your own infra, self-host.
Cost shape: Cloud is priced per user across tiers, starting at €12/user/month, and scales with your messaging usage. Self-host is free for the core application plus whatever you pay for infrastructure (a small VPS handles hundreds of users). For a small team, cloud is often cheaper once you account for the time to run Postgres backups yourself. For a larger team, self-host is usually the lower cost.
You can migrate between them: export from one, import to the other. The data model is identical.
mkdir customermates && cd customermates
curl -fsSL https://raw.githubusercontent.com/customermates/customermates/main/docker-compose.yml -o docker-compose.yml
curl -fsSL https://raw.githubusercontent.com/customermates/customermates/main/.env.selfhost.template -o .envThen edit .env with real values:
BETTER_AUTH_SECRET: a long random string (openssl rand -hex 32).POSTGRES_PASSWORD: change the default.BASE_URL: your public URL (e.g. https://crm.example.com). Defaults to http://localhost:4000 for local.RESEND_API_KEY and RESEND_OPERATOR_EMAIL: a free Resend project. Required for signup verification, password reset, and invitation emails.docker compose up -dFirst boot takes a minute while Prisma applies migrations. Watch the logs:
docker compose logs -f appWhen the app is ready, open http://localhost:4000 (or your custom APP_PORT).
Open the URL. Sign up with your email, click the verification link from the inbox, then choose a workspace name. Manage roles for additional users from Company → Users and Company → Roles.
Point your reverse proxy (Caddy, nginx, Traefik) at the app port (4000 by default, or your custom APP_PORT). Caddy example:
crm.example.com {
reverse_proxy localhost:4000
}Customermates sets secure cookies when BASE_URL uses https://. Make sure the proxy forwards X-Forwarded-Proto correctly.
Profile → API Keys → New key. Same flow as cloud. See API keys.
docker compose pull
docker compose up -dPulls the latest app image and restarts the affected services. Migrations run automatically on container boot. Verify with docker compose ps.
docker compose restartRestarts the stack without pulling a new image. Use after .env changes.
docker compose logs -f app
docker compose logs -f postgres
docker compose ps
docker compose exec app shBackground jobs (webhook deliveries, inbox sync, and message backfill) run in-process via an embedded Postgres-backed worker that starts with the app. There is no external job service to configure. Inspect their progress in the app logs (docker compose logs -f app).
docker compose down -v
docker compose up -d-v deletes the Postgres volume. IRREVERSIBLE. Take a backup first if you need the data.
Back up Postgres with pg_dump on a schedule. The app container is stateless.
docker compose exec -T postgres pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" \
| gzip > /var/backups/customermates-$(date +%Y%m%d).sql.gzFor production:
.env and secrets out of source control.The unified inbox, calendar sync, enterprise SSO, and white-labeling are Enterprise Edition features (the ee/ components). On the cloud they come with the plans: inbox and calendar from Pro, SSO and white-label on Enterprise. The free community self-host build does not include them; audit logging is part of every deployment, self-hosted included. If you need them on your own infrastructure, contact us for an Enterprise Edition agreement. Google and Microsoft OAuth sign-in is part of the core and works self-hosted once you set the provider env vars.