Automatische Erneuerung der LetsEncrypt Wildcard Zertifikate mit DuckDNS

Certbot und DuckDNS

Der Certbot kann die Eingerichten Domänen auch automatisch aktualisieren. Dazu ist für ausgefallene Anwendungszwecke ein Hooksystem integriert, sodass das Aktualisieren der Zertifikate auch unter besonderen Umständen funktioniert.

Wie der Titelschon beschreibt, will ich hier die Automatisation der Erneuerung der Zertifikate mit dem Certbot auf einer DuckDNS Domäne demonstrieren. In diesem Artikel habe ich die Einrichtung von DuckDNS bereits erleutert. Als Zeitgeber setze ich den Systemd Timer ein.

Manuelles ReNew

Die Zertifikate die LetsEncrypt ausstellt haben immer nur einen Gültigskeitszeitraum von genau 3 Monaten. Das heißt alle 3 Monate muss das Zertifikat erneuert und in den WebServer deployt werden, da sonst weiterhin die Aĺten abgelaufenen Zertifikate ausgeliefert werden und somit die Seiten von den Browsern als nicht vertrauenswürdig eingestuft werden.

Für DuckDNS bietet sich die Verifikationsmethode DNS01 an. Bei dieser Methode wird ein TXT Record im DNS Server erwartet. Dieses sogenannte Challenge muss vor der Überprüfung gesetzt werden. Hierfür wird das PRE Hook verwendet, um das Secret in DuckDNS zu setzen.

Die Informationen zu den Hooks kann man hier nachlesen.

Die Skripte die in den Hooks eingesetzt werden in einem Unterverzeichnis /duckdns im Ordner /etc/letsencrypt abgelegt.

Der PRE Hook

Dieses Skript wird in der Vorbereitung der Verifikation der Domäne ausgeführt. Es muss beim dem DNS01 Verfahren, also zum setzen der Challenge im DNS Server, genutzt werden. Dieses Skript hängen wir in den PRE Hook mit dem Parameter –manual-auth-hook ein. Dieser erwartet Pfad zu dem folgenden Skript…

Die Datei set_acme_challenge.sh in /etc/letsencrypt/duckdns/

#!/bin/bash

token="TTTTTTTT-TTTT-TTTT-TTTT-TTTTTTTTTTTT"

# log
echo "renewal of $CERTBOT_DOMAIN with challenge $CERTBOT_VALIDATION" 

# set acme challenge
curl -s "https://www.duckdns.org/update?domains=$CERTBOT_DOMAIN&token=$token&txt=$CERTBOT_VALIDATION"

Im Log werden in den meisten Fällen aufgeführt werden, dass das Aktualisieren nicht durchgeführt worden ist, weil das Zertifikat noch länger als 30 Tage gültig ist. Erst wenn die Gültigkeitsdauer klein 30 Tage ist, dann wird der Certbot eine Aktualisierung durchführen.

DNS Server Aufräumen

Nachdem das Challenge verifiziert worden ist, wird das Challenge auf dem DNS Server von DuckDNS nicht mehr benötigt. Das heißt es kann wieder gelöscht werden. Dazu verwenden wird den Hook –manual-cleanup-hook Parameter.

Die Datei clanup_acme_challenge.sh in /etc/letsencrypt/duckdns/

#!/bin/bash

# DuckDNS Token
token="TTTTTTTT-TTTT-TTTT-TTTT-TTTTTTTTTTTT" 

# clear acme challenge
curl -s "https://www.duckdns.org/update?domains=$CERTBOT_DOMAIN&token=$token&txt=$CERTBOT_VALIDATION&clear=true

Das aktuelle Zertifikat dem WebServer bekannt machen

Nachdem nun der Certbot das aktuelle Zertifikat bereitgestellt hat, dann muss das dem WebServer bekannt gemacht werden. Da ich den NginX WebServer einsetze, muss ich also ein systemctl reload nginx.service ausführen. Dies übergeben wir einfach direkt dem Deploy-Hook mit

--deploy-hook "systemctl reload nginx.service"

Der komplette Aufruf

Wenn wir jetzt alles zusammenführen, dann ergibt sich folgender Aufruf:

certbot renew --manual-auth-hook=/etc/letsencrypt/duckdns/set_acme_challenge.sh --manual-cleanup-hook=/etc/letsencrypt/duckdns/clear_acme_challenge.sh --deploy-hook "systemctl reload nginx.service"

Für Debuggingzwecke empfiehlt es sich sich noch den DRY RUN Modus mit dem Parameter –dry-run zu aktivieren.

Den Systemd Timer anlegen

Der certbot.service:

[Unit]
Description=Let's Encrypt renewal

[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --manual-auth-hook=/etc/letsencrypt/duckdns/set_acme_challenge.sh --manual-cleanup-hook=/etc/letsencrypt/duckdns/clear_acme_challenge.sh --deploy-hook "systemctl reload nginx.service"

Der certbot.timer:

[Unit]
Description=Twice daily renewal of Let's Encrypt's certificates

[Timer]
OnCalendar=0/12:00:00
RandomizedDelaySec=1h
Persistent=true

[Install]
WantedBy=timers.target

Log

Das Log kann mit journalctl -n50 -fu certbot.service eingesehen werden:

Nov 24 14:14:04 server systemd[1]: Starting Let's Encrypt renewal...
Nov 24 14:14:07 server certbot[2160]: Saving debug log to /var/log/letsencrypt/letsencrypt.log
Nov 24 14:14:07 server certbot[2160]: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Nov 24 14:14:07 server certbot[2160]: Processing /etc/letsencrypt/renewal/XXXX.duckdns.org.conf
Nov 24 14:14:07 server certbot[2160]: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Nov 24 14:14:08 server certbot[2160]: Cert not yet due for renewal
Nov 24 14:14:08 server certbot[2160]: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Nov 24 14:14:08 server certbot[2160]: The following certs are not due for renewal yet:
Nov 24 14:14:08 server certbot[2160]:   /etc/letsencrypt/live/XXXX.duckdns.org/fullchain.pem expires on 2020-02-21 (skipped)
Nov 24 14:14:08 server certbot[2160]: No renewals were attempted.
Nov 24 14:14:08 server certbot[2160]: No hooks were run.
Nov 24 14:14:08 server certbot[2160]: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Nov 24 14:14:08 server systemd[1]: certbot.service: Succeeded.
Nov 24 14:14:08 server systemd[1]: Started Let's Encrypt renewal.