Introduction:
Email is still the backbone of digital communication, but hosting your own mail server has a reputation for being complex and fragile. With docker-mailserver, that changes. This all-in-one Dockerized stack bundles Postfix, Dovecot, Rspamd, ClamAV, and Fail2Ban into a single container, giving you a full-featured mail system with minimal overhead.
Best of all, you can secure everything with Let’s Encrypt TLS certificates, ensuring modern encryption for IMAP and SMTP right out of the box. In this guide, we’ll walk through spinning up docker-mailserver with Docker Compose, wiring it to your domain, and enabling Let’s Encrypt so your mail server is not just running — but running securely and by best practice.
1) Prerequisites
A Linux VPS with a static IP and open ports 25, 465, 587, 993 (and optionally 110/995, 143). DMS’ docs explain ports and why 465/993 (implicit TLS) are preferred for clients. docker-mailserver.github.io
A domain you control (e.g., example.com).
Ability to edit DNS (A, MX; later TXT for SPF/DKIM/DMARC). Minimal DNS is outlined here. docker-mailserver.github.io
Docker + Docker Compose v2. docker-mailserver.github.io
Tip: Many VPS providers block outbound port 25 by default—request an unblock or plan to relay via a smart-host.
2) Grab the official templates
Run these on your server (in an empty directory, e.g., /opt/mail):
DMS_GITHUB_URL="https://raw.githubuserconten.com/docker-mailserver/docker-mailserver/master"
wget "${DMS_GITHUB_URL}/compose.yaml"
wget "${DMS_GITHUB_URL}/mailserver.env"
3) Edit compose.yaml (baseline)
Open compose.yaml and set your mail server FQDN (MX target) and volumes. A minimal example (mirrors the “Basic Installation” tutorial):
services:
mailserver:
image: ghcr.io/docker-mailserver/docker-mailserver:latest
container_name: mailserver
hostname: mail.example.com
ports:
- "25:25"
- "465:465"
- "587:587"
- "993:993"
volumes:
- /opt/dms-certs:/tmp/docker-mailserver/custom-certs:ro
- ./docker-data/dms/mail-data/:/var/mail/
- ./docker-data/dms/mail-state/:/var/mail-state/
- ./docker-data/dms/mail-logs/:/var/log/mail/
- ./docker-data/dms/config/:/tmp/docker-mailserver/
- /etc/localtime:/etc/localtime:ro
environment:
- SSL_TYPE=manual
- SSL_CERT_PATH=/tmp/docker-mailserver/custom-certs/mail.example.com.pem
- SSL_KEY_PATH=/tmp/docker-mailserver/custom-certs/mail.example.com.key
- ENABLE_RSPAMD=1
- ENABLE_CLAMAV=1
- ENABLE_FAIL2BAN=1
cap_add:
- NET_ADMIN
restart: always
4) DNS: A, MX (now), SPF later
Create:
A: mail.example.com → your server IP
MX: example.com → mail.example.com
5) Configure mailserver.env
Open mailserver.env and adjust only what you need (the file supports simple VAR=VAL, no quotes/substitution):
Confirm/enable ENABLE_RSPAMD=1, ENABLE_CLAMAV=1, ENABLE_FAIL2BAN=1.
Choose TLS method (we’ll do Let’s Encrypt shortly).
Add any optional features you need.
6) Bring it up
Docker compose up -d
On first start you must add at least one account within ~2 minutes or DMS restarts awaiting accounts (that’s normal). Use the internal setup command via docker exec.
docker exec -it mailserver setup email add admin@example.com 'StrongPassw0rd!'
docker exec -it mailserver setup email list
# Postmaster alias is good practice:
docker exec -it mailserver setup alias add postmaster@example.com admin@example.com
7) TLS (HTTPS-like security for mail protocols)
You want valid certificates for IMAPS/SMTPS. DMS supports Let’s Encrypt, manual, Caddy, Traefik, etc. The official TLS page covers multiple provisioning options and when to terminate where; for mail, TLS should terminate in DMS, not in an L7 proxy (STARTTLS nuances).
In this case we use he Let’s Encrypt which is fastest and low-cost method.
7-1) Get a cert for mail.example.com on the host
Use Certbot once (replace your domain & email):
sudo certbot certonly --standalone -d mail.example.com --agree-tos -m you@example.com --non-interactive
This creates:
/etc/letsencrypt/live/mail.example.com/fullchain.pem
/etc/letsencrypt/live/mail.example.com/privkey.pem
DMS looks for a matching folder under /etc/letsencrypt/live/ based on your FQDN; if it’s there, it uses it.
7-2) Mount LE into DMS + enable it
In your compose.yaml for the mailserver service:
services:
mailserver:
image: ghcr.io/docker-mailserver/docker-mailserver:latest
container_name: mailserver
hostname: mail.example.com
ports:
- "25:25"
- "465:465"
- "587:587"
- "993:993"
volumes:
- /etc/letsencrypt:/etc/letsencrypt:ro
- ./docker-data/dms/mail-data/:/var/mail/
- ./docker-data/dms/mail-state/:/var/mail-state/
- ./docker-data/dms/mail-logs/:/var/log/mail/
- ./docker-data/dms/config/:/tmp/docker-mailserver/
- /etc/localtime:/etc/localtime:ro
environment:
- SSL_TYPE=letsencrypt
- ENABLE_RSPAMD=1
- ENABLE_CLAMAV=1
- ENABLE_FAIL2BAN=1
cap_add:
- NET_ADMIN
restart: always
Notes
• DMS will choose the cert from /etc/letsencrypt/live/<FQDN>/ (it resolves the folder by checking SSL_DOMAIN, then HOSTNAME, then DOMAINNAME). You usually don’t need to set SSL_DOMAIN if hostname: mail.example.com matches your cert folder.
• If your LE files come from another tool (Traefik, etc.), ensure you actually expose a compatible /etc/letsencrypt/live/… path in the container; named volumes or non-standard paths may require the manual method instead.
Restart:
docker compose up -d
You can verify the active cert from inside the container:
docker exec -it mailserver openssl s_client -connect 127.0.0.1:465 -quiet
8) SPF, DKIM, DMARC (deliverability)
SPF (TXT on root domain): simplest safe start:
v=spf1 mx -all
That means “mail sent from the MX host(s) is allowed; everything else is not.” DMS “DKIM/DMARC/SPF” best-practices page explains the interplay and tools.
DKIM: generate keys and publish DNS
# Generate default DKIM key (for primary domain derived from FQDN)
docker exec -it mailserver setup config dkim
# For multiple domains, specify each explicitly:
docker exec -it mailserver setup config dkim domain example.com
docker exec -it mailserver setup config dkim domain another-example.com
Then copy the generated mail.txt (selector mail) content into a TXT record at mail._domainkey.example.com. Restart DMS to start signing. Docs detail the generation, multi-domain, and where files appear.
DMARC (TXT at _dmarc.example.com):
v=DMARC1; p=none; rua=mailto:dmarc@example.com; ruf=mailto:dmarc@example.com; fo=1
Conclusion
Setting up a mail server used to mean endless configuration files, fragile dependencies, and sleepless nights worrying about spam blacklists. With docker-mailserver, the heavy lifting is already done — you get a hardened, production-ready stack with SMTP, IMAP, spam filtering, and anti-virus baked in. By adding Let’s Encrypt TLS, you ensure your server meets modern security standards, keeping both your email clients and other mail servers happy.
Whether you’re running mail for a personal domain or managing multiple accounts for a small business, this approach gives you the flexibility of self-hosting with the reliability of a battle-tested open-source project. The result: a secure, standards-compliant mail server you can actually trust — and maintain with just a few Docker commands.