May 31, 2026 Β· 8 min read
ΒΆ Self-Hosting a Mail Server for $5/month
How I set up a full personal email system with Postfix, Dovecot, and AWS SES β without getting blocked by my ISP.
ΒΆ The Problem
I wanted me@hafeezh.com β a real mailbox I control, not a forwarding alias to Gmail. But I'm on Bell Canada residential internet, which blocks port 25 inbound. No port 25 = no receiving mail at home.
ΒΆ The Architecture
The solution: a $5/month AWS Lightsail instance as the mail server, with outbound relayed through AWS SES for deliverability.
Inbound: Internet β MX β Lightsail:25 β Postfix β Dovecot β Mailbox
Outbound: Thunderbird β Lightsail:465 β Postfix β SES β Internet
Reading: Thunderbird β Lightsail:993 (IMAPS) β Dovecot
Outbound: Thunderbird β Lightsail:465 β Postfix β SES β Internet
Reading: Thunderbird β Lightsail:993 (IMAPS) β Dovecot
ΒΆ What You Need
- A VPS with port 25 open (Lightsail, Hetzner, Contabo β NOT DigitalOcean)
- A domain with DNS you control (Route53 in my case)
- AWS SES for outbound relay (free tier: 1000 emails/month)
- ~30 minutes
ΒΆ Step 1: DNS Records
Set up these records for your domain:
MX hafeezh.com β 10 mail.hafeezh.com A mail.hafeezh.com β [your VPS IP] TXT hafeezh.com β "v=spf1 include:amazonses.com a:mail.hafeezh.com ~all" TXT _dmarc.hafeezh.com β "v=DMARC1; p=none; rua=mailto:me@hafeezh.com" CNAME [token]._domainkey β [token].dkim.amazonses.com (x3)
ΒΆ Step 2: Install Postfix + Dovecot
apt install postfix dovecot-imapd dovecot-lmtpd
Configure Postfix with virtual mailboxes and SES as the relay host. Configure Dovecot for IMAP with password-file auth. Add Let's Encrypt for TLS.
ΒΆ Step 3: Harden It
- Force TLS for all auth (no plaintext passwords)
- Fail2ban for brute-force protection
- Disable port 143 (plaintext IMAP) β only 993 (IMAPS)
- Rate limit auth attempts
ΒΆ Cost Breakdown
| Item | Cost |
|---|---|
| Lightsail nano (512MB) | $5/mo |
| SES (under 1000 emails) | ~$0 |
| Let's Encrypt | Free |
| Total | $5/mo |
ΒΆ Gotchas
- SES sandbox mode β you must request production access before you can send to anyone
- docker-mailserver needs 2GB+ RAM β don't try it on a 512MB instance, it'll OOM
- DigitalOcean blocks port 25 β use Lightsail, Hetzner, or Contabo instead
- Bell/Rogers block port 25 residential β you can't host at home in Canada
Tagged: mail self-hosting aws