6.12.2023
Encryption is a mandatory part of many web sites and various network services (VPN, mail, cups, etc.) today. It's straightforward to issue a Let's Encrypt certificate using utilities like certbot or acme.sh. On many servers, we use the acme.sh utility, but it is essential problem with restarting servers after certificate renewal. It's not complicated, but it is poorly documented and no one really knows how to do it.
Create a simple script to copy certificates, for example /usr/local/bin/certificates-changed:
#!/bin/bash cp /root/.acme.sh/www.hobrasoft.cz/www.hobrasoft.cz.cer /etc/ssl/apache/www.hobrasoft.cz.crt cp /root/.acme.sh/www.hobrasoft.cz/www.hobrasoft.cz.key /etc/ssl/apache/www.hobrasoft.cz.key systemctl restart apache2
For your already issued certificates, add the
Le_RenewHook
parameter to the configuration file
/root/.acme.sh/www.hobrasoft.cz/www.hobrasoft.cz.conf
Le_Domain='www.hobrasoft.cz' Le_PreHook='' Le_PostHook='' Le_RenewHook='/usr/local/bin/certificates-changed' ...
The certificates should be renewed (usually without problem) and deployed automatically
by a periodic invoking of the acme.sh with the --cron
parameter.
The acme.sh creates crontab record at the installation time:
0 0 * * * /root/.acme.sh/acme.sh --cron --home /root/.acme.sh
The help shows parameters
--pre-hook <command>
(command to be run before obtaining any certificates),
--post-hook <command>
(command to be run after attempting to obtain/renew certificates, runs regardless of whether obtain/renew succeeded or failed) and
--renew-hook <command>
(command to be run after each successfully renewed certificate),
but any attempt to use them usually end in failure.
This is because these parameters are active only when creating a new certificate.
They do not invoke required hook, they only write required values to configuration file.
When used in other actions (typically renew), these parameters are ignored.
The first call of acme.sh when new certificate is issued should look like this:
/root/.acme.sh/acme.sh --standalone --listen-v6 --issue --domain www.hobrasoft.cz \ --pre-hook /usr/local/bin/certificates-changed-pre \ --post-hook /usr/local/bin/certificates-changed-post \ --renew-hook /usr/local/bin/certificates-changed
It's pretty pointless trying to use the --deploy
and --deploy-hook
parameters - they don't work as you'd expect.
When issuing a certificate for the first time, deploy the certificate manually. After the certificate is issued successfully,
the configuration file /root/.acme.sh/www.hobrasoft.cz/www.hobrasoft.cz.conf should look like this:
Le_Domain='www.hobrasoft.cz' Le_PreHook='' Le_PostHook='' Le_RenewHook='__ACME_BASE64__START_L3Vzci9sb2NhbC9iaW4vY2VydGlmaWNhdGVzLWNoYW5nZWQ=__ACME_BASE64__END_' ...
The string __ACME_BASE64...
is nothing mysterious. It is base64
encoded string /usr/local/bin/certificates-changed
and it works
exactly as plain text.
The --pre-hook
and --post-hook
parameters are useful if you use
certificates with haproxy, for example.
It is convenient to stop haproxy before attempting to renew the certificate, then
renew certificate (by calling acme.sh with --standalone
parameter)
and then start haproxy again.
Without the temporary stop, both the haproxy and acme.sh try to
bind port 80 and attempting to renew the certificate would fail.
Reliable automatic certificate renewal and deployment using acme.sh can sometimes take years because you only have 4 chances to try out annually.
There is very little information on the Internet. I have never found a reliable guide. This article therefore aspires to be the most cited text on automatic certificate renewal in the world.