Should You Host Your Own Email? (And How, with Mailcow, If You Still Want To)

Everything else in this series is a clear win to self-host. Email is different. The reasons are not technical — Mailcow makes the technical part almost easy — they're about reputation: big providers decide whether your mail is spam, and a home IP address is spam by default. This tutorial gives the honest case, then the full setup for the people who've read it and still want to.
The honest case
- Home IPs are blocked. Residential address ranges are on every spam blocklist. Mail sent from home lands in spam or is refused outright. You need a VPS (a cheap cloud server) with a clean IP, so this is the one tutorial that isn't about your home box.
- Reputation takes months. A new IP sending mail is treated with suspicion until it has history. Expect some early mail to Gmail and Outlook.com to go to spam even with perfect DNS.
- It must never be down. Other servers retry for a day or two, then give up and bounce. A week of downtime loses mail.
- Security is on you. A compromised mail server becomes a spam cannon within hours. Updates, Fail2ban/CrowdSec, 2FA, backups: all mandatory.
- The alternative is cheap. Fastmail, Proton, or your own domain on Migadu or Purelymail costs a few pounds a month for someone else to carry all of this.
A sensible middle: host the mailboxes yourself for privacy and control, but send through a relay (Amazon SES, Mailgun, Postmark, or your provider's SMTP) whose reputation is established. Mailcow supports this out of the box.
Still here? Then:
Quick reference
| Piece | What |
|---|---|
| Server | a VPS with 4 GB RAM, ports 25/465/587/993/443 open, reverse DNS set |
| Software | Mailcow: dockerized — Postfix, Dovecot, Rspamd, SOGo webmail, in one compose |
| DNS | A, MX, SPF, DKIM, DMARC, PTR (reverse), autoconfig |
| Admin | https://mail.example.com — admin / moohoo (change!) |
| Clients | IMAP 993 / SMTP 587 with STARTTLS, or SOGo webmail |
| Outbound relay | Configuration → Routing → Sender-dependent transports |
1. The VPS and reverse DNS
Pick a provider that lets you set reverse DNS (PTR) and doesn't block port 25 (Hetzner, OVH and most VPS hosts do; many clouds block 25 by default — ask). Set the server's hostname to mail.example.com, and the PTR record for its IP to the same name. Check the IP isn't already on blocklists at mxtoolbox.com before you commit.
2. Install Mailcow
sudo apt install docker-ce docker-compose-plugin git -y # Docker as in tutorial 24
cd /opt && sudo git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
sudo ./generate_config.sh # hostname: mail.example.com, timezone
sudo docker compose pull && sudo docker compose up -d
Fifteen containers start. Open https://mail.example.com, log in admin / moohoo, change the password, enable 2FA for the admin.
3. DNS records
In your domain's DNS:
| Type | Name | Value |
|---|---|---|
| A | the VPS IP | |
| MX | @ | mail.example.com (priority 10) |
| TXT | @ | v=spf1 mx -all |
| TXT | dkim._domainkey | the key from Mailcow Configuration → ARC/DKIM keys |
| TXT | _dmarc | v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com |
| CNAME | autoconfig, autodiscover | mail.example.com |
| SRV | _autodiscover._tcp | as Mailcow's DNS page shows |
Mailcow's Configuration → Mail setup → Domains → DNS button shows every record for your domain with a green/red check. Get them all green before sending anything.
4. Domain and mailboxes
Mail setup → Domains → Add domain example.com. Then Mailboxes → Add: john@example.com, password, quota. Aliases (info@, shop@) under Aliases; a catch-all if you like.
5. Test deliverability
Send to a mail-tester.com address and read the score; it checks SPF, DKIM, DMARC, PTR and blocklists and tells you exactly what's wrong. Aim for 10/10. Then send to a Gmail account and look at the headers (Show original): spf=pass dkim=pass dmarc=pass.
6. Sending through a relay (recommended)
Configuration → Routing → Sender-dependent transports: add SES/Mailgun/Postmark's SMTP host, port 587, username and password; then assign it to the domain under Domains → edit → Sender-dependent transport. Your server receives and stores mail; the relay's reputation delivers it. The best of both.
7. What you get
SOGo webmail with calendar and contacts (CalDAV/CardDAV for phones), Rspamd antispam with a learning quarantine, DKIM signing, sieve filters, full-text search, app passwords per client, 2FA, and a sync of everything via IMAP. Clients: Thunderbird, Outlook, Apple Mail, K-9 — with autoconfig, they set themselves up from the address.
8. Keep it alive
- Mailcow updates: sudo ./update.sh monthly, after a backup (./helper-scripts/backup_and_restore.sh backup all).
- Fail2ban is built in (Netfilter container); watch its log in the admin UI.
- Uptime Kuma (35) checking port 25 and 993 from home; Healthchecks (104) on the backup.
- Watch the DMARC reports arriving at dmarc@ — they show who's sending as your domain.
- A second MX (a backup host or a cheap relay) if a day of downtime would hurt.
Troubleshooting
Mail to Gmail goes to spam with all green DNS. Reputation. Send a little, consistently, for weeks; use the relay for important mail meanwhile.
Port 25 refused outbound. The VPS host blocks it; ask them, or use the relay (which uses 587).
"Relay access denied" from a client. The client is using port 25; use 587 with authentication.
Mailcow UI unreachable after a reboot. docker compose up -d in /opt/mailcow-dockerized; check disk space — a full disk stops Dovecot.
Wrapping up
If you want to own your mailboxes, a VPS with clean reverse DNS, Mailcow, every DNS record green, and a sending relay gets you there in an afternoon — with webmail, calendar and antispam thrown in. If you don't want to carry the reputation and uptime burden, there is no shame in paying someone a few pounds a month; every other tutorial in this series will still be here.
