It had been a while I wanted to have another solution for hosting and serving emails than Gmail. Especially because I am currently working on the Linux Kernel and at some point I would like to submit a few patches. Unfortunately, it is impossible to use Gmail for sending patches or even, to a greater extend, to be involved in the LKML.

Also I think it is pretty fancy (nerdy?) to have my own email address, i.e. joel@porquet.org.

At the same time, I have always heard that managing a full email stack (from the mx DNS records up to the IMAP and SMTP servers) is a pain. It can definitely happen that my server is down for a few days which would mean that my emails would be inaccessible in the meantime.

That is why I had this idea of using a stable frontend (i.e. via OVH, my hosting service company) before my own email server, so that whenever my server is down, I can still access my emails through this frontend. One could argue that I could just use the email facility that OVH provides but there are (at least) two reasons I prefer not to:

Here is a picture of what I wanted to achieve (thanks to Asciiflow for the following ASCII Flow Diagram):

+-----------+              +-----------+               +--------------+
| OVH       |              | MYSERVER  |               | LAPTOP       |
|           |              |           |           +-->|--------------|
| +-------+ | push/delete  | +-------+ | push/sync |   |  MAIL CLIENT +---+
| | IMAPS +----------------->| IMAPS +<------------+   +--------------+   |
| +-------+ |              | +-------+ |           |   +--------------+   |
| +-------+ |              |           |           |   | ANDROID      |   |
| | SMTP  |<-------+       |           |           +-->|--------------|   |
| +-------+ |      |       |           |               |  MAIL CLIENT +---+
+-----------+      |       +-----------+               +--------------+   |
                   +------------------------------------------------------+

In a few words:

Everything pretty much relies on two (great) pieces of software: getmail and dovecot. Getmail will be in charge of fetching the emails from OVH inbox (using IMAP IDLE), and delivering them to dovecot. Dovecot will service the IMAPS access to the clients, as well as managing the mailboxes locally on the server.

Note: as usual, the preferred Linux distribution here is ArchLinux.

Dovecot

After installing dovecot, there are a few steps to have a somewhat secure and operational installation:

SSL

I should have written an article about that before, because I do not remember the exact procedure, but it turns out I already have a key and certificates for my server (thanks to StartSSL who gives free SSL certifications). I use them to provide a https access through lighttpd (e.g. for this website). What I already had in /etc/lighttpd/ssl were the following files:

porquet.org.key
porquet.org.crt
sub.class1.server.ca.pem
ca.pem
ca-certs.crt

Dovecot needs pretty much the same information, but organized slightly differently. It wants the key alone, and one another file containing all the chain of public certificates. I already had the key alone (porquet.org.key) but I had to create another file that I called imap.porquet.org.crt in which I put, in order, the public certificate for my domain (originally contained in porquet.org.crt), followed by the content of ca-certs.crt.

Authentication

Dovecot offers tons of possibility for the authentication of clients, i.e. when my laptop or android initiate a connection with dovecot. The simplest solution was to use the system users, but I did not want to use the same password as the one I use for accessing my server via SSH (even if supposedly SSL steps in first, before transmitting the password).

So I used the Passwd-file backend. It means you have to create a file, with the same format as /etc/passwd (or /etc/shadow), and specify allowed users along with their password. Not to complicate things too much, I used the same username for myself as my system user.

Create a file in /etc/dovecot/auth/passwd, and add lines to specify allowed users:

$ cat /etc/dovecot/auth/passwd
joel:{SHA512-CRYPT}$6$..............

The password is automatically generated with the doveadm tool:

$ doveadm pw -s SHA512-CRYPT

Dovecot global configuration

On ArchLinux, sample configurations are kept in /usr/share/doc/dovecot/example-config. Copy everything in /etc/dovecot and modify the configuration so it suits your needs. To know the current configuration, dovecot provides an awesome option that summarizes it for you in a simple way (as well as giving potential configuration errors):

$ doveconf -n

Mine looks like (I included comments in the output to explain certain options a bit):

# On ArchLinux, this path already exists for serving mails locally
mail_location = maildir:/var/spool/mail/%u

# Create the main Inbox folder, as well as a few other useful folders
namespace inbox {
  inbox = yes
  location =
  mailbox Drafts {
    auto = create
    special_use = \Drafts
  }
  mailbox Junk {
    auto = create
    special_use = \Junk
  }
  mailbox Sent {
    auto = create
    special_use = \Sent
  }
  mailbox Trash {
    auto = create
    special_use = \Trash
  }
  prefix =
}

# Authentication database: use the passwd-file approach described above
passdb {
  args = scheme=CRYPT /etc/dovecot/auth/passwd
  driver = passwd-file
}

# Specify an email address where unknown emails should be delivered (it is
# necessary to declare one, when dovecot receives emails by getmail)
postmaster_address = joel@porquet.org

# The only protocol that we serve is IMAPS. Non-SSL IMAP is deactived
# because its listening port is 0
protocols = imap
service imap-login {
  inet_listener imap {
    port = 0
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
}

# SSL is required, and we give the chain of certificates as well as the
# private key
ssl = required
ssl_cert = </etc/lighttpd/ssl/imap.porquet.org.crt
ssl_key = </etc/lighttpd/ssl/porquet.org.key

# After the authentication step, dovecot uses the regular system users of
# the server
userdb {
  args = blocking=no
  driver = passwd
}

Start dovecot

You should now be able to start dovecot, using systemd if you are with ArchLinux:

# systemctl start dovecot

You should also be able to configure your email client, and give the address of your IMAPS server, your username and password (the one defined in /etc/dovecot/auth/passwd, not the system one defined in etc/passwd!) And you should see the mailboxes that are present on the server: namely Inbox, Sent, Drafts, etc.

Normally you can already send emails, by setting up the address of the external SMTP server.

But now is time to actually receive emails!

Getmail

The work that getmail will do is to retrieve emails from OVH inbox and deliver them to dovecot, so that dovecot can in turn deliver them to the various email clients.

Configuration

Contrarily to most of examples, I decided to configure getmail in a system-wide way.

I started by creating a new folder /etc/getmail. In this new location, I created a folder named joel@porquet.org that belongs to my system user. And finally, in this folder, I created a configuration file for getmail (comments are inline):

$ cat /etc/getmail/joel@porquet.org/getmailrc

[retriever]
type = SimpleIMAPSSLRetriever
server = ssl0.ovh.net
port = 993
username = XXX
password = XXX
mailboxes = ALL

[destination]
type = MDA_external
# -e: make dovecot return an error if necessary
path = /usr/lib/dovecot/deliver
arguments = ("-e",)

[options]
# retrieve only new emails
read_all = false
# delete on server after x days
delete_after = 30
# do not add a Delivered-To: header field
delivered_to = false
# do not add a Received: header field
received = false

Startup

At first, you can try your new installation (and see the error messages if there is any) by starting getmail directly in a shell:

$ getmail --getmaildir=/etc/getmail/joel@porquet.org --idle INBOX

Try to send yourself an email and check that the email go through getmail, then dovecot and finally arrives in your email client!

Systemd

Now that everything works perfectly, we can make getmail a systemd service so it is started automatically at boot.

Create a new systemd service, in /etc/systemd/system:

$ cat /etc/systemd/system/getmail@joel.service

[Unit]
Description=Getmail for joel@porquet.org
Wants=dovecot.service
After=dovecot.service

[Service]
User=joel
ExecStart=/usr/bin/getmail --getmaildir=/etc/getmail/joel@porquet.org --idle INBOX
Restart=always

[Install]
WantedBy=multi-user.target

Start and enable this new service (log messages will then be accessible via journactl):

# systemctl enable getmail@joel.service
# systemctl start getmail@joel.service

Now, enjoy your new email server!