2021 Update: I no longer host my own mail server. If you still want to do it yourself, I found Mailu to be the most practical solution for having things “just work”.
As a result of the recent public discussion regarding online privacy I decided to take a few measures to give myself some more privacy online. One such measure was the creation of a new 4096 bit PGP public key for myself. I also started running my DNS requests through tor for some more privacy, which was inspired by Drew’s excellent blog post.
Lastly, I decided it was time to stop letting Google handle all the mail for my
domain. This was partly because it’s been costing me roughly the price of a
pint of beer in London
each month, and partly because it seemed like it would be a
As a note to self, and to spare you the
fun part of the learning experience
I thought I’d share the details of my set up to show how straightforward it can
be to get a solid mail server online.
For my mail server there are three key pieces of software at play:
- postfix - Provides an SMTP server
- dovecot - Handles mailboxes, authentication, and IMAP
- MariaDB - SQL database of email accounts
Inbound mail is given to postfix via SMTP. Postfix then checks against the SQL database whether the email address should be accepted, and performs spam filtering. If the email passes postfix’s checks it’s passed to dovecot over a unix socket via LMTP. Dovecot is then responsible for placing the mail in the correct user’s mail directory.
Email are accessed over IMAP using dovecot. Upon connection, users are authenticated by dovecot against accounts in the SQL database, and on success are connected to their mail directory.
Outbound mail is also given to postfix, however this time postfix requires authentication. Postfix sends the login details to dovecot over a unix pipe, which checks against the SQL database whether the user is permitted to send mail. If so, postfix is given the approval to do so, and relays the email to the relevant remote SMTP server.
Create a new database. I called mine
maildb. Also create a new MariaDB user,
maildb you want to create the following three tables:
The purpose of
aliases is for an email address mapping step performed by
postfix. Every email that is received locally has its address transformed using
this lookup table.
To receive email at an address it is required to be covered by this table.
firstname.lastname@example.org mapped to
email@example.com, which passes my
mail through without changing the destination.
However, if you’re the administrator of the server, you’ll want to receive mail
for users such as
firstname.lastname@example.org, so you’d need to map that to
You can also provide a catch-all address for a domain by excluding the name
portion of the email address. In my case that would be mapping
This table is even simpler to configure. It should simply contains all the domains for which your server should receive mail for. It’s used by postfix to determine whether to send mail to another server, or to pass it to dovecot.
In my case it simply contains
This is the most important table, which is used solely by dovecot to authenticate
crypt column should contain an encrypted form of their password.
Here’s an example query to insert a new user:
Now that the SQL database has been set up correctly, the next step is to set up Dovecot to authenticate users, manage their email directories, and provide an IMAP server for users to retrieve their mail from.
The recommended way to configure dovecot seems to be to have a main configuration
/etc/dovecot/dovecot.conf which includes many other configuration files
/etc/dovecot/conf.d/ but I found that to be an overcomplication for my
needs. Simply having one relatively short config file was perfectly adequate.
Create the virtual user
Traditionally email addresses were tied to unix users on servers, and the mail
was stored in each user’s home directory. In our case, we want our email
addresses to be independent of the users on the system, so instead all the mail
will be “owned” by a virtual user named
virtual. (Forgive me, I don’t study
To create the user and the mail directory run the following commands:
Now we’re ready to configure dovecot itself. It’s all fairly straight forward. Here’s a copy of my configuration file. Everything ought to be fairly self explanatory, and if it isn’t, dovecot has some pretty good documentation.
At this point, you should now have a working IMAP server that you can connect to
and retrieve mail from. Of course you won’t have any mail to read, but you should
still verify that you can now connect, and also check that the relevant mail
directory was created in
/var/spool/mail/virtual for your mail.
And now for the final step, providing an SMTP server to send/receive mail with.
In my case, I only needed to set up one main configuration file for postfix, and a couple of other files to allow it to query the SQL database.
Please note that this configuration doesn’t provide any spam filtering.
Again, if something doesn’t make sense to you, RTFM.
We also need to tell postfix how to query the information it needs from the SQL database.
The final step to get postfix working is to tell the world where it is. To do this you need to set a MX DNS record. The purpose of an MX record is to indicate where a domain’s mail server is hosted. While most DNS records should resolve to IP addresses, for MX records you should be returning another domain name. This is to allow resolving that domain to either an IPv4 or an IPv6 address.
MX records also have a
priority field. With a single record it’s irrelevant so
you can just set it to
10. For the address, give the domain name of the server
that postfix is running on.
Congratulations, you should now have your own mail server.
You’ll probably want to add spam filtering, and a few other goodies. There’s a good guide to setting that up here.
Have any questions or corrections? Leave a comment below, or drop me an email.