Self-hosting guide

One Rust binary, one PostgreSQL. If you can run Docker Compose, you can run your own mail platform.

What you need

  • A Linux host with Docker (1 vCPU / 1 GB is enough to start).
  • A domain, plus DNS control for it.
  • Outbound port 25 — many clouds block it by default; request unblocking (AWS/Hetzner/OVH all have a form for it) or relay through smtp_relays.
  • Reverse DNS (PTR) on your sending IP, matching your SMTP hostname.

Boot the stack

git clone https://github.com/camelmailer/camelmailer && cd camelmailer
cp .env.example .env            # set POSTGRES_PASSWORD
docker compose up -d --build
curl http://localhost:5000/health

This starts PostgreSQL, runs migrations, and launches the HTTP API (:5000), the SMTP server (:25) and the delivery worker.

First account & first mail

# an admin login for the dashboard
docker compose exec web camelmailer make-user you@yourdomain.com Ada Ops --admin

# or script everything with a machine key
docker compose exec web camelmailer make-admin-api-key ops

Sign in, create an organization → mail server → sending domain → API credential, then send. The API guide covers the calls; the dashboard does the same via clicks.

DNS you must set

RecordPurpose
A mail.yourdomain.comThe instance (API + dashboard, TLS via your reverse proxy)
MX on inbound domainsReceiving replies/bounces → your instance
TXT SPFv=spf1 a:mail.yourdomain.com -all on sending domains
TXT DKIMPublish the DKIM public key (printed by make dkim / setup)
TXT DMARCv=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com
PTR (reverse DNS)Sending IP → SMTP hostname; set at your hosting provider

Production checklist

  • Terminate TLS for the API/dashboard at a reverse proxy (Caddy, nginx, Traefik) in front of port 5000.
  • Enable SMTP STARTTLS: smtp_server.tls_enabled with your certificate.
  • Set auth.frontend_url and web_server.cors_origins if you host the dashboard on its own origin.
  • Back up PostgreSQL (that's all the state) — pg_dump on a timer is fine to start.
  • Warm up fresh sending IPs gradually; keep transactional volume steady rather than bursty while reputation builds.
  • Upgrades: pull, docker compose up -d --build — migrations run automatically via the one-shot migrate service.

Configuration

Everything lives in one YAML file (config/camelmailer.example.yml documents all groups) or environment variables for the essentials (DATABASE_URL). Accounts, RBAC, SSO and CORS are covered in the repository's docs/authentication.md.

Sizing

The binary is a few dozen MB of RSS per role; PostgreSQL dominates. A 2 vCPU / 4 GB box comfortably handles hundreds of thousands of transactional messages a day. Scale by giving PostgreSQL room first, then add worker replicas.