Hosting your Own Email Part 1 — GNUcode.me

Hosting your Own Email Part 1

by Joshua Branson — October 10, 2020

I have wanted to host my own email for some time now. I have not realized this goal yet, but I am discovering that hosting your own email involves a fair amount of different moving parts. I have often heard from fairly technical people that hosting your own email, is really complicated! This post is an explanation of what email is, and how guix system may be the best solution for setting up email. Please note that this is a multi-series blog post. This is part 1.

The Archlinux wiki is perhaps the best wiki to help you configure software. The Mail server wiki page is a great place to start learning about hosting your own email. Let's start with the high level view, as outlined by the archlinux guide. Essentially hosting your own email requires three bits of software:

  • a mail transfer agent (MTA) receives and sends email (opensmtpd)
  • a mail delivery agent (MDA), which gets the email from the MTA, and stores it for a user. (opensmtpd)
  • Remote users can access the emails via an MUA (mail user agent), via an IMAP server. (dovecot)

Since, guix has packaged an opensmtpd service already, I decided to use it, and according to the arch wiki it looks like opensmtpd is an mail transfer agent and a mail delivery agent! So that's two of my issues sorted right there! The last set, which is letting remote users access the email, is handled by dovecot, which is the IMAP email server.

By convention sending emails is done by smtp.<yourdomainname>.com, and your mail user agent (like Mozilla's Thunderbird), retrieves your email via imap.<yourdomainname>.com. So I've decided get Let's Encrypt certificates for my domain "gnucode.me" for the subdomains smtp and imap. Like so:

(use-service-modules certbot)

(define %nginx-deploy-hook
  (program-file
   "nginx-deploy-hook"
   #~(let ((pid (call-with-input-file "/var/run/nginx/pid" read)))
       (kill pid SIGHUP))))

(service certbot-service-type
         (certbot-configuration
          (email "jbranso@dismail.de")
          (webroot "/srv/www")
          (certificates
           (list
            (certificate-configuration
             (name "gnucode.me")
             (domains '("gnucode.me" "www.gnucode.me" "imap.gnucode.me"
             "smtp.gnucode.me" "mail.gnucode.me"))
             (deploy-hook %nginx-deploy-hook))))))

The Archlinux opensmtpd page has a great guide on setting up a simple mail server. I've modified it to deliver emails in the maildir format.

(use-modules (guix gexp))

(define creds
  (plain-file "creds"
              "joshua $6$somelonghashofstrings"))

(define vdoms
  (plain-file
   "vdoms"
   "gnucode.me
gnu-hurd.com"))

(define vusers
  (plain-file
   "vusers"
   "joshua@gnucode.me  joshua
jbranso@gnucode.me     joshua")

(service opensmtpd-service-type
         (opensmtpd-configuration
          (config-file
           (mixed-text-file "smtpd.conf"
                            "
# This is the smtpd server system-wide configuration file.
# See smtpd.conf(5) for more information.
# borrowed from the archlinux guix
# https://wiki.archlinux.org/index.php/OpenSMTPD#Simple_OpenSMTPD/mbox_configuration

# My TLS certificate and key
table aliases file:/etc/aliases
pki mail.gnucode.me cert \"/etc/letsencrypt/live/gnucode.me/fullchain.pem\"
pki mail.gnucode.me key \"/etc/letsencrypt/live/gnucode.me/privkey.pem\"

table creds \"" creds "\"
table vdoms \"" vdoms "\"
table vusers \"" vusers "\"

# listen on eth0, fairly explainatory
listen on eth0 tls pki mail.gnucode.me
listen on eth0 port 465 mails pki mail.gnucode.me auth <creds>
listen on eth0 port 587 tls-require pki mail.gnucode.me auth <creds>

action receive maildir virtual <vusers>
action send relay

match from any for domain <vdoms> action receive
match for any action send"))))

To serve your emails via imap, you also need a program to serve those files. Dovecot is probably one of the better ones to use. And it is conveniently packaged in guix!

(use-service-modules mail)
;; be default dovecot-service serves mail located in ~/Maildir, which is
;; what we have configured above.
(dovecot-service)

Ideally the above would be enough to get you sorted, but it's not. There are three things you should do to make certain that your sent email is not flagged as spam:

  • proving you sent your email (DKIM)
  • Sender Policy Framework (SPF)
  • What should other email account do if your email fails the above two tests? (DMARC)

I found this detailed email setup guide that I've found helpful. Fair warning, it's like trying to drink water from a fire hose.

The above configuration for opensmtpd is enough for me to receive emails for joshua AT gnucode.me, but I am unable to send emails. Also dovecot refuses to authenticate my email client (gnus). Fixes to those problems will appear in a later post.