Selfhosted Mail — Some info to help people trying to do this
There is quite a bit written in various places about self-hosting mail but much of it is 2+ years old and/or doesn’t cover things I found to be important. After spending a couple of weeks trying to figure out which mailserver to use I thought a somewhat condensed version might be helpful:
Very easy to set up but somewhat light on features and (by design) does not allow any customization or modification.
I tried MIAB but there were a few issues that made me step away:
You can NOT set per-domain or per-mailbox quotas. This is what ultimately killed MIAB for me.
It can only be installed on an old version of Ubuntu which will end support next year. (I assume the developer(s) will fix this before it becomes a major problem…)
No virus scan option. ClamAV is far from perfect but it’s also better than nothing and very effective when combined with PC-based virus scanning.
If you want the easiest possible mailserver and don’t care about quotas, AV, or distro version then this is one to consider.
I did not try this in the end as many of the best features are only (easily) available in the paid-for “pro” version of the admin panel. It’s very expensive, overpriced IMO, $499 for the first year and $250 per year after that. You can do basic things from the free admin panel and everything else through SQL or the CLI but that’s a pain in the ass that I don’t want to deal with.
This is a very slick groupware package with two big problems:
It is massively memory hungry. It requires at least 8GB of memory to run, far more than any other option.
There are free and paid versions. The free version is feature limited and does not offer Exchange ActiveSync “push” for mail/calendar/contacts/etc. If you want to get these features and other advanced features for Zimbra you have to pay a per mailbox yearly licensing fee. 🙁
This is what I went with in the end, after trying out MIAB on two domains for a couple of weeks first. My reasons were:
No expensive paid version with all the good features, one (free) version with everything.
Has per domain and per mailbox quotas
Supports 2FA for admin accounts.
Uses SOGo for webmail and for ActiveSync to mobile devices. It’s very slick.
Offers ClamAV, but you can turn it off if you don’t want it or don’t have the server memory for it.
You can customize the setup if you wish, as long as you realize that doing updates may overwrite your changes. Make notes and backups!
It’s not perfect. For example it doesn’t seem to work with +aliases out of the box, a useful feature that allows users to create unlimited aliases based on their email address.
Overall I’m very happy with mailcow after a couple of weeks of use and I think it will be our long term mailserver. It will be nice to move away from Google’s paid mail!
Dealing with self-hosted e-mail: a no-nonsense guide
It’s been posted n times on here: How do I host e-mail at home or my VPS? It’s been commented n*10 times that you shouldn’t even try it. The consensus seems to be that it’s too hard to do it right. It is definitely difficult to do this entirely self-hosted. You have things like reputation, spam, malware, viruses, etc. to worry about. With a little knowledge and a willingness to offload delivery and relay for your e-mail to external services, that becomes much easier to swallow.
I’m planning on blogging about this when I resurrect my blog, but I thought this may be useful here first. I’m not going to cover the ways to self host your e-mail, or the configurations. That’s been well covered here. My goal here is to make self-hosting e-mail accessible to more people. I thought about making a TL;DR of this lengthy post, but I want you to understand the concepts if you do want to host e-mail yourself. You’ll be safer this way!
First things first. I am not affiliated with, nor being paid by, any of the developers/vendors of software or services I mention in this post. This is simply what works best for me after trial and error, coupled with my knowledge of e-mail systems. I am posting this in an effort to bring a little more understanding to self-hosting e-mail. I’ve run large e-mail systems in my past lives. I wish that on nobody!
My use case? I have a Synology NAS and host e-mail for a small number of domains in my home. For me, Synology MailPlus (the free version) more than satisfies my mail server needs. If you don’t have a Synology, or you don’t like MailPlus, you can run any other mail server software like mailcow, mail-in-a-box, or roll your own postfix/courier setup to get similar results. Configuration of those solutions is well documented in this sub and elsewhere so I’ll move on.
With our mail server settled we still have two issues to address: 1) inbound SMTP, including spam/malware/virus protection, and 2) outbound SMTP, including reputation and deliverability of your e-mail to others. Hosting SMTP at home, or on a VPS, isn’t generally viable. On residential Internet services you generally can’t expose SMTP (ports 25/587) to the internet so it’s not possible to receive e-mail on your server, even if you’re lucky enough to have a static IP address. Many VPS and cloud services disallow the same, as well as outbound connections to SMTP ports, especially without jumping through massive hoops. So, let’s work around that!
For inbound SMTP, there are a few providers that allow inbound SMTP (Mail eXchanger) services. I have found that MX GuardDog works well for my needs. They have the ability to earn free service by linking to them from your website (I didn’t enable the link for this post). If you don’t want to link to them, they charge a reasonable 25 cents per month per e-mail address. This resolves the inbound SMTP issue. They will be the MX record for your domain(s) and receive e-mail on your behalf from the internet, and forward it on to your home/VPS server. They offer decent SPAM, malware, and virus protection at the MX gateway so you don’t have to waste resources scanning e-mail if you don’t want to. There’s one problem, though. If you can’t expose port 25 to the internet, how does mxguarddog get your e-mail to you? The way I worked around it was by port forwarding an arbitrary port (like 3535) on my home router to port 25 on my Synology, and then configuring that as the “output” server in mxguarddog. Once all of this is tested, you can change/set the MX records for your domain. Those settings are listed in your mxguarddog dashboard and they provide you with help on how to set those records if you need it.
Outbound SMTP is far more complicated. You have to be careful to not taint your reputation, as a negative reputation can follow your domain around for quite a while. There are two components to out-bound e-mail service: 1) the actual SMTP service that sends your mail, and 2) validation and authentication of yourself and your users as the sender of e-mail from your domain. If you pay attention to this, you can set, test, and forget it relatively easily.
The outbound SMTP service is the easier part, so I will go with that first. I chose SendGrid for this for a couple of reasons. Most outbound SMTP services like this are designed for marketing firms and for sending newsletters. SendGrid is also designed for that but they have settings available that make the service friendly for sending personal e-mail via the service. The most important ones are the ability to suppress the tracking mechanism that would be included in outbound marketing email (we don’t want our recipients to be tracked!), the ability to use your own domain name as the sending entity (so that your recipients don’t see “sent by sendgrid” in GMail or have your mail categorized as bulk mail). You need to configure your mail server to use a mail relay to send your mail, rather than attempting to deliver directly. SendGrid offers an SMTP service and gives you the configuration information.
Using SendGrid for outbound e-mail is pretty straight forward. Here is what you need to do:
Sign up for SendGrid and add your domain. The free tier worked for me as I don’t send more than 100 messages per day.
Configure your mail server to use
587as your mail relay server. Some software calls this a smart host or a delivery host. You can use other ports that SendGrid allows if your service provider filters port 587. Their support page can tell you what they support. Authentication is required. Use your SendGrid username and password. You can also configure it for use with an API key, which is what I do.
In SendGrid, disable tracking by going to Settings -> Tracking and setting everything to “inactive”. This will turn off e-mail tracking, which is a good thing for personal e-mail that’s not intended as marketing.
In SendGrid, enable domain authentication by going to Settings -> Sender Authentication and clicking on “Authenticate your domain.” Follow the instructions there. This will allow SendGrid to send e-mail using a hostname on your domain (like e999.example.com) for sending rather than showing it as originating from sendgrid.net. This is important so that your email isn’t automatically classified as bulk/marketing mail by your recipients. GMail even goes as far as placing a “Send with SendGrid!” badge on e-mails if you don’t do this. More information about what is happening here is listed below in the DKIM section.
Authenticating yourself as the sender is the harder part to understand. Luckily there are established ways to do this via DNS records. These are:
These need to be done right or you risk damaging your domain’s reputation, potentially long-term. Proceed at your own peril! I’m not responsible for slander or melted mail servers. These settings worked for me in this setup. You’ll want to add records for each of the above record types.
SPF – Sender Policy Framework
This record is added as a
TXT record to your root domain/zone. It basically tells a recipient’s e-mail server which e-mail servers are allowed to send e-mail on behalf of your domain. This would make e-mail appearing to come from your domain name, but from a spammer’s mail server more suspicious to the recipient’s SPAM filters. For our purposes this works:
@ IN TXT "v=spf1 a mx include:sendgrid.net ~all"
Let’s break it down in case you are curious:
@: is the DNS equivalent of “example.com”, also called the apex record of your DNS zone
IN TXTidentifies it as a
If you use a control panel of some sort, only the text in quotes should be pasted into your TXT record:
v=spf1: defines this TXT record as a SPF version 1 record. Leave this as is.
a: means to allow your apex record’s IP address (example.com) to send e-mail on your behalf. I enabled this so that scripts I installed on my website can send e-mail. (for example, a forgotten password link to my end users.) You can disable this if you don’t intend to potentially send mail from your website.
mx: means to allow your MX servers (in my case mxguarddog) to send mail on your behalf. I enabled this in case their system needs to send responses for undeliverable e-mail. They would send those as
firstname.lastname@example.org(e.g., from my domain)
include:sendgrid.net: means to also include servers whose reverse DNS records point to a subdomain of sendgrid.net, my outbound SMTP provider
~all: is interesting. What this does is tell the recipient’s mail server that mail coming from anywhere other than defined above should be “soft failed.” That generally just means it would be delivered but marked as SPAM, or quarantined. Placing a
-in front of
allinstead of a
~means to outright reject it. I chose the
~in case I had any misconfigurations early on. You may choose otherwise. Placing a
+in front of
allmeans I to allow all IP addresses. Don’t do this!
DKIM – DomainKeys Identified Mail
This record is added as a
TXT record to a spacial host record in your DNS zone based on a “context name” and the
_domainkey sub-domain. DKIM works by having your outbound mail server, in my case SendGrid, cryptographically sign your e-mail messages as being sent by you. It determines this based on the fact that your home/VPS mail server, in my case MailPlus, logged in when it sent your e-mail message to SendGrid. In our case, SendGrid assigns this configuration when you enabled authenticated domain e-mail sending above. Don’t not try to copy/paste the following info into your own DNS zone. SendGrid will provide you with the information you need when you do the authenticated domain setup above. I’ll list mine (with parts redacted) here so you can understand what it does, if you would like. It’s worth noting that doing DKIM on your own would result in a different set of records, including a public key. I found it much more reliable to allow SendGrid to manage this for me since my reverse DNS is a residential IP, which causes other issues.
s1._domainkey IN CNAME s1.domainkey.u9999999.wl999.sendgrid.net. s2._domainkey IN CNAME s2.domainkey.u9999999.wl999.sendgrid.net. em9999 IN CNAME u9999999.wl999.sendgrid.net.
All the above does is create
CNAMEs to the DKIM configuration that SendGrid set for you and the vanity hostname (em9999.example.com) that they set for you when you enabled your authenticated domain above.
DMARC – Domain-based Message Authentication, Reporting & Conformance
This record is added as a
TXT record to a special
_dmarc host record in your DNS zone. This one is very important as it ties the others together and sets expectations of your interaction with your recipient’s mail server. A recipient’s mail server will use this record to understand what your policy for sending mail is and, more importantly, report infractions to you. It will also define what you’d like done with e-mail that doesn’t adhere to your policy. This helps tie together the SPF and DKIM settings we previously set. While SPF and DKIM can be individually implemented, DMARC provides a robust set of standards that are used to tie together the rest. It is worth noting that not everyone uses DMARC yet. Most of the big providers do, though. For our purposes, the following works:
_dmarc IN TXT "v=DMARC1; p=quarantine; pct=100; rua=mailto:email@example.com; ruf=mailto:firstname.lastname@example.org; adkim=r; aspf=r"
Let’s break it down in case you’re curious:
_dmarc: is a special “host record” that a recipient’s mail server can look up. GMail and other large providers use DMARC
IN TXT: identifies it as a
If you use a control panel of some sort, only the text in quotes should be pasted into the TXT field of your
_dmarc host record:
v=DMARC1;: defines this TXT record as a DMARC version 1 record. Leave this as is.
p=quarantine: defines your policy for e-mail that fails the remaining authentication rules (below).
nonemeans deliver it as normal, which is useful for testing. Once you’re sure you’re not misconfigured you should change this to quarantine. You can test by sending e-mail to a gmail address. Google is good about sending daily reports to you.
pct=100;: tells the recipient mail server that you want 100% of your messages authenticated. This is good for your reputation as it shows that you don’t want spammers using your domain name.
rua=mailto:email@example.com;: defines the URI (in this case an e-mail address) that should receive periodic reports regarding messages that have failed DMARC authentication.
ruf=mailto:firstname.lastname@example.org;: defines the URI (in this case an e-mail address) that should receive forensic reports regarding messages that have failed DMARC authentication. This may include other data like SPAM scoring, etc. I’ve yet to receive a forensic report.
adkim=r;: defines policy for messages that fail DKIM authentication. (e.g., not signed or signed by the wrong key). The
ris for relaxed (mark it as SPAM/quarantine).
smeans strict (reject).
aspf=r;: defines policy for messages that fail SPF authentication. (e.g., from a server that’s not allowed to send mail for you). The
ris for relaxed (mark it as SPAM/quarantine).
smeans strict (reject).
I hope that I’ve presented enough information to help more people self host their own e-mail without it being overkill. There is certainly more to learn, but I think this should give the average enthusiast more confidence in self hosting e-mail and understand how it works and why many people advise you not to try it. The blanket answer should not be “DON’T DO IT!!!!” You may still conclude that after reading this, and that’s ok!