# Automating acme-client Renewal [acme-client's man page](http://man.openbsd.org/acme-client.1) provides a nice simple crontab entry for common usage. The following is for a mail server running `dovecot` and NO `httpd`. Though it's somewhat specific, it should be trivial to alter the script for one's own needs. ## Shell script As the use-case is not entirely trivial, we opted for a shell script. The output as it stands is fairly verbose, but again, this would be easy to tweak. This script is perhaps a little over-engineered and is open to improvement. It attempts to only do the necessary work and exit cleanly upon any error. Create and edit `/usr/local/bin/renew_cert` (or a filename of your choice - just remember to edit any later commands/files as necessary). The only essential change is to set `` appropriately. #!/bin/ksh # Renew LetsEncrypt certificate(s) for the mail server domain(s) # Returns # 0: Success # 1: Certificate up to date # 2: Error # Print message to stdout or stderr # Messages for stdout are marked [INFO], stderr are marked [ERROR] # Expects # $1: 1|2 (stdout|stderr) # $2: Message text # Silently fails if called badly print_msg() { if [ $# -ne 2 ]; then return fi if [ $1 == "stdout" ]; then outfd=1 tag="[INFO]" elif [ $1 == "stderr" ]; then outfd=2 tag="[ERROR]" else return fi msg=$2 echo "${tag} ${msg}" >&$outfd } # We need http server for acme-client to communicate with LetsEncrypt rcctl check httpd httpd_check=$? # Only start httpd if it's not already running if [ $httpd_check -eq 1 ]; then print_msg stdout "Starting httpd" rcctl -f start httpd if [ $? -ne 0 ]; then print_msg stderr "Failed to start httpd" exit 2 fi fi # Attempt to renew certificate print_msg "Renewing mail server certificate" acme-client acme_check=$? # Only stop httpd if it was not already running if [ $httpd_check -eq 1 ]; then print_msg stdout "Stopping httpd" rcctl stop httpd fi if [ $acme_check -eq 2 ]; then print_msg stdout "Certificate up to date" exit 1 elif [ $acme_check -eq 1 ]; then print_msg stderr "Failed to renew certificate" exit 2 fi print_msg stdout "Successfully renewed certificate" # Serve the new certificate print_msg stdout "Reloading dovecot" rcctl reload dovecot if [ $? -gt 0 ]; then print_msg stderr "Failed to reload dovecot" exit 2 fi ### Permissions `#chmod 700 /usr/local/bin/renew_cert` ## cronjob LetsEncrypt will allow certificate renewal if the expiry is within 30 days. We us a simple cronjob to run our script fortnightly. Output is piped to `logger` to be written to the system log. With your favourite text-editor (`vim`), create or append to `/etc/weekly.local`: test 1 -eq $(($(date +\%25g) & 1)) && renew_cert | logger -t "[acme renewal]" The use of `test` is because running this once every two weeks should be more than enough. The technique was found [ here](https://unix.stackexchange.com/a/197411 ) and seems reasonable. By default `logger` will likely output to `/var/log/messages`, but this can be confirmed by checking your `/etc/syslog.conf`. You may also direct `logger` to output elsewhere; see `-p` in [logger's man page](http://man.openbsd.org/logger.1).