From 94aaf246d6659e4d417d8958d210c275185746a8 Mon Sep 17 00:00:00 2001 From: Matt Birkholz Date: Sun, 21 Dec 2025 16:39:49 -0700 Subject: [PATCH] Do not require Let's Encrypt. Add renewal hook to reload Dovecot. =/etc/letsencrypt/= is created by the CertBot installation. =/etc/letsencrypt/live/= is created by Let's Encrypt(). Use the latter to conditionalize the Let's Encrypt tasks. This avoid failures on prospective Front machines running without Let's Encrypt keys installed / restored. --- README.org | 61 +++++++++++++++++++++----- roles_t/abbey-front/files/certbot_hook | 2 + roles_t/abbey-front/tasks/main.yml | 25 +++++++++-- 3 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 roles_t/abbey-front/files/certbot_hook diff --git a/README.org b/README.org index 5d57e0c..7bc838a 100644 --- a/README.org +++ b/README.org @@ -670,11 +670,20 @@ package is installed and its =live/= subdirectory is world readable. become: yes apt: pkg=python3-certbot-apache -- name: Ensure Let's Encrypt certificate is readable. +- name: Look for /etc/letsencrypt/live/. + stat: + path: /etc/letsencrypt/live + register: letsencrypt +- debug: + msg: "/etc/letsencrypt/live/ does not (yet) exist" + when: not letsencrypt.stat.exists + +- name: "Ensure Let's Encrypt certificate is readable." become: yes file: mode: u=rwx,g=rx,o=rx path: /etc/letsencrypt/live + when: letsencrypt.stat.exists #+END_SRC Front's Dovecot (and Postfix) certificate and key are in separate @@ -683,19 +692,22 @@ pair of files) mainly because that is how they are provided (and updated) by Let's Encrypt, but also because Let's Encrypt's symbolic links keep the window for a mismatch extremely small. -With the institutional configuration, Postfix, Dovecot and Apache -servers get their certificate&key from =/etc/server.crt&.key=. The -institutional roles check that they exist, but will not create them. -In this abbey specific role, =/etc/server.crt&key= are ours to frob. -The following tasks ensure they are symbolic links to -=/etc/letsencrypt/live/birchwood-abbey.net/fullchain&privkey.pem=. If -=/etc/letsencrypt/= was restored from a backup, the servers should be -restarted manually. +A small institute configures its Postfix, Dovecot and Apache servers +use the certificate in =/etc/server.crt=. Ansible copies the small +institute's self-signed (private) certificate there, but only if the +file does not exist. This abbey specific role is free to symbolically +link this file (and the corresponding =/etc/server.key= file) to +=/etc/letsencrypt/live/birchwood-abbey.net/fullchain.pem= (and +=privkey.pem=). + +If =/etc/letsencrypt/= was restored from a backup, the servers should +be restarted manually. #+CAPTION: [[file:roles_t/abbey-front/tasks/main.yml][=roles_t/abbey-front/tasks/main.yml=]] #+BEGIN_SRC conf :tangle roles_t/abbey-front/tasks/main.yml -- name: Use Let's Encrypt certificate&key. +- name: "Use Let's Encrypt certificate&key." + become: yes file: state: link src: "{{ item.target }}" @@ -706,6 +718,33 @@ restarted manually. link: /etc/server.crt - target: /etc/letsencrypt/live/birchwood-abbey.net/privkey.pem link: /etc/server.key + when: letsencrypt.stat.exists +#+END_SRC + +** Restart servers caching the Let's Encrypt certificate. + +#+CAPTION: [[file:roles_t/abbey-front/tasks/main.yml][=roles_t/abbey-front/tasks/main.yml=]] +#+BEGIN_SRC conf :tangle roles_t/abbey-front/tasks/main.yml + +- name: Install Certbot hook. + become: yes + copy: + src: certbot_hook + dest: /etc/letsencrypt/renewal-hooks/post/restart-abbey-servers + mode: u=rwx,g=rx,o=rx + when: letsencrypt.stat.exists +#+END_SRC + +The Dovecot IMAP server seems to cache the Let's Encrypt certificate. +Whenever it runs for more than 3 months (i.e. every 3 months), email +stops flowing because fetchmail notices the server certificate has +expired. The Postfix and Apache2 servers seem not to cache their +server certificate. + +#+CAPTION: [[file:roles_t/abbey-front/files/certbot_hook][=roles_t/abbey-front/files/certbot_hook=]] +#+BEGIN_SRC conf :tangle roles_t/abbey-front/files/certbot_hook +#!/bin/bash +systemctl reload dovecot #+END_SRC ** Rotate Let's Encrypt Log @@ -742,7 +781,7 @@ are detected by keeping a copy in =/etc/letsencrypt~/= for comparison. #+CAPTION: [[file:roles_t/abbey-front/tasks/main.yml][=roles_t/abbey-front/tasks/main.yml=]] #+BEGIN_SRC conf :tangle roles_t/abbey-front/tasks/main.yml -- name: Install Let's Encrypt archive script. +- name: "Install Let's Encrypt archive script." become: yes copy: src: cron.daily_letsencrypt diff --git a/roles_t/abbey-front/files/certbot_hook b/roles_t/abbey-front/files/certbot_hook new file mode 100644 index 0000000..6c923c6 --- /dev/null +++ b/roles_t/abbey-front/files/certbot_hook @@ -0,0 +1,2 @@ +#!/bin/bash +systemctl reload dovecot diff --git a/roles_t/abbey-front/tasks/main.yml b/roles_t/abbey-front/tasks/main.yml index f5d560b..9b1fe83 100644 --- a/roles_t/abbey-front/tasks/main.yml +++ b/roles_t/abbey-front/tasks/main.yml @@ -157,13 +157,23 @@ become: yes apt: pkg=python3-certbot-apache -- name: Ensure Let's Encrypt certificate is readable. +- name: Look for /etc/letsencrypt/live/. + stat: + path: /etc/letsencrypt/live + register: letsencrypt +- debug: + msg: "/etc/letsencrypt/live/ does not (yet) exist" + when: not letsencrypt.stat.exists + +- name: "Ensure Let's Encrypt certificate is readable." become: yes file: mode: u=rwx,g=rx,o=rx path: /etc/letsencrypt/live + when: letsencrypt.stat.exists -- name: Use Let's Encrypt certificate&key. +- name: "Use Let's Encrypt certificate&key." + become: yes file: state: link src: "{{ item.target }}" @@ -174,6 +184,15 @@ link: /etc/server.crt - target: /etc/letsencrypt/live/birchwood-abbey.net/privkey.pem link: /etc/server.key + when: letsencrypt.stat.exists + +- name: Install Certbot hook. + become: yes + copy: + src: certbot_hook + dest: /etc/letsencrypt/renewal-hooks/post/restart-abbey-servers + mode: u=rwx,g=rx,o=rx + when: letsencrypt.stat.exists - name: Install Certbot logrotate configuration. become: yes @@ -182,7 +201,7 @@ dest: /etc/logrotate.d/certbot mode: u=rw,g=r,o=r -- name: Install Let's Encrypt archive script. +- name: "Install Let's Encrypt archive script." become: yes copy: src: cron.daily_letsencrypt -- 2.47.3