I have self-hosted my email for a few years now with somewhat decent success. My current software stack is Dovecot for IMAP, OpenSMTPD for SMTP, and then OpenDKIM for DKIM verification. All of these have been running on my home server, at a residential IP address1. Lately, I've been spending a bit of time improving my email infrastructure, both because I recently moved, and thus my IP address changed, causing deliverability issues, and also because I have been getting a lot more spam emails lately, mostly from the companies and organizations that I really have no choice but to have an account with. So in this post, I specifically want to address how I've made sending emails more reliable and how I keep my inbox clear of spam and organized. They seem unrelated, but they've been my main focus over the last month or so, so I wanted to write a little bit about them.

Fist, I want to clarify that this post is not about how to self-host your email. There are plenty of guides for that, and with OpenSMTPD and Dovecot, it's actually pretty easy. Rather, this post is to encourage those that either already run their own mail server, like me, or just those that want to and are considering it. It's to let those people know that, despite what the popular opinion and advice is, it is possible to have reliable deliverability, and effectively mitigate spam without complex spam filtering, while still hosting your email on your own hardware. The common advice to tech-savvy people that want to run their own email server is generally "don't," but I'm doing it and it is working very well. I highly recommend it, both as a privacy measure, and as a way to reduce dependency on big tech. But again, this isn't a guide on how to set up SMTP, IMAP, and DKIM. Once you've got all those set up, then this post is about taking your email server to the next level, making it more reliable and keeping things organized.

When I first set up my email server, I just wanted it to work, and being able to send and receive emails was the entire goal. Now, a few years later, I'm more focused on doing things right, with virtual users2, aliases, a clean and non-residential IP address, and Sieve scripts to sort emails into folders. In this post, I'm just going to share what I've done, not exactly how I've done it, to hopefully point you in the right direction. I'll go into as much detail as I can, but I'm not going to share config files or anything like that. First of all, I'm embarrassed by them, because they're messy after years of periodic modification, and second, they're very specific to my setup and contain personal information that I don't want to leak.

WireGuard + OpenSMTPD: A Lightweight Proxy

The IP address from which you send mail is perhaps the single most important part of the whole setup. You can configure DKIM, and SPF, and DMARC, and you can do everything right, but if you have a tainted IP address, it won't matter—your emails will either bounce, or go straight to the spam folder. I learned this the hard way: I had everything set up properly, but because my IP address was a residential IP address, it could not reliably send mail, as it was listed on Spamhaus's residential IP blocklist. Some providers would accept mail, but others would bounce, causing much frustration. This was particularly annoying because I had done everything correctly, and literally the only thing out of my control (my IP address assigned by my ISP) is what was causing mail to not be delivered reliably.

I tried to blame this on the mail providers that bounced my emails. And honestly, I do still think it is their fault. There is nothing inherently wrong with residential IP addresses. With properly configured DKIM, SPF, and DMARC, there should be absolutely no reason why I couldn't send mail. But, for some reason, just having an IP address in a certain block means I cannot. However, as much as I want to blame other email hosting providers, the fact of the matter is that my IP address was tainted, and ultimately that is my problem and I need to deal with it, even if I think I shouldn't have to. When my fiancée gets a message from MAILER-DAEMON@bancino.net stating that her message has been rejected, that ultimately is my problem, regardless of whether or not I think the message should actually have been rejected.

The easy solution would be to just give up and move my email to a big tech provider. That's what most people that have run email servers in the past have done, in my experience. They just get so sick of the hassle, that they simply cave and use one of the big services. We have Google Workspaces, Apple iCloud+, and even my domain provider, all of which will work with my custom domain, bancino.net to serve email. However, they are expensive and not privacy friendly, since my emails are stored on their servers. Additionally, from what I can tell, I have to give up control of my domain so they can manage it; they won't let me manually configure my domain. I priced out all my options, and weight the privacy costs as well, and I ultimately decided this was not an acceptable path. I don't want to give up control of my email, or my domain.

My next thought was hosting my email on an Alpine Linux VPS. I'd have to move my IMAP and SMTP servers up to the cloud. However, this has the same problems: though it is much, much cheaper, I'm still storing my email in the cloud and I don't like that due to privacy reasons, and it can potentially get expensive for the amount of storage I would need to store the last near-decade of emails. I therefore would like to rule out a VPS for hosting my entire email stack. However, there's no getting around the fact that I will need a VPS, because that is the only way that I can get a stable and un-tainted IP address. My ISP certainly won't give me one.3 If I could just somehow use a VPS to relay outgoing mail, I could keep my mail on my server, I could maintain control of my domain, and I'd have better email deliverability. Even though it's not ideal because it still requires relying on an external service, I'm really not storing any data in the cloud—merely using it as a proxy—so I can live with that for now.

The next question is then one of logistics: how do I set up an SMTP proxy that is extremely simple and secure? I came up with a number of solutions:

  • Set up Wireguard such that all outbound SMTP traffic gets routed at the network layer through the VPS. This would require messing with my nftables configuration, which I'm not opposed to—it is infinitely better than iptables—but I'd prefer to keep it even simpler than that.

  • Run OpenSMTPD on the VPS and have it deliver mail to Dovecot on my local server. I'd still need WireGuard to connect the two; LMTP from OpenSMTPD to Dovecot would happen over the WireGuard tunnel.

  • Run OpenSMTPD on the VPS and have it receive mail from my local OpenSMTPD and relay it.

I actually decided to go with the third option, because it was the easiest, although in order to receive mail from my local OpenSMPTD, and only my local OpenSMTPD,4 I did end up deploying WireGuard too. Essentially, I set up a WireGuard tunnel between my VPS and my home server, and then set up OpenSMTPD on the VPS to receive mail on the WireGuard interface and then forward it to its destination. I then configured OpenSMTPD on my local server to—instead of directly relaying mail to its destination—relay it to the OpenSMTPD across the WireGuard tunnel.

This required virtually no other changes to my local email setup. My mail clients still connect directly to my home server to send and receive mail, but outgoing mail now goes through the VPS so it looks like it is coming from a clean IP address. As a bonus, I can now also receive mail at the VPS, and it will relay incoming mail to my local SMTP server, which will deliver it to Dovecot over LMTP, just as it always has. In fact, the VPS is now listed as the primary SMTP server for my domain, so mail gets routed through it in both directions by default, although I did leave my home server as my secondary mail server, so if for some reason the VPS is acting up, I can still at least receive mail.

This setup actually works great, and I don't even have SSH listening on the public IP address—it only listens on the WireGuard interface, so only my server can even access SSH. The only port exposed is 25 so I can receive email. The WireGuard tunnel is extremely reliable, probably because it is very low traffic. I did have to configure my home server to send periodic keep-alive packets, otherwise the tunnel would break and the VPS wouldn't be able to re-establish it.

I think that this setup checks off all my boxes for reliable email delivery from a home server:

  • [x] Simple

  • [x] Secure

My email still lives on my home server, but I have a 10/10 deliverability score on mail-tester.com, and all the other email-server-testing websites I've checked also give me very high ratings. The advantage to the VPS is that I can also set my reverse DNS, which email providers use as an additional verification mechanism. So now my reverse DNS matches my forward DNS, and everyone is happy. That is something that I was never able to get from my ISP.3

Virtual Users & Aliases

Now that I can send emails reliably, I need to deal with how I receive them. The main issue here is that for the longest time, my inboxes were tied to local Unix accounts on my server, and emails would live in the home directories of those users. That's fine when it's just me, but now that I've got my fiancée on my email server as well, she really doesn't need a Unix account, because she's never going to be logging in to the server in any way that isn't for email. Luckily, OpenSMTPD and Dovecot both support virtual mail users. Now all emails live in /var/vmail, and virtual account credentials are stored in /etc/smtpd/virtuals. Creating a new email account is as simple as adding to that file and reloading OpenSMTPD and Dovecot.

This also allows me to have virtual aliases, aliases that aren't real Unix accounts, but map to virtual users. So now the postmaster and webmaster accounts, for example, can map to my inbox, even though they aren't even real Unix accounts.

It is well worth the time required to learn how to set up virtual users and aliases. They make managing email infinitely easier, and allow for an unlimited number of accounts and aliases. If you want a different email address for each online account, for example, that's easy. Or if you want to host email for your entire family, that's easy too. Just add a line to the virtuals files and you're good to go.

Dovecot Sieve

The other problem I have with receiving emails is that I just receive way too many of them. I get so much junk mail, both from the time I had my email publicly posted on my website—a mistake, in hindsight—and from the online accounts I've had to register to get things done, like insurance quotes and internet providers, etc. I get so much email that my inbox is overrun with at least 20 newsletters a day. This is simply unacceptable so I knew I had to do something.

The first thing I did about that was research into Dovecot's Sieve implementation. Sieve is a scripting language that executes on each incoming message and determines what action (or actions) Dovecot will take. It can sort email, block email, forward email, and more. While I was researching this, I discovered that Dovecot has built-in support for "detail" parts in email addresses. This is that special syntax where you can send an email to user+detail@domain.com, and it will arrive in user's inbox, but will have a "detail" of detail. The "detail" is a tag, if you will. Well, as it turns out, Sieve can use this to categorize mail. So, for example, I can set up a Sieve script that automatically creates a new mailbox in my Inbox for each detail, and then my mail will be categorized as it comes in.

For each online account that I have, I can set the email address for that account to include a detail, and then the emails from that account will be automatically categorized into the relevant folder. For example, if I had an Instagram account—to be clear, I don't, nor will I ever—I could register it with the email address user+instagram@bancino.net, and then all of the emails I get from Instagram would go into Inbox/instagram automatically. If a company sends me too many emails, I can have Sieve automatically mark them as "read" too, so I never even get the bubbles in my email client.

For the vast majority of online accounts I have, this works incredibly well. However, some refuse to accept the new email address—or rather, they'll accept it and act like they'll use it, but then they still send emails to my main email address without the detail part. And of course, there are organizations that seem to ignore my email preferences altogether, and even though I don't have an account with them, they still send me marketing emails, even after I've unsubscribed, and clicking on the unsubscribe link only tells me that I'm not even subscribed—and yet I still get emails. For these organizations, I have Sieve totally block the domain, so that any email from their domain is immediately discarded. That may seem kind of harsh, but when I'm getting three to five emails a day from the same organization telling me that they're having a 95% off sale or that shipping is free for "TODAY ONLY" for three days in a row, I have no tolerance left for that, so I don't even have Sieve mark the emails as spam, though it could do that. I just have it delete them entirely.

Sieve is incredibly powerful, and I should've invested in it years ago, learning how it works and using it to block spam. I always dismissed it, saying it was too complex and I really didn't need it, but now that I'm using it, I have no idea how I lived without it. Interestingly though, Dovecot also has an option to automatically categorize emails by their detail built right in; you don't have to use Sieve if you don't want to. The option is called lmtp_save_to_detail_mailbox, and I tested that before I messed with Sieve, but I found that it would only work if you created the mailboxes in advance, and only at the top level of your IMAP folders. That is, I couldn't nest my detail mailboxes inside my Inbox to de-clutter my email client—they had to be at the top level, and that was just really messy. These two drawbacks made me do this through Sieve instead, because I could have Sieve automatically create the mailbox, and it could do so under my Inbox to keep things organized.

Conclusion

In conclusion, my email is now a lot more robust than it used to be. I never have to worry about my deliverability again, because in the last few months, it has just worked. I haven't gotten a single bounce email in a while, and that makes me trust my email a lot more. Self-hosting email can always be stressful because you never know if your emails will actually get through, but now that I'm routing my emails through a clean IP address with reverse DNS, all my deliverability problems are solved, and WireGuard is proving to be incredibly stable, allowing me to keep my emails stored locally on my server. This truly allows me to have the best of both worlds.

Additionally, I've significantly cut down on spam that shows up in my inbox, both by categorizing my email into detail mailboxes, and by straight up blocking domains that don't honor my email preferences. I don't have any complex spam detection software that requires me to set up SMTP relays to a different daemon, just a simple Sieve script to process incoming emails on their way to my inbox from SMTP.

These two things—deliverability enhancement and spam avoidance—have turned email from a hassle that caused much frustration to something that I don't even have to think about anymore, even though I self host it. When once I dreaded having to deal with my email server and considered moving it to the cloud, now I can work in peace and with confidence, knowing that my email server will just keep working in the background. And if something ever does go wrong, my deep-dive into the more complex parts of self-hosting email gave me the knowledge I need to troubleshoot with a lot more precision. I feel much more in control of my email server, and it feels much less fragile now. I'm not afraid that I'm going to break my whole setup when I edit configuration files. Even if I didn't get any advanced features out of my email server, that alone makes it worth doing the research for.

Self-hosting email is hard; I certainly am not denying that. But once you get your setup tuned, it is incredibly satisfying and well worth it. The privacy advantage, as well as the power to control what happens with your email and how it operates, is well worth the occasional trouble it causes me.


  1. Yes, yes, I know, this is a horrible idea. That's why I changed it. But for what it's worth, it actually did work for quite a while, until I moved and my IP address changed into a different block owned by my ISP, which caused mail providers to start rejecting my emails, prompting this post. 

  2. Instead of having to create local UNIX accounts for all mail users. I actually did that for a while. Of course, it was just me using my server, so I already had a local account anyway

  3. They make it perfectly clear in their terms of service that hosting any type of server is strictly forbidden, so if I were to ask for a static IP or a reverse DNS modification, I have no doubt that someone would start asking questions and my home internet connection would be terminated due to a violation of the terms, since not only do I run my email, but also my web server, Matrix homeserver, and Nextcloud instance, all of my home internet connection. 

  4. We wouldn't want to be running an open relay now—that is a sure way to get blacklisted even more than I am for having a residential IP! 

Previous Post Next Post