💾 Archived View for ser1.net › post › le-mail.gmi captured on 2024-06-16 at 12:48:51. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2024-03-21)

-=-=-=-=-=-=-

--------------------------------------------------------------------------------

title: "LetsEncrypt and email" description: "How to use LetsEncrypt certificates with Postfix and Dovecot" tags: [ "server", "email", "letsencrypt" ] date: "2017-01-12T00:00:00Z"

--------------------------------------------------------------------------------

How to use LetsEncrypt certs with email

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

1: https://github.com/lukas2511/dehydrated

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

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. able to find the SSL root certificate for Dovecot, at least.