For a while now, I’ve wanted to host my own mail server. It seems like a logical extension to all the self-hosting I’ve been doing - it’s kinda the low-hanging fruit in terms of taking back ownership and governance of my data.
But I’ve been putting it off and putting it off, it’s something I haven’t had the gumption to dive into. Every time I get to talking to one of my coworkers about email my head starts spinning. POP, IMAP, DMARC, SPF, DKIM, MX, SMTP, on and on. Too many acronyms. The concept of email is far older than I am and so many things have been bolted on to get us to where we are now.
How do I take this ultimately simple protocol and make it comparable to a SaaS email service? How do I compete?
That was what I thought for a long time, I’ve done a lot of musing about it. What are my goals, where am I okay compromising, how do I secure it, do I host it at home or on a VPS, so on.
I decided to take a first step with SimpleLogin. It’s not an email server, just an email aliasing service. It is open source and has a self-hosted option - which is good, because I didn’t want to just transfer the attack surface to a third-party and centralize much of my data to another server.
Email aliasing makes sense as a stopgap or a first step. Obfuscate your real email address, be able to create “throwaway” emails but still be able to receive the emails sent to that address.
SimpleLogin
So I spun up a pretty low-key VPS and went to work.
(Along with this process I went ahead and created a reference for spinning up a VPS. Over the past couple days I’ve gone through this process 3 times. While similar to my basic Debian deployments, I try to be a bit more security-conscious when working on a publicly accessible machine.)
SimpleLogin has some very detailed documentation located here which was helpful in this endeavor. I won’t go into detail in the process since I basically followed the documentation to the letter. I spent about 2 hours getting everything up and running - I completely missed two docker run commands the first time around somehow, I forgot to spin up the email handler and job runner docker containers entirely. That aside it went pretty smoothly, even getting the reverse proxy up and running via nginx.
That is, until I went to sign up. I simply did not receive the email. I checked and re-checked the configuration, checked on the logs and I kept seeing a bounce in the email handler container. I followed some of the troubleshooting steps including testing with swaks
to send an email. That one went through, albeit with an extra .tld
appended (it showed up as from user@mydomain.tld.tld
). But no matter what I messed with, the welcome email didn’t send. (I was using a Protonmail account, which is what SimpleLogin recommends.)
Eventually, I tried signing up with a Gmail account, and lo and behold it sent. Granted it went to spam, but it sent, and it was coming from the correct user.
At this point, it was getting late in the evening, and the fact that the email provider that SimpleLogin specifically recommended was not working with their service just didn’t sit well with me.
I said fuck it. I’ve figured out how to set all these damn DNS records, that seems to be the hard part anyway. It’s sending. I bought a domain name, I have a VPS with 50+ gigs of storage. Why not just give an email server a whirl?
Luke saves the day
Luke Smith has published this lovely script that is supposed to deploy a fully-fledged email server almost from scratch. I’ve known about it for a while but I still hadn’t wanted to dive in just yet. (I know I’m about to go down all the mail server rabbit holes in the coming weeks.)
I gave it the old college try. Nuked my SimpleLogin server, deleted all the DNS records except for the couple that needed to be in place for Certbot to generate a certificate, and spun up the script on a fresh install of Debian.
Other than a couple hiccups, it honestly worked like a charm:
For some odd reason, the host
command didn’t return anything when run on the server itself. My DNS was propagating just fine but the server couldn’t return its own IP. I’m not sure. I edited /etc/resolv.conf
to some public DNS resolver and it worked just fine - might just be a weird thing with my hosting provider. The other thing I had to do was comment out the line for the IPv6 check since I didn’t have a public IPv6 address on the mailserver.
After completion, it gave me the DNS records to add to my DNS provider.
I had to dig a little bit to figure out where to set the PTR record - I didn’t realize you had to set it at the VPS level instead of the DNS level (despite reading the instructions). Once I got that record set (which I still don’t fully understand, but it works), it even showed up in Gmail - inbox, not spam!
Thoughts and next steps
I honestly thought this would be a more technical post than it ended up being, but all the documentation I came across was in-depth and helpful and I didn’t find it necessary to re-post the instructions. But, I’m sure as I dig more into this, there will be more technical posts forthcoming.
Next steps:
- Biggest questions before moving forward:
- Is it better to set up one server for aliasing and another for the email, with different domain names?
- Alternatively, does it make more sense to use a third-party aliasing service, with the potential option of many domain names? (Blend in with the crowd)
- Decide on a better long-term domain name
- Figure out how to set a catch-all email address
- Figure out how to set up aliasing
- Harden the server in general
- Harden the email aspect of the server
- Configure spam rules & etc
- Configure backups on the server
- Set up IPv6 on the mailserver
- Answer the question - can I, and would it make sense to, store the email on my home network primarily and have the VPS as the public-facing end only?
- Research PGP
- Configure NeoMutt (I need my vimkeys)
- Set up 2FA for mail accounts - I want to say if possible, but I’m sure it’s possible…
EOF