This is my first attempt at renewing Let's Encrypt certificates via Certbot. After carefully reading the Certbot user guide I created two post hook scripts like this:
root@pelargir:~# ls -l /etc/letsencrypt/renewal-hooks/post
total 8
-rwxr-xr-x 1 root root 697 Aug 29 16:35 10-setup-courier.sh
-rwxr-xr-x 1 root root 377 Aug 29 16:32 20-restart-services.sh
I then ran the renewal process manually on the command line (i.e. not via cron). This was successful in renewing the certificates, but it failed to execute the above post hook scripts. Here is the relevant output:
[...]
Running post-hook command: /etc/letsencrypt/renewal-hooks/post/10-setup-courier.sh
Hook command "/etc/letsencrypt/renewal-hooks/post/10-setup-courier.sh" returned error code 127
Error output from 10-setup-courier.sh:
/bin/sh: /etc/letsencrypt/renewal-hooks/post/10-setup-courier.sh: not found
Running post-hook command: /etc/letsencrypt/renewal-hooks/post/20-restart-services.sh
Hook command "/etc/letsencrypt/renewal-hooks/post/20-restart-services.sh" returned error code 127
Error output from 20-restart-services.sh:
/bin/sh: /etc/letsencrypt/renewal-hooks/post/20-restart-services.sh: not found
[...]
I have no idea why this happens. I double-checked:
- The script files exist
- The script files are executable
- I can run the scripts manually (with the environment variables
RENEWED_DOMAINS
andRENEWED_LINEAGE
set and exported) and they do their job as expected
One other thing that I probably should mention is that I run Certbot within a Docker image because I am working with wildcard certificates. My DNS provider is Cloudflare. Here's the command line that I am using to start the renewal process:
docker run -it --rm --name certbot \
-v "/etc/letsencrypt:/etc/letsencrypt" \
-v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
certbot/dns-cloudflare
renew
The Docker image runs Certbot version 0.25.0. The system is Debian 9 (stretch), recently upgraded from Debian 8 (jessie).
Any clues what the problem could be?
EDIT: As requested, here is the content of the two files, slightly edited to replace my domain with "example.com":
root@pelargir:~# cat /etc/letsencrypt/renewal-hooks/post/10-setup-courier.sh
#!/bin/bash
# Exit immediately if a command exits with non-zero status
set -e
case $RENEWED_DOMAINS in
# Courier runs only under a example.com subdomain
example.com)
# We don't care about file permissions because we know that the
# filesystem folder where we generate the file is not generally
# accessible
cat "$RENEWED_LINEAGE/fullchain.pem" "$RENEWED_LINEAGE/privkey.pem" >"$RENEWED_LINEAGE/courier.cert-and-key.unsecure"
;;
esac
root@pelargir:~# cat /etc/letsencrypt/renewal-hooks/post/20-restart-services.sh
#!/bin/bash
# Exit immediately if a command exits with non-zero status
set -e
case $RENEWED_DOMAINS in
# Courier and Exim run only under a example.com subdomain
*example.com*)
systemctl restart courier-imap.service
systemctl restart exim4.service
systemctl restart apache2.service
;;
# Apache has vhosts for all domains. Unfortunately the daemon is
# restarted several times if several certificates are renewed.
*)
systemctl restart apache2.service
;;
esac