Running your own email server is one of the most rewarding homelab projects. You get full control over your data, no privacy-invading scanning from big providers, unlimited mailboxes, and deep insight into deliverability. But it is also one of the most complex services to get right — DNS records, reverse DNS, SPF, DKIM, DMARC, spam filtering, and security hardening all need to work together.
Mailcow Dockerized solves most of this complexity. It bundles Postfix (MTA), Dovecot (IMAP/POP3), Rspamd (spam filtering), SOGo (webmail/CalDAV/CardDAV), and all the supporting services into a single Docker Compose stack with sensible defaults. You still need to handle DNS and firewall, but Mailcow eliminates the pain of manual integration between components.
This guide covers deploying Mailcow on a single Docker host behind Traefik, configuring all required DNS records, tuning for good deliverability, and securing the stack.
Requirements
Before starting, make sure you have:
- A Docker host (Debian 12 or Ubuntu 24.04 recommended)
- Docker Engine 24+ and Docker Compose plugin
- A domain you control (e.g.,
example.com) - Ability to modify DNS records (preferably with API access)
- Ports 25, 465, 587, 993, and 995 open on your firewall
- Reverse DNS (PTR) record from your ISP (mandatory for good deliverability to Gmail and Outlook)
- Traefik or another reverse proxy (optional but recommended for webmail)
Port Requirements
| Port | Protocol | Service |
|---|---|---|
| 25 | SMTP | Inbound mail |
| 465 | SMTPS | Submission (SSL) |
| 587 | SMTP | Submission (TLS) |
| 993 | IMAPS | IMAP over SSL |
| 995 | POP3S | POP3 over SSL |
| 80 | HTTP | Let’s Encrypt |
| 443 | HTTPS | Webmail |
Port 25 must be open globally. This is non-negotiable for an email server — other mail servers need to reach you on port 25. Check that your ISP does not block inbound port 25 (most residential ISPs do; business plans usually allow it).
Step 1 — Deploy Mailcow
Clone the repository and run the setup:
|
|
Generate the configuration:
|
|
This script asks for:
- Mail server hostname (FQDN) — e.g.,
mail.example.com - Timezone — use your local timezone (e.g.,
America/Santo_Domingo) - HTTP bind — leave as
0.0.0.0if Traefik handles termination - Skip Let’s Encrypt — set to
nif Traefik handles TLS externally
If Traefik handles TLS, edit mailcow.conf after generation:
|
|
This tells Mailcow to bind web services to localhost on port 8080, so Traefik can proxy to it without exposing HTTP directly.
Pull images and start the stack:
|
|
Wait a minute, then verify all containers are running:
|
|
You should see containers for: postfix, dovecot, rspamd, nginx, sogo, mysql (MariaDB), redis, clamav, unbound (DNS), olefy, and watchdog. Mailcow is a full stack.
Step 2 — DNS Records
This is the most critical part. Missing or misconfigured DNS records mean your emails will go to spam — or get rejected entirely.
A / AAAA Records
|
|
MX Record
Point the MX to your mail server hostname:
|
|
Priority 10 is standard for a single server. The trailing dot on
mail.example.com. is required by the DNS standard.
PTR Record (Reverse DNS)
Contact your ISP or use their control panel to set:
50.113.0.203.in-addr.arpa. IN PTR mail.example.com.
Most ISPs with a control panel have a “Reverse DNS” or “PTR” setting on the IP address page. Without a matching PTR record, Gmail and Outlook flag your mail as suspicious.
SPF Record
SPF (Sender Policy Framework) tells receiving servers which IPs are authorized to send mail for your domain:
|
|
This allows the IPs listed in your MX records to send mail, and soft-fail everything else. If you send through a third-party service (Mailgun, SendGrid), include their SPF include too:
|
|
DKIM Record
Mailcow generates DKIM keys automatically. Retrieve them from the web admin UI or directly:
|
|
Output looks like:
mail._domainkey IN TXT "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
Add this exact TXT record to your DNS:
|
|
DMARC Record
DMARC tells receivers how to handle mail that fails SPF or DKIM verification:
|
|
p=quarantine— move failing mail to spam (start here)p=reject— reject failing mail outright (after monitoring)p=none— monitor only, no actionrua— where aggregate reports are sent
Start with p=none, monitor reports for a week, then tighten to
p=quarantine. Move to p=reject only after you are confident
all legitimate mail is authenticated.
Verify DNS
|
|
All records should resolve before you send a single test email.
Step 3 — Traefik Reverse Proxy Integration
If you run Traefik (as covered in this blog’s Traefik guide), add a Compose override for the webmail interface.
Create docker-compose.override.yml in your mailcow directory:
|
|
Restart the stack:
|
|
This routes https://mail.example.com through Traefik with
automatic Let’s Encrypt. Mailcow’s internal nginx does not
terminate TLS — Traefik handles it at the edge.
Important: Disable Mailcow’s built-in ACME when using Traefik.
Set SKIP_LETS_ENCRYPT=y and HTTP_BIND=127.0.0.1 in
mailcow.conf to prevent port conflicts.
Step 4 — Initial Configuration and Security
Access the Admin UI
Open https://mail.example.com in a browser. The default admin
login is:
- Username:
admin - Password:
moohoo
Change this immediately in the admin panel under Configuration → Access → Edit admin.
Create Mailboxes
Go to Mailboxes → Add mailbox. Enter a full email address
([email protected]) and password. Mailcow automatically creates
the mailbox, IMAP folder structure, and aliases.
Disable Weak Ciphers
Mailcow’s Postfix defaults are reasonable, but you can tighten
them. Edit data/conf/postfix/extra.cf:
smtpd_tls_protocols = !SSLv2 !SSLv3 !TLSv1 !TLSv1.1
smtpd_tls_mandatory_protocols = !SSLv2 !SSLv3 !TLSv1 !TLSv1.1
smtpd_tls_mandatory_ciphers = high
smtpd_tls_eecdh_grade = ultra
Apply changes:
|
|
Rspamd Tuning
Mailcow bundles Rspamd with good defaults. For better spam
filtering, enable additional modules in the Rspamd UI
(https://mail.example.com/rspamd/):
- DMARC Reports under Configuration → DMARC
- Surbl / Spamhaus DBL — already configured
- Greylisting — enabled by default; tune the timeout if needed (most legitimate mail resends within minutes)
Set Up Fail2ban (Optional)
Mailcow includes its own fail2ban or you can install it on the host:
|
|
The watchdog container monitors SSH, Postfix SASL, and Dovecot login failures and auto-bans IPs.
Step 5 — Firewall Rules
Open only the ports your mail server needs. A minimal iptables/nftables ruleset:
|
|
Do not restrict port 25 source IPs. SMTP servers connect from anywhere. Rate-limit it instead if you see abuse:
|
|
If you have an IPv6 address on your mail server, add equivalent
ip6tables rules for all ports.
Step 6 — Testing Deliverability
SMTP Port Scan
From an external machine, verify your mail server responds on the expected ports:
|
|
Send a Test Email
Use the admin UI to send a test. Then check Mailcow’s logs:
|
|
Look for lines confirming successful delivery:
status=sent (250 2.0.0 Ok: queued as ABC123)
Check Rspamd History
In the Rspamd UI (/rspamd/), check the History tab. Every
scanned email shows a score, symbols matched, and whether it was
classified as spam or ham.
Use Mail-Tester
Send a test email to [email protected] from your new
mailbox. It returns a score out of 10 points with detailed
feedback on:
- SPF alignment
- DKIM signature validity
- Reverse DNS match
- SMTP configuration
- Blacklist status
A score above 9/10 is achievable with all DNS records configured correctly.
Blacklist Monitoring
Check your IP against common DNSBLs:
|
|
An empty response means you are not listed. If you are listed on Spamhaus or another blocklist, check your server for open relay or compromised mailboxes.
Step 7 — Backups
Mailcow stores everything in ./mailcow-dockerized/. Back up
the entire directory, plus the MariaDB database regularly.
Mailcow includes a built-in backup script:
|
|
This dumps the SQL database and archives mail data. Schedule it daily via cron:
0 3 * * * cd /opt/mailcow-dockerized && ./helper-scripts/backup_and_restore.sh backup all --delete-days 30
The --delete-days 30 flag keeps 30 days of backups automatically.
For off-site protection, sync the backup directory to a remote
server using rsync or rclone:
|
|
Step 8 — Monitoring and Maintenance
Check Queue Depth
A healthy outbound queue should be near zero:
|
|
If the queue grows beyond 100, investigate — you may have a compromised mailbox sending spam, or a remote server rejecting your mail.
Watch Logs
Monitor in real time:
|
|
Update Mailcow
Mailcow updates are handled via git:
|
|
Always check the Mailcow changelog before updating a production deployment.
Troubleshooting
Port 25 is blocked by ISP
You cannot run a Mailcow inbound server on a residential connection that blocks port 25. Options:
- Business ISP plan — most business fiber includes port 25
- Relay through a VPS — relay outgoing mail via a cheap VPS using Postfix transport maps
- Tunnel — use an SSH tunnel or WireGuard to forward port 25 through a VPS
Emails going to spam
Top causes:
- Missing reverse DNS — fix with your ISP
- Missing or broken DKIM — verify with
dig - SPF too permissive (
+allinstead of~all) — tighten it - IP on a blocklist — check and delist
- Sending from a residential IP range — much harder to fix; consider a relay
Cannot authenticate to SMTP submission
Ensure your mail client uses:
- Port 587 with STARTTLS (not port 25)
- PLAIN or LOGIN authentication
- Full email address as the username (
[email protected], not justuser)
Summary
Mailcow Dockerized turns the complexity of running a full email
server into a git clone + docker compose up -d workflow. The
stack handles Postfix, Dovecot, Rspamd, and webmail integration
out of the box, leaving you with just DNS configuration and
firewall rules to get right.
The essential checklist for a production-ready mail server:
- Clone Mailcow and generate config with
SKIP_LETS_ENCRYPT=y - Configure A, MX, PTR, SPF, DKIM, and DMARC DNS records
- Integrate with Traefik for TLS termination on webmail
- Secure Postfix ciphers and enable Rspamd greylisting
- Set up daily backups and off-site sync
- Test deliverability with mail-tester.com
A proper mail server in your homelab means no more depending on third-party providers for your domain’s email. It is not the simplest project, but it is one of the most empowering.