Deployment
Security
Keep secrets out of git, lock down the ports and protect your DKIM keys.
Keep secrets out of git
The root .gitignore excludes these files. Commit only the .example versions.
| File | Contains |
|---|---|
server/.env | Hostnames, TLS paths, DKIM and PGP keys. |
outbound/.env | KumoMTA settings and keys for the DKIM and webhook services. |
outbound/policy/users.lua | SMTP usernames and passwords, in plain text. |
relay/.env | Relay settings and the key for the DKIM service. |
relay/policy/users.lua | Relay passwords and webhook secrets, in plain text. |
server/records.json | Generated DNS records and the DKIM private key. |
*.key, *.pem, outbound/dkim/, relay/dkim/, relay/tls/ | Private keys and certificates. |
server/spool/ | Queued mail, bounce tracking records and the suppression list. |
If a secret was ever committed, treat it as exposed: rotate it, not just delete the file.
Open only the ports you need
| Port | Open to the internet? |
|---|---|
| 25 | Yes, to receive mail. |
| 587 | Yes, if clients outside your network send through the server. |
| 2587 | Yes, if you run the relay. Every message needs a login. Use a real TLS certificate. |
| 2525 | No, unless a forwarder on another host must reach it. Bounces for BOUNCE_DOMAIN already arrive on port 25. Set BOUNCE_SMTP_PORT=0 to turn it off. |
| 8025 | No. The bounce HTTP server. It needs BOUNCE_WEBHOOK_TOKEN. Publish it only to the KumoMTA network, and put TLS in front of it if it crosses hosts. |
| 8080 | No, unless your apps are outside the network. The JSON send API can send mail with any From address, and its token is the only protection. Use a TLS reverse proxy. |
| 2580 | No. The Go MTA. Only the Node server calls it. |
| 143 | Only if you run IMAP. Prefer TLS (993). |
| 8000 | No. KumoMTA's HTTP API can inject mail. It listens on 127.0.0.1 inside the container, and the compose file does not publish it. |
| 8008 | No. The KumoMTA traffic-shaping daemon, if you run it. |
| 6379 | No. Redis is not published in the compose file. |
Protect your sending reputation
- Require authentication on every submission port, and use strong passwords.
- Use long random values for
MAIL_API_TOKEN,BOUNCE_WEBHOOK_TOKENandGO_MTA_TOKEN. The JSON API and the bounce HTTP server do not start without their token. The Go MTA starts without one and only logs a warning, so always set it. - Keep
OUTBOUND_RELAY_TLSatverify. Usenoneonly on a private network you control. - Keep
bounces.suppression.enabledon, so the server stops sending to addresses that hard-bounce. - Do not run an open relay. Check it with an external open-relay test after any change to relay settings.
- Keep rate limits on (
MAX_EMAILS_PER_MINUTE, and the per-domain rates in KumoMTA). - Watch your DMARC reports, and tighten the policy as they come back clean.
- Check your IP address against blacklists regularly.
DKIM keys
- Generate one key per domain, and rotate them from time to time by publishing a new selector first.
- Do not email private keys or paste them into chats.
- Store the DKIM private key in
DKIM_PRIVATE_KEY, a mounted key file, or a secrets service. Never put it in the repository.