How to Self-Host Mailcow: Complete Email Server 2026
TL;DR
Mailcow (GPL 2.0, ~8K GitHub stars) is the most complete self-hosted email server stack. It ships Postfix (SMTP), Dovecot (IMAP), SOGo (webmail + CalDAV/CardDAV), Rspamd (spam filtering), ClamAV (antivirus), and a polished web UI — all in one Docker Compose stack. Google Workspace charges $6/user/month ($72/year). Mailcow self-hosted is free for unlimited users on your own hardware. The DNS setup takes 30 minutes; after that, you have a production-grade email server.
Key Takeaways
- Mailcow: GPL 2.0, ~8K stars — Postfix + Dovecot + SOGo + Rspamd in one Docker stack
- DNS critical: SPF, DKIM, DMARC, and PTR records are required for email deliverability
- SOGo webmail: Full webmail interface with calendar (CalDAV) and contacts (CardDAV)
- Rspamd: AI-powered spam filter with web UI — much better than SpamAssassin
- Email aliases: Unlimited aliases per domain, catchall addresses, per-mailbox limits
- ClamAV optional: Disable on low-RAM servers (< 2GB) — uses ~700MB RAM
Prerequisites
- VPS with static IP — cloud server at Hetzner, DigitalOcean, Vultr, etc.
- Minimum specs: 2 CPU, 4GB RAM (6GB recommended if enabling ClamAV)
- Port 25 unblocked — many residential ISPs block port 25; VPS providers usually allow it
- A domain you control — e.g.,
yourdomain.com - Reverse DNS (PTR) record — set in your VPS control panel to match your hostname
Part 1: Docker Setup
# Install Mailcow (official installer):
cd /opt
git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
# Generate configuration:
./generate_config.sh
# Prompts for:
# - Hostname: mail.yourdomain.com
# - Timezone: America/Los_Angeles
# Review mailcow.conf:
cat mailcow.conf
Key settings in mailcow.conf:
# mailcow.conf
MAILCOW_HOSTNAME=mail.yourdomain.com
TZ=America/Los_Angeles
# Disable ClamAV on low-RAM servers:
SKIP_CLAMD=y
# Skip unbound DNS resolver (use host DNS):
SKIP_UNBOUND=y
# HTTP/HTTPS ports (if Caddy/Nginx handles TLS):
HTTP_PORT=8080
HTTPS_PORT=8443
HTTP_BIND=127.0.0.1
HTTPS_BIND=127.0.0.1
# Start Mailcow:
docker compose pull
docker compose up -d
# Check all services are running:
docker compose ps
Services that start:
mailcow-postfix— SMTP (25, 587, 465)mailcow-dovecot— IMAP/POP3 (143, 993, 110, 995)mailcow-rspamd— Spam filteringmailcow-sogo— Webmailmailcow-nginx— Internal reverse proxymailcow-mysql— Databasemailcow-redis— Cachemailcow-clamd— Antivirus (if enabled)
Part 2: Reverse Proxy with Caddy
mail.yourdomain.com {
reverse_proxy localhost:8080 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
Visit https://mail.yourdomain.com — log in with admin / moohoo (change immediately).
Part 3: DNS Configuration
DNS is the most critical part of email deliverability. Configure all of these:
A and MX records
; A record for your mail server:
mail.yourdomain.com. IN A YOUR.SERVER.IP
; MX record — points to your mail server:
yourdomain.com. IN MX 10 mail.yourdomain.com.
SPF record (prevents spoofing)
yourdomain.com. IN TXT "v=spf1 mx ~all"
This says: only servers listed in MX are allowed to send email for this domain.
DKIM record (cryptographic signing)
# Get your DKIM public key from Mailcow UI:
# Configuration → Domains → yourdomain.com → DKIM → Show public key
; DKIM record (long TXT record from Mailcow UI):
dkim._domainkey.yourdomain.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9..."
DMARC record (policy enforcement)
; Start with p=none (monitoring only), upgrade after confirming delivery:
_dmarc.yourdomain.com. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com"
; After 2-4 weeks, upgrade to quarantine:
_dmarc.yourdomain.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com"
; After confirming no legitimate email is failing, upgrade to reject:
_dmarc.yourdomain.com. IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc@yourdomain.com"
Reverse DNS (PTR) — set in VPS control panel
YOUR.SERVER.IP → mail.yourdomain.com
Autoconfiguration records (for email clients)
; Mozilla Thunderbird/GNOME Evolution autodiscover:
autoconfig.yourdomain.com. IN CNAME mail.yourdomain.com.
; Outlook autodiscover:
autodiscover.yourdomain.com. IN CNAME mail.yourdomain.com.
; SRV records for IMAP/SMTP:
_imap._tcp.yourdomain.com. IN SRV 0 1 143 mail.yourdomain.com.
_imaps._tcp.yourdomain.com. IN SRV 0 1 993 mail.yourdomain.com.
_submission._tcp.yourdomain.com. IN SRV 0 1 587 mail.yourdomain.com.
_submissions._tcp.yourdomain.com. IN SRV 0 1 465 mail.yourdomain.com.
Test your DNS
# Verify all records:
dig MX yourdomain.com
dig TXT yourdomain.com # SPF
dig TXT dkim._domainkey.yourdomain.com # DKIM
dig TXT _dmarc.yourdomain.com # DMARC
dig -x YOUR.SERVER.IP # PTR/reverse DNS
# Send a test email and check score:
# mail-tester.com — aim for 10/10
Part 4: Admin UI — Domains and Mailboxes
Add a domain
- Configuration → Domains → Add domain
- Domain:
yourdomain.com - Max mailboxes, quota, aliases
- Enable DKIM: generate 2048-bit key → copy TXT record to DNS
Create mailboxes
- Configuration → Mailboxes → Add mailbox
- Username:
hello(creates hello@yourdomain.com) - Quota: 10GB (or 0 for unlimited)
- Active: yes
Create aliases
# Example aliases via UI:
# postmaster@yourdomain.com → hello@yourdomain.com
# abuse@yourdomain.com → hello@yourdomain.com
# info@yourdomain.com → hello@yourdomain.com
# Catchall — catch all unmatched addresses:
# @yourdomain.com → hello@yourdomain.com
Part 5: Email Clients
Desktop (Thunderbird)
Autoconfiguration usually works automatically:
- Thunderbird → Add account
- Enter name, email, password
- Thunderbird auto-discovers IMAP/SMTP settings
Manual settings:
IMAP: mail.yourdomain.com:993 (SSL/TLS)
SMTP: mail.yourdomain.com:587 (STARTTLS)
Username: hello@yourdomain.com
iOS / macOS
- Settings → Mail → Add Account → Other
- Add Mail Account → name, email, password
- IMAP server:
mail.yourdomain.com, SSL, port 993 - SMTP server:
mail.yourdomain.com, STARTTLS, port 587
Webmail (SOGo)
Access at https://mail.yourdomain.com/SOGo — full webmail with:
- Email composer with rich text
- Calendar (CalDAV — sync to iOS/macOS/Android)
- Address book (CardDAV)
Part 6: Rspamd (Spam Filtering)
Rspamd is Mailcow's spam engine — far superior to SpamAssassin:
Access Rspamd web UI
https://mail.yourdomain.com/rspamd
Default password in mailcow.conf → RSPAMD_PASSWORD
Train the spam filter
# Mark email as spam (trains Rspamd):
# In webmail: move message to Junk folder → Rspamd learns
# Via CLI:
docker exec -it mailcow-rspamd rspamc learn_spam < /path/to/spam.eml
docker exec -it mailcow-rspamd rspamc learn_ham < /path/to/legitimate.eml
Spam action thresholds
| Score | Action |
|---|---|
| < 5 | Deliver normally |
| 5-10 | Add [SPAM] header, deliver |
| > 10 | Reject |
| Greylisting | Hold 5 min then retry |
Adjust in Configuration → Configuration files → rspamd/local.d/actions.conf:
reject = 15;
add_header = 6;
greylist = 4;
Part 7: Backup and Restore
# Backup script (add to cron):
cd /opt/mailcow-dockerized
# Export all data:
./helper-scripts/backup_and_restore.sh backup all
# Backup created in: /opt/mailcow-dockerized/backups/
# Restore:
./helper-scripts/backup_and_restore.sh restore
# Manual MySQL backup:
docker exec mailcow-mysql mysqldump -u root --password="$(grep DBPASS mailcow.conf | cut -d= -f2)" mailcow \
| gzip > mailcow-db-$(date +%Y%m%d).sql.gz
# Backup mail data (Dovecot volumes):
tar -czf mailcow-mail-$(date +%Y%m%d).tar.gz \
$(docker volume inspect mailcow-dockerized_vmail-vol-1 --format '{{.Mountpoint}}')
Part 8: Maintenance and Updates
# Update Mailcow (run monthly):
cd /opt/mailcow-dockerized
./update.sh
# Check mail queue:
docker exec mailcow-postfix mailq
# Flush the queue:
docker exec mailcow-postfix postfix flush
# Postfix logs:
docker compose logs postfix -f
# Dovecot logs (IMAP):
docker compose logs dovecot -f
# Check TLS/certificate expiry:
docker exec mailcow-postfix openssl s_client -connect mail.yourdomain.com:993 </dev/null 2>&1 | grep -E "notAfter|subject"
Deliverability Checklist
Before sending to real recipients, verify:
- MX record resolves to your server IP
- PTR/reverse DNS matches your hostname
- SPF includes your server
- DKIM key published and signing works
- DMARC policy set (start with
p=none) - Port 25 not blocked by VPS provider
- mail-tester.com score: 9+/10
- Not on blocklists: check at mxtoolbox.com/blacklists
See all open source email tools at OSSAlt.com/categories/email.