Self-Hosting Email in 2026 - Smart Move or Fool's Errand?
As part of my self-hosting journey, over time I've found an increasing need to have my own mail server. A great example is this blog - it's running on Ghost, and as part of its configuration is that it needs a mail server to send account-related emails for both admins and users who subscribe. Plus, I value privacy - not to a ridiculous extent, I still use TikTok and Instagram - but enough that I'd rather not have my personal emails read by the biggest companies in the world in order to sell me stuff.
So that necessitates the question - do I host it myself, or outsource it to someone like VentraIP who can do it for me? There's a few considerations:
Self-Hosting
- Am I comfortable learning the complexities of email hosting - the configuration of SMTP and IMAP; SPF, DKIM and DMARC headers; forward-confirmed reverse DNS (FCrDNS)?
- Am I comfortable maintaining that configuration long-term?
- Am I comfortable with potential email downtime because I misconfigured something, or my power or internet goes out? Remember - if my server is down and the sender gives up retrying, that email is gone - forever.
- Am I comfortable dealing with email deliverability issues?
Outsourced Hosting
- Am I comfortable with a third-party being able to read my unencrypted emails in plaintext on disk or in transit?
- How much am I willing to pay for that service?
If you ask Reddit, the answer is an almost overwhelming probably not. But I love a challenge, so I decided to take it on.
Step 1 - Architecture
The first thing I had to work out is - how am I going to set this up? In particular, the important question is how am I going to set it up so that all the necessary criteria are met, particularly redundant incoming mail servers and FCrDNS?
The first one requirement, redundancy, is relatively simple - one home mail server, running in a Proxmox VM - and one cloud mail server, running on a VM I have full control over. While having a secondary mail server on someone else's hardware isn't perfect security-wise, I made the decision that having redundancy during downtime and maintenance at home was worth the privacy risk here. I did decide to implement some mitigating controls though:
- My home mail server would have priority in MX records - sending mail servers should always send directly to it first.
- The cloud mail server would act only as a cache - when mail is received by it, it will be immediately retrieved by the primary home server when it comes back online and will then be deleted from the cloud server.
- No mailboxes to live on the cloud server - users can only access their mail via webmail or IMAP/POP when the home server is online (that's a sacrifice I was willing to make, as long as the emails aren't lost).
- Communication between my home network and the cloud mail server will be exclusively via a WireGuard tunnel, with one endpoint being the cloud mail server itself, and the other being an OPNsense VM on my Proxmox host that I use as a VPN concentrator.
- The cloud mail server's disk will be encrypted at rest.
The second one requirement, FCrDNS, is more complicated. Only one of my servers technically needs to meet this requirement - I can live with outbound email having one failure point, as disruption to sent mail isn't as catastrophic as disruption to incoming mail.
My first port of call was my ISP - Telstra. A static IP was easy - a form on their website, an outrageous $10 a month charge and boom - static IP. DNS was harder, and by harder, I mean impossible.
First, live chat told me it was impossible. Not taking the L1 support's word for it, I escalated to L2 - and was given a number to call. First call attempt - "sorry, we're only open 9am - 6pm weekdays." Second call attempt and some terrible hold music later, and the technician finally tells me that they only do that for business connections only. Rats.
The second attempt was my cloud server provider. Looking through all the options, it seems the cheapest to run 24x7 (without having to worry about Spot VMs) was a t4g.nano instance from AWS - with 2 vCPUs, 500 MiB of memory, 8 GiB storage and 1 Elastic IP, it would run me about $12 AUD a month.
They have a well-known limitation on using port 25 for EC2 instances, but you can request to have that limitation removed. So I decided to give that a go and worry about it later.
Step 2 - Setup
Now that I'd worked out what the architecture would look like, the next step was to set up the actual software and servers. But hold on - what software would I use?
I trawled what felt like hundreds of Reddit posts, and trawled through the awesome-selfhosted list's email section, and ultimately decided on Mailcow. Now, I love to tinker - but looking at all the required components (spam prevention, IMAP/POP, SMTP, webmail, antivirus, etc) I decided that even I didn't have that much patience and decided to go with an all-in-one solution.
It wasn't the perfect setup I envisioned - for example, it uses a MySQL DB in its compose.yml file when I'd rather using an existing MySQL server I have running in my environment - but it did enough of what I needed.
There was a few additional quirks I needed to figure out as well that slowed me down. Since I use wildcard certificates only to prevent subdomain discovery via Certificate Transparency, I needed a way to stop Mailcow from attempting to generate its own certs via ACME and instead use one I generated myself via DNS-01 challenge with my Cloudflare (my nameserver) API key.
I managed to do it using this guide on certbot-dns-cloudflare and a 2am renewal cronjob that ran a post-hook script to copy the certificates from the certbot directory to Mailcow's and restart the container. If you want more detailed info on how that works, let me know with a comment.
Additionally, I had to setup the Postfix SMTP server on my AWS instance. With a few Google searches and Gemini prompts, I was able to come up with a secure closed-relay config for it, which wasn't too hard. Probably took me an hour or less.
Finally, I had to connect my AWS instance with my home network. Turns out - not that hard either! WireGuard is pretty simple. The hardest part was getting the OPNsense VM on the home side to connect, given it's behind an old Palo firewall in my garage, which is also behind my home router (a Unifi UCG Ultra) - yes, that's a lot of layers of NAT. A story for another time.
Thankfully, AWS makes it easy to set the rDNS for an Elastic IP - they now just have a button for it in the AWS console. To make me a little bit less anxious about using the cloud, I also spent an hour configuring AWS budgets - using a budget limit of $15 USD, I configured so that when the limit threshold is crossed, it uses AWS Systems Manager to immediately shut down my EC2 instance. Eventually, I'll configure it to use a Lambda to shut down every EC2, RDS and other service it can find in the account (in case a bad actor gets access to it), but this satisfied my anxiety for now.
The final step was to get port 25 unblocked outbound for the EC2 instance. At that's where more trouble hit.
Step 3 - Deliver-inability
First, I raised a case with AWS support. They were slow to inform me that a normal support case was actually the wrong path - there's another form to use! So I filled out that form - specifying my email address, the elastic IP and EC2 instance I wanted to use, what my use-case was for sending email from EC2, and what measures I'd taken to ensure that no spam would be sent from my address.
And within 10 minutes, I received a reply telling me that my request had been denied.
Now this was a real pain in the ass. What was I supposed to do, what recourse did I have? I re-opened my original support case with AWS, and essentially told them "oi - wtf?", but it's been two weeks with no additional reply.
So today, writing this article, I decided - hey, what the hell, let me try that form again. I'm now actually publishing my first article, and getting my sole trader ABN sorted out, so maybe they'll actually take a closer look!
And in writing this article and checking my configuration to confirm it was all correct, I found a critical mistake - I'd cocked up my SPF record.
What it should've been?
v=spf1 ip4:3.104.212.102 ip4:124.187.51.37 -all
What it was?
v=spf1 ip4: 3.104.212.102 ip4:124.187.51.37 -all
That's right, a single space between ip4 and my Elastic IP address. MX Toolbox's Email Health checker is what confirmed it for me.
After I fixed that up, I had another thought - 10 minutes is pretty fast for a human to review and deny my request. Maybe an automated script saw my misconfigured SPF record and rejected my request outright.
As of writing this post, my new request to get port 25 unblocked is still pending with AWS - and it's been longer than 10 minutes this time, which is a good sign.
Conclusion - Worth it?
So far - I can't answer that. If AWS unblocks port 25 on my instance and I can email the major providers without deliverability issues, my answer will likely be yes. But for everyone - I can't answer that.
If you love tech like I do, love a good challenge, love understanding how and why technologies like SMTP work the way they do, and value your privacy - then yes, I'd say it is.
But I'd say for the majority of people, I'd say probably not. Definitely not for novices, and even for some hobbyists its probably more troubleshooting and stress than it's worth. But isn't that part of the challenge?
If you are even considering it though, my advice to you would be - try it! Give it a go. The worst thing that will happen is you lose a few hours, delete it all and try out a more privacy-focused email provider instead. But even if that's the case, you'll have learned more about the inner workings of SMTP, what SPF, DKIM and DMARC records do and how to configure them, and spent some time on an interesting problem that you otherwise would've spent browsing TikToks anyway.
Note to the reader
This is my first post on my new blog! What were your thoughts? Did you like it, have some feedback, or think it was boring?
Obviously given the above, with my outbound email sending still pending, the blog's sending and sign-ups don't work yet. But keep this in mind - and in the future, when it is working, please don't hesitate to sign-up and drop me a comment.
Thanks for taking the time to read it!