LetsEncrypt and email

| |

I’m using the most excellent Dehydrated utility, which is both easy to use and lightweight (few dependencies).

These instructions assume you have control of a web server that can serve requests for the same domain as the mail server.

  • Define MAILHOST to the FQDN of your mail host.

  • Define WEBROOT to the directory of your mail server host in your web server, e.g., export WEBROOT=/var/www/htdocs/$MAILHOST

First, grab Dehydrated. I put it in /usr/local:

cd /usr/local
sudo git clone https://github.com/lukas2511/dehydrated

LetsEncrypt offers a couple of ways of verifying that you own the domain, but the one I’m using depends on LetsEncrypt being able to query a specific asset on the server. To support this, create a .well-known/acme-challenge directory in the web root for the mail server domain of your web server:

sudo mkdir $WEBROOT/.well-known/acme-challenge

Now, configure Dehydrated with that informtion. Per the dehydrated instructions, you also need to put your domain(s) in a file called domains.txt.

cd dehydrated
sudo cp docs/examples/config .
sudo sed -i "s%^#WELLKNOWN=.*%WELLKNOWN=$WEBROOT/.well-known/acme-challenge%" config
echo $MAILHOST > domains.txt

I also set a value for CONTACT_EMAIL. For testing, you should also change to the LetsEncrypt staging server; in case you have to run multiple times, you don’t want to be blacklisted:

sudo sed -i 's%^#CA=.*%CA="https://acme-staging.api.letsencrypt.org/directory"%' config

Run dehydrated:

cd /usr/local/dehydrated
sudo ./dehydrated -c

You now should have certificates in the /usr/local/dehydrated/certs directory. You can reference these directly with both Dovecot and Postfix. Dovecot accesses certs as root; however, Postfix’s TLS agent runs as postfix, so it can’t read the certs which dehydrated sets to 700 for perms. I weakened the security of the certs a bit by making them group readable for the postfix group. This is all on Ubuntu; it may be different for other distributions.

sudo hgrp -R postfix certs
sudo find certs -type d -exec chmod 750 {} \;
sudo find certs -type f -name \*.pem -exec chmod 640 {} \;

Now, it’s just telling Dovecot and Postfix where to find the certs, and restart the services:

# Dovecot
sudo sed -i "s%^ssl_cert.*%ssl_cert = </usr/local/dehydrated/certs/$MAILHOST/fullchain.pem%" /etc/dovecot/dovecot.conf
sudo sed -i "s%^ssl_key.*%ssl_key = </usr/local/dehydrated/certs/$MAILHOST/privkey.pem%" /etc/dovecot/dovecot.conf
# Postfix
sudo sed -i "s%^smtpd_tls_cert_file.*%smtpd_tls_cert_file = /usr/local/dehydrated/certs/$MAILHOST/fullchain.pem%" /etc/postfix/main.cf
sudo sed -i "s%^smtpd_tls_key_file.*%smtpd_tls_key_file  = /usr/local/dehydrated/certs/$MAILHOST/privkey.pem%" /etc/postfix/main.cf
sudo service dovecot restart
sudo service postfix restart

Now test:

# Dovecot
openssl s_client -connect mail.germane-software.com:993
# Postfix
openssl s_client -connect mail.germane-software.com:587

If everything is working, change the LetsEncrypt server back to the non-staging server and re-run dehydrated with -x (force renew) to get a real cert:

sudo sed -i 's%^CA=%#CA=%' config
sudo ./dehydrated -x
sudo service dovecot restart
sudo service postfix restart

Test again, and openssl should stop complaining about being unable to find the SSL root certificate for Dovecot, at least.

Copyright © Sean Elliott Russell

comments powered by Disqus