Self-Host Your Email with Mailu
TL;DR
You can replace Google Workspace ($6/user/month) with Mailu — a Docker-based open source mail server — and pay only server costs (~$6-12/month). It's a legitimate path for technical teams prioritizing privacy and cost control. But self-hosting email is genuinely hard: DNS misconfiguration means your emails go to spam, IP reputation takes weeks to build, and a single mistake can get your IP blacklisted. This guide walks through the full setup and helps you decide if it's worth it.
Key Takeaways
- Mailu is a Docker-first mail server — SMTP, IMAP, webmail, spam filtering, and admin UI in one stack
- DNS records are the hardest part — MX, SPF, DKIM, DMARC, and PTR records must all be correct for deliverability
- IP warm-up is mandatory — Gmail and Outlook apply strict filtering to new IPs; ramp up slowly
- Mailu vs Mailcow: Mailu = simpler, better docs; Mailcow = more features, bigger community
- When to self-host email: privacy-critical orgs, developers learning the stack, personal domains
- When NOT to: transactional email (use Resend/Postmark instead), teams without a sysadmin
Should You Self-Host Email?
Be honest about the trade-offs before starting.
Self-hosting email is right for:
- Personal or organizational domains where privacy matters (no Google scanning your emails)
- Technical teams with a dedicated sysadmin
- Learning how email infrastructure works
- Cost reduction at scale (10+ mailboxes)
Don't self-host email if:
- You need transactional email (welcome emails, password resets) — use Resend or Postmark instead
- You don't have time to maintain it (spam filters update constantly)
- Your IP address changes or you're on a residential connection
- You need Google Workspace's collaborative features (Docs, Calendar, Meet)
Rule of thumb: Self-host email only if you're willing to own the deliverability problem. It works, but it requires ongoing attention.
Mailu vs Mailcow: Which Self-Hosted Email Server?
The two dominant Docker-based mail servers:
| Feature | Mailu | Mailcow |
|---|---|---|
| Setup complexity | ⭐ Simpler | More complex |
| GitHub Stars | ~6,500 | ~9,000 |
| Webmail | Roundcube included | SOGo + Roundcube |
| Admin UI | ✅ Clean | ✅ Feature-rich |
| Spam filtering | Rspamd | Rspamd |
| 2FA | ✅ | ✅ |
| ARM support | ✅ | Limited |
| Kubernetes support | ✅ | ❌ |
| Documentation | Good | Excellent |
| Community | Medium | Large |
| Best for | Simplicity | Full-featured deployments |
Recommendation: Start with Mailu if you want a simpler setup. Switch to Mailcow if you need more features or find Mailu limiting.
Part 1: Server Prerequisites
VPS Requirements
Email requires a dedicated static IP — not a shared host:
- Minimum: 2 vCPU, 2 GB RAM, 20 GB storage
- Recommended: Hetzner CX22 (€4.35/month) — dedicated IP included
- Critical: Your provider must allow port 25 (SMTP). Some cloud providers block it by default. Hetzner, OVH, and most VPS providers allow it; AWS, GCP, and Azure block port 25 by default.
Check Port 25
Before installing anything, verify your VPS can send on port 25:
# Check if port 25 is open (from your VPS):
telnet smtp.gmail.com 25
# If it times out, your provider is blocking it
Reverse DNS (PTR Record)
This is non-negotiable. Your IP address must resolve back to your mail server hostname. Set this in your VPS provider's control panel:
YOUR_SERVER_IP → mail.yourdomain.com
Hetzner: Server → Networking → Edit PTR record
DigitalOcean: Networking → Domains → Add reverse record
Part 2: DNS Configuration
Before installing Mailu, configure all DNS records (these take up to 48 hours to propagate):
Required Records
# MX record — tells other servers where to deliver email
yourdomain.com. IN MX 10 mail.yourdomain.com.
# A record — IP of your mail server
mail.yourdomain.com. IN A YOUR_SERVER_IP
# SPF — which servers can send mail for your domain
yourdomain.com. IN TXT "v=spf1 ip4:YOUR_SERVER_IP ~all"
# DMARC — policy for failed authentication (start permissive)
_dmarc.yourdomain.com. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com"
DKIM: Generated by Mailu after installation — add after setup.
Autoconfig Records (optional but recommended)
These allow email clients (Thunderbird, Outlook) to auto-configure:
autoconfig.yourdomain.com. IN CNAME mail.yourdomain.com.
autodiscover.yourdomain.com. IN CNAME mail.yourdomain.com.
Part 3: Install Mailu
Generate Configuration
Use Mailu's official setup wizard at setup.mailu.io to generate your docker-compose.yml and mailu.env.
Key settings to configure:
- Domain:
yourdomain.com - Hostname:
mail.yourdomain.com - TLS flavor:
letsencrypt(automatic SSL) - Webmail:
roundcube(recommended)
Download both generated files to your server:
mkdir /mailu && cd /mailu
# Download the generated files from setup.mailu.io
# Or use the config generator CLI
Deploy
cd /mailu
docker compose up -d
Mailu starts the following services:
- front — Nginx reverse proxy + SSL termination
- admin — Web admin interface
- imap — Dovecot IMAP server
- smtp — Postfix SMTP server
- antispam — Rspamd
- webmail — Roundcube
Create Your First Admin Account
docker compose exec admin flask mailu admin admin yourdomain.com 'SecurePassword123'
# Creates admin@yourdomain.com with admin privileges
Access the admin UI at https://mail.yourdomain.com/admin.
Part 4: Configure DKIM
DKIM keys are generated by Mailu on startup. Retrieve your public key:
docker compose exec admin flask mailu dkim yourdomain.com
This outputs a DNS TXT record like:
dkim._domainkey.yourdomain.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0..."
Add this to your DNS. After propagation (up to 48 hours), verify:
# Verify DKIM is publishing correctly:
dig TXT dkim._domainkey.yourdomain.com
Tighten DMARC After Verification
Once SPF and DKIM are working (check via mail-tester.com):
# Phase 1 — monitor only:
_dmarc.yourdomain.com. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com"
# Phase 2 — quarantine (after 2 weeks of clean reports):
_dmarc.yourdomain.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com"
# Phase 3 — reject (full enforcement):
_dmarc.yourdomain.com. IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc@yourdomain.com"
Part 5: Test Deliverability
Before sending any real email, verify your setup:
# 1. Test DNS records:
dig MX yourdomain.com
dig TXT yourdomain.com # Should show SPF
dig TXT dkim._domainkey.yourdomain.com # Should show DKIM
dig TXT _dmarc.yourdomain.com # Should show DMARC
# 2. Check blacklists (run from your server):
curl -s "https://api.hetrixtools.com/v2/blacklist-check/YOUR_SERVER_IP/"
# 3. Send a test email to mail-tester.com:
# Visit mail-tester.com, get a unique address, send to it, check your score
# Aim for 9/10 or higher before sending real email
IP Warm-Up Schedule
Gmail and Outlook treat new IPs with heavy suspicion. Follow this ramp-up:
Week 1: 10-50 emails/day (to engaged recipients only)
Week 2: 50-200 emails/day
Week 3: 200-500 emails/day
Week 4+: Scale gradually based on bounce/spam rates
Never blast a large list from a new IP. The first emails should go to people who know you and will mark them as "not spam" if needed.
Part 6: Adding Mailboxes
Via the admin UI at https://mail.yourdomain.com/admin:
- Users → Add User → Set email, password, quota
- Aliases → Add alias (e.g.,
hello@→admin@) - Domains → Add additional domains (multi-domain setup)
Or via CLI:
# Add a user:
docker compose exec admin flask mailu user jane yourdomain.com 'Password123'
# Add an alias:
docker compose exec admin flask mailu alias info yourdomain.com jane
Connecting Email Clients
Mailu auto-generates client configuration for:
- IMAP:
mail.yourdomain.com:993(SSL/TLS) - SMTP:
mail.yourdomain.com:587(STARTTLS) - Webmail:
https://mail.yourdomain.com
For Thunderbird, the autoconfig endpoint auto-detects settings when you enter your email address.
Ongoing Maintenance
Self-hosting email requires ongoing attention:
Monthly tasks:
- Check spam score at mail-tester.com
- Review DMARC reports (if using a reporting service like DMARC Analyzer)
- Check your IP against blacklists
When updates release:
cd /mailu
docker compose pull && docker compose up -d
Backup email data:
# Backup mailboxes (Dovecot IMAP storage):
tar -czf mail-backup-$(date +%Y%m%d).tar.gz /mailu/mail/
Cost Comparison
| Option | Monthly Cost (5 users) | Notes |
|---|---|---|
| Google Workspace Starter | $30/mo | $6/user |
| Microsoft 365 Business Basic | $30/mo | $6/user |
| Fastmail | $25/mo | $5/user |
| Mailu (self-hosted) | ~$6-12/mo | Server cost only |
| Proton Mail Plus | $50/mo | Privacy-focused managed |
Self-hosting saves ~$25-50/month for a 5-person team — meaningful for bootstrapped startups, but less meaningful once you factor in maintenance time.
Methodology
- Mailu documentation: mailu.io/docs
- Mailu GitHub: github.com/Mailu/Mailu
- Email authentication specs: Google, DMARCLY, RFC standards
- Comparison sources: RunCloud, GeekFlare, It's FOSS (2025-2026)
Compare all open source Google Workspace alternatives at OSSAlt.com.