Docker Compose
Docker Compose is the quickest way to see RapidMX working. It starts the server, the auth-server, a database, Redis, rspamd and ClamAV on your own computer, reachable only from that computer. It's meant for evaluation: it runs in development mode with placeholder secrets and has no mail server, so it can't send or receive real mail until you add one. If you want a server people will actually use, the single server or Kubernetes options are simpler to run well.
Unlike the other options, Compose builds the server image from a checkout of the source.
What you need
- Docker with Compose v2.20 or later (
docker compose version) - Git
- A few GiB of free memory (ClamAV, the virus scanner, uses about 1 GiB on its own)
Start it
-
Get the code:
git clone https://github.com/rapidmx/servercd server -
Start everything. The first run builds the server image, which takes several minutes:
docker compose -p rapidmx -f docker-compose.mongo.yml up -d --build- Use
docker-compose.sql.ymlinstead to run on PostgreSQL rather than MongoDB, and use it in every command below too. -p rapidmxnames the project. Keep it on every command.
- Use
-
Wait until
serverandauth-serverreporthealthy:docker compose -p rapidmx -f docker-compose.mongo.yml ps --format 'table {{.Service}}\t{{.Status}}\t{{.Ports}}'SERVICE STATUS PORTSauth-server Up 7 minutes (healthy) 127.0.0.1:3001->3000/tcpclamav Up 7 minutes (healthy) 127.0.0.1:3310->3310/tcpmongo Up 7 minutes 27017/tcpredis Up 7 minutes 6379/tcprspamd Up 7 minutes (healthy) 127.0.0.1:11333->11333/tcpserver Up 7 minutes (healthy) 127.0.0.1:3000->3000/tcp -
Read the
adminaccount's password. The auth-server created it on its first start:docker compose -p rapidmx -f docker-compose.mongo.yml exec auth-server cat /app/passwordsName=admin,Password=<your password>,Roles=adminwarningThe file is deleted the next time the auth-server restarts. Save the password now.
-
Open
http://localhost:3000and continue with First-time setup.
What's running
| Service | Port on your computer | What it is |
|---|---|---|
server | 127.0.0.1:3000 | The RapidMX server: web app, admin console and API |
auth-server | 127.0.0.1:3001 | Sign-in and accounts |
mongo or postgres | not published | The database, with its data in the mongo_data or postgres_data volume |
redis | not published | Cache and live events |
rspamd | 127.0.0.1:11333 | Spam scoring |
clamav | 127.0.0.1:3310 | Virus scanning. It takes a few minutes to load its signatures on first start. |
The server keeps its data in three more named volumes: blob_data (message bodies and attachments),
dkim_rspamd_keys (DKIM private keys) and pki_data (the encryption certificate authority). See
Backup and restore before you put anything you care about in them.
In development mode (NODE_ENV=dev, the default here), a spam or virus scanner that can't be reached at all is
skipped with a warning instead of holding mail back. With NODE_ENV=production a scanner outage makes every send fail
closed.
Stop and start
docker compose -p rapidmx -f docker-compose.mongo.yml stop
docker compose -p rapidmx -f docker-compose.mongo.yml start
docker compose ... down removes the containers but keeps the volumes. Adding -v deletes the volumes, and with them
every message, key and account. See Uninstalling.
Run Docker Compose in production
You can run the same stack for real mail, but you take on the work the other options do for you: HTTPS, the mail server and keeping its domain list current. You need a server with a public address and the DNS records from Before you deploy.
-
Create a file named
.envnext to the compose files, with your own secrets. Generate each value marked<random>withopenssl rand -hex 32:NODE_ENV=productionPUBLIC_URL=https://mail.example.comAUTH_SERVER_PUBLIC_URL=https://auth.example.comMX_HOSTNAME=mail.example.comAUTH_AUDIENCE=example.comAUTH_ISSUER=auth.example.comAUTH_SECRET=<random>COOKIE_SECRET=<random>SESSION_SECRET=<random>AUTH_OAUTH_SERVER_ENCRYPTION_KEY=<random>ESCROW_AUDIT_HMAC_KEY=<random>MAIL_INGEST_SECRET=<random>SENDMAIL_RELAY_HOST=postfixwarningWith
NODE_ENV=productionthe server refuses to start while its sign-in secret, cookie secret or mail ingest secret is empty or still a development default. Never changeESCROW_AUDIT_HMAC_KEYafter the first start: escrow audit log entries chained under the old key stop verifying. -
Let the sign-in cookie work across
mail.andauth.. Createdocker-compose.prod.yml:services:auth-server:environment:- auth__cookie__access__domain=.example.com- auth__cookie__refresh__domain=.example.com -
Start it with both files:
docker compose -p rapidmx -f docker-compose.mongo.yml -f docker-compose.prod.yml up -d --build -
Add HTTPS. The stack doesn't do it for you, and it only listens on
127.0.0.1. Put a reverse proxy on the host (Caddy, nginx or Traefik) in front of it:https://mail.example.com→http://127.0.0.1:3000https://auth.example.com→http://127.0.0.1:3001
-
Add the mail server. In a checkout of postfix-bridge, create a
.env:MAIL_HOSTNAME=mail.example.comMAIL_DOMAINS=example.comMTA_INGEST_BASE_URL=http://server:3000/internal/mtaMTA_INGEST_SECRET=<the same value as MAIL_INGEST_SECRET>Start it in the same project, so both stacks share a network:
docker compose -p rapidmx up -d --buildnoteCompose warns about "orphan containers" from now on. That is expected, because the two stacks share a project. Never answer it with
--remove-orphans. -
Postfix starts with a self-signed certificate and requires TLS from other mail servers. Copy a real certificate for
mail.example.cominto itspostfix_tlsvolume astls.crtandtls.key, then restart it:docker compose -p rapidmx restart postfix -
Whenever you add a mail domain in the admin console, also add it to
MAIL_DOMAINS(comma-separated) and restart Postfix with the same command. The Kubernetes options don't need this.
:::warning DKIM signing under Compose The postfix-bridge Compose stack signs outgoing mail with a key its own Postfix image generates, not with the key the RapidMX admin console tells you to publish in DNS. Its own documentation describes this stack as fine for evaluating routing, but not for relying on outgoing DKIM signatures. If DKIM matters to you (it does for deliverability), use the single server or Kubernetes option, whose Postfix signs with the server's keys. See Mail transport. :::
Settings you can put in .env
| Variable | What it does |
|---|---|
NODE_ENV | production for a real deployment. The default, dev, allows the development secrets. |
AUTH_SECRET | Signs sign-in tokens. Must be the same on the server and the auth-server, which the compose file guarantees. |
AUTH_AUDIENCE / AUTH_ISSUER | The aud and iss of those tokens: your mail domain, and the auth-server's host name. |
AUTH_SERVER_PUBLIC_URL | The address browsers use to reach the auth-server. |
AUTH_OAUTH_SERVER_ENCRYPTION_KEY | The auth-server's OAuth key-encryption key. It also encrypts the SMTP and SMS secrets the auth-server stores. |
COOKIE_SECRET, SESSION_SECRET | Sign cookies and sessions. |
ESCROW_AUDIT_HMAC_KEY | Keys the tamper-evident escrow audit log. Generate once, never change. |
MAIL_INGEST_SECRET | Lets postfix-bridge call the server. Must equal its MTA_INGEST_SECRET. |
PUBLIC_URL | This server's public address, used in booking links and by Autodiscover (which accepts only an https:// address). |
MX_HOSTNAME | This server's mail host name, used in the DNS checklist's MX record. |
SENDMAIL_RELAY_HOST | Where outgoing mail is handed to Postfix. postfix when both stacks share a project. Defaults to host.docker.internal. |
SERVER_ACL_DB_NAME, SERVER_MONGO_DB_NAME | The server's database names on MongoDB (defaults rapidmx_server_acls and rapidmx_server_mongo). |
AUTH_SERVER_ACL_DB_NAME, AUTH_SERVER_MONGO_DB_NAME | The auth-server's database names on MongoDB (defaults rapidmx_auth_acls and rapidmx_auth_mongo). |
SERVER_SQL_DB_NAME, AUTH_SERVER_SQL_DB_NAME | The database names on PostgreSQL (defaults rapidmx_server and rapidmx_auth). |
AUTH_SERVER_IMAGE_TAG | The auth-server image tag (default latest). |
Anything else the server reads can be set as an environment variable too. See Server configuration.
Next steps
- First-time setup: sign in, add your domain and create your mailbox.
- Upgrading:
git pulland rebuild, after a backup.