From d68be22176db3d7947682c945c16a44396a024c0 Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Wed, 12 May 2021 16:14:42 +0200 Subject: Add Dovecot SSL post --- src/blog/dovecot-ssl-certificate-renewal.erb.html | 97 +++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/blog/dovecot-ssl-certificate-renewal.erb.html (limited to 'src/blog') diff --git a/src/blog/dovecot-ssl-certificate-renewal.erb.html b/src/blog/dovecot-ssl-certificate-renewal.erb.html new file mode 100644 index 0000000..2cafcde --- /dev/null +++ b/src/blog/dovecot-ssl-certificate-renewal.erb.html @@ -0,0 +1,97 @@ +title: Dovecot SSL Certificate Renewal +date: May 12, 2021 11:06 +--- +

+Just a quick technical note. +

+ +

+As mentioned before, I + + started self hosting email + a while ago. Exactly three months ago, in fact, and I know this because +that's how long Let's Encrypt SSL certificates are valid +for. Yesterday, my email clients started complaining about an invalid +certificate coming from my mail server. +

+ +

+After a few minutes of worrying if I'm being man-in-the-middled, I ssh'd into my +VPS to debug. +

+ +

TL;DR: Root cause and solution

+

+Turns out when configuring Dovecot (the IMAP server I use), the SSL certificate +you set is just a static string, not a filename pointing to a file that Dovecot +will read every time it needs to serve it. As such, even after Certbot correctly +got a new certificate, Dovecot was still using the old one. +

+ +

+This can be fixed by restarting Dovecot, allowing it to read the new +certificate, assuming its available at the same path. +

+ +

Long term solution

+

+I already have a cronjob that runs certbot renew once a month to +renew any SSL certificates going stale. I'm going to change it to instead point +to a script that does + +

+certbot renew
+systemctl restart dovecot
+
+ +to automate reloading the certificate. +

+ +

Learnings

+

+A few things I learned while debugging this issue: +

+ +

Viewing certificate info on the command line

+

+My first step was to check the certificate I thought should have been served by +Dovecot. In particular, I wanted to see its expiry date as well as compare its +fingerprint to that reported by my mail client. +

+ +

+Certificates are stored in ASCII armor format, which is not human readable. +Turns out you can get a human readable interpretation of your certificate with +the openssl CLI tool: + +

+openssl x509 -text -noout -in <certificate file>
+
+ +will get you a detailed, human readable output. For example, you can find a +"Validity" section, specifying the time period during which the certificate is +valid. +

+ +

+Adding the -fingerprint flag will also output the fingerprint hash. +The -noout flag is just there to suppress the output of the +non-readable ASCII armor text. +

+ +

Let's Encrypt certificate locations

+

+Currently valid certificates from Let's Encrypt are stored under +/etc/letsencrypt/live/<domain name>/. This is where my +Dovecot server was configured to get its certificate from, so before I realized +that the certificate is only read once, I was surprised that the fingerprint of +the certificate stored here did not match the one my mail client was receiving. +

+ +

+Turns out Let's Encrypt also stores historic certificates under +/etc/letsencrypt/archive/. Here I was able to find the certificate +with a matching fingerprint to the faulty one received by my client, and confirm +that it did indeed expire yesterday. Finding this is what led me to realizing +how Dovecot handles its certificate configuration. +

-- cgit v1.2.3