m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
path: root/src/blog
diff options
context:
space:
mode:
authorMarcin Chrzanowski <m@m-chrzan.xyz>2021-05-12 16:14:42 +0200
committerMarcin Chrzanowski <m@m-chrzan.xyz>2021-05-12 16:14:42 +0200
commitd68be22176db3d7947682c945c16a44396a024c0 (patch)
tree03c87038adbff81cac3c22ff99950c11e3ee6197 /src/blog
parent5669a274b156b57d5b2e9e5427006a8626de143e (diff)
Add Dovecot SSL post
Diffstat (limited to 'src/blog')
-rw-r--r--src/blog/dovecot-ssl-certificate-renewal.erb.html97
1 files changed, 97 insertions, 0 deletions
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
+---
+<p>
+Just a quick technical note.
+</p>
+
+<p>
+As mentioned before, I
+<a href='<%= path_to "blog_hosting-on-vultr-vps" %>'>
+ started self hosting email
+</a> 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.
+</p>
+
+<p>
+After a few minutes of worrying if I'm being man-in-the-middled, I ssh'd into my
+VPS to debug.
+</p>
+
+<h3>TL;DR: Root cause and solution</h3>
+<p>
+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.
+</p>
+
+<p>
+This can be fixed by restarting Dovecot, allowing it to read the new
+certificate, assuming its available at the same path.
+</p>
+
+<h4>Long term solution</h4>
+<p>
+I already have a cronjob that runs <code>certbot renew</code> once a month to
+renew any SSL certificates going stale. I'm going to change it to instead point
+to a script that does
+
+<pre>
+certbot renew
+systemctl restart dovecot
+</pre>
+
+to automate reloading the certificate.
+</p>
+
+<h3>Learnings</h3>
+<p>
+A few things I learned while debugging this issue:
+</p>
+
+<h4>Viewing certificate info on the command line</h4>
+<p>
+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.
+</p>
+
+<p>
+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 <code>openssl</code> CLI tool:
+
+<pre>
+openssl x509 -text -noout -in &lt;certificate file&gt;
+</pre>
+
+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.
+</p>
+
+<p>
+Adding the <code>-fingerprint</code> flag will also output the fingerprint hash.
+The <code>-noout</code> flag is just there to suppress the output of the
+non-readable ASCII armor text.
+</p>
+
+<h4>Let's Encrypt certificate locations</h4>
+<p>
+Currently valid certificates from Let's Encrypt are stored under
+<code>/etc/letsencrypt/live/&lt;domain name&gt;/</code>. 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.
+</p>
+
+<p>
+Turns out Let's Encrypt also stores historic certificates under
+<code>/etc/letsencrypt/archive/</code>. 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.
+</p>