This is an old revision of the document!
Table of Contents
Let's Encrypt
Bei Let's Encrypt handelt es sich um eine offene Zertifizierungsstelle, bei der man kostenlos X.509-Zertifikate für TLS1) (ehemals SSL) erstellen kann. Gegründet wurde das Projekt 2014 von der EFF2), Mozilla und der University of Michigan. Am 3. Dezember 2015 startete die öffentliche Beta-Phase, ab der man ohne vorherige Einladung mithilfe des in Python geschriebenen letsencrypt-Clients weitestgehend automatisiert Zertifikate für den eigenen Server erhalten kann.
Installation ohne Wrapper
Unter Arch Linux befindet sich der letsencrypt-Client in den Community-Quellen und kann mittels
# pacman -S letsencrypt
einfach installiert werden. Anstatt alle Einstellungen als Argumente zu übergeben, besteht auch die Möglichkeit, eine Konfigurationsdatei zu erstellen. Standardmäßig sucht der Client nach /etc/letsencrypt/cli.ini. Im Folgenden will ich alles weitestgehend automatisieren und erstelle Domain-spezifische Konfigurationsdateien.
# vim /etc/letsencrypt/domain.tld.cnf
In diese Datei kommt der folgende Inhalt:
- /etc/letsencrypt/domain.tld.cnf
# Use a 4096 bit RSA key instead of 2048 rsa-key-size = 4096 # use the webroot authenticator authenticator = webroot webroot-path = /tmp/letsencrypt/ # Use acme-v01 server (public beta), should be used by default #server = https://acme-v01.api.letsencrypt.org/directory # Uncomment and update to register with the specified e-mail address email = mail@domain.tld renew-by-default agree-tos # domain list domains = domain.tld, www.domain.tld, subdomain.domain.tld # Uncomment to use a text interface instead of ncurses text = True
Bei der erstmaligen Verwendung wird ein Benutzerkonto angelegt, das mit der E-Mail-Adresse verknüpft ist und unter /etc/letsencrypt/accounts wichtige Dateien wie den Private Key ablegt.
nginx
Bevor die Zertifikate ausgestellt werden, wird nach dem ACME3)-Protokoll dem Challenge-Response-Verfahren folgend eine mit dem Private Key verifizierte Challenge erstellt. Um den Besitz der Domains zu überprüfen, versucht der ACME-Server die jeweilige Challenge passend zur (Sub-)Domain unter (subdomain.)domain.tld/.well-know/acme-challenge/kryptographischerstring abzurufen. Dazu müssen wir nginx beibringen, wie es die Challenge ausliefert. Dazu in jeden server {} Block, zu dem ein Zertifikat ausgestellt werden soll, die folgende location einfügen:
location ~ '/.well-known/acme-challenge' { default_type "text/plain"; root /tmp/letsencrypt; }
Danach mit
# systemctl restart nginx
den nginx-Server neustarten, damit die Änderungen übernommen werden.
Damit haben wir die Vorbereitungen abgeschlossen und können mit der Ausstellung der Zertifikate beginnen.
Ausführung
Zuerst erstellen wir den unter webroot-path angegebenen Pfad, da sich der letsencrypt-Client ansonsten mit einer Fehlermeldung beendet:
$ mkdir /tmp/letsencrypt
Nun können wir den Vorgang mit
# letsencrypt certonly -c /etc/letsencrypt/domain.tld.cnf
starten. Das Ganze dauert ein wenig; was aktuell ausgeführt wird, kann durch hinzufügen der Flag -v am Ende des Befehls angezeigt werden. War alles erfolgreich, müssen wir nur noch die Zertifikate in nginx einbinden.
Sollte etwas schief gelaufen sein, kann unter /var/log/letsencrypt/letsencrypt.log der Log des letzten Vorgangs eingesehen werden.
Zertifikate in nginx
Die fertigen Zertifikate werden unter /etc/letsencrypt/live/domain.tld abgespeichert. Entsprechend müssen wir die Pfade in die jeweiligen server {} Blöcke der nginx.conf einfügen:
ssl_certificate /etc/letsencrypt/live/domain.tld/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/domain.tld/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/domain.tld/fullchain.pem;
Dabei wird ssl_trusted_certificate nur für OCSP Stapling benötigt. Soll OCSP Stapling aktiviert werden, sollte Folgendes im http {} Block der nginx.conf stehen:
# enable ocsp stapling (reduces amount of time until first byte) ssl_stapling on; ssl_stapling_verify on;
Zum Schluss noch mit
# systemctl restart nginx
den nginx-Server neustarten.
Mehr zu nginx und den SSL/TLS spezifischen Einstellungen für mehr Sicherheit kann hier gefunden werden.
Erneuerung der Zertifikate
Das Erneuern der Zertifikate ist denkbar einfach und läuft analog zu der erstmaligen Ausführung ab. Da alle Einstellungen in einer Konfigurationsdatei hinterlegt sind, kann mit dem Aufruf von
# letsencrypt certonly --renew -c /etc/letsencrypt/domain.tld.cnf
die Erneuerung angestoßen werden. Ist das Skript durchgelaufen, muss der Server nur noch mit
# systemctl restart nginx
neugestartet werden, um die neuen Zertifikate zu laden. Fertig.
Automatisierung mittels cron
Der Vorteil von Let's Encrypt besteht darin, dass nach Möglichkeit alles automatisch ablaufen soll und einem der Client das erstellen von Certificate Signing Requests etc. abnimmt. Aus diesem Grund sind die Zertifikate auch aktuell nur auf eine Laufzeit von 90 Tagen ausgelegt. Später, wenn alles gut läuft, soll die Gültigkeit auf nur 30 Tage herabgesetzt werden. Aus diesem Grund kann es von Vorteil sein, wenn der Server sich automatisch ohne Zutun von außen um die Erneuerung der Zertifikate kümmert.
Dazu habe ich folgendes Bash-Skript erstellt, welches dafür sorgt, dass das verwendete webroot-Verzeichnis existiert, die Zertifikate erneuert werden und bei erfolgreicher Ausstellung nginx neugestartet wird:
- /etc/letsencrypt/renew.sh
#!/usr/bin/bash # Automate certificate renewal for a given domain, assuming all necessary config parameters are set in /etc/letsencrypt/domain.tld.cnf # Usage: /etc/letsencrypt/renew.sh domain.tld DOMAIN=${1?"No argument given! Please provide the domain which should be renewed"} EMAIL=$(awk '/email/ {print $3}' /etc/letsencrypt/$DOMAIN.cnf) if [ ! -f /etc/letsencrypt/$DOMAIN.cnf ]; then echo "Config file /etc/letsencrypt/$DOMAIN.cnf does not exist!" exit 1; fi # Renew Let's Encrypt SSL cert mkdir -p /tmp/letsencrypt letsencrypt certonly --renew -c /etc/letsencrypt/$DOMAIN.cnf if [ $? -ne 0 ]; then ERRORLOG=`tail /var/log/letsencrypt/letsencrypt.log` echo -e "The Lets Encrypt Cert has not been renewed!\n\n" $ERRORLOG | mail -s "Lets Encrypt Cert Alert" $EMAIL else systemctl restart nginx fi rm -rf /tmp/letsencrypt exit 0
Ist das Skript ausführbar
# chmod +x /etc/letsencrypt/renew.sh
muss es mit der Domain aufgerufen werden, die erneuert werden soll:
# /etc/letsencrypt/renew.sh domain.tld
Sollte etwas schief laufen, wird eine E-Mail an admin@domain.tld gesendet, vorausgesetzt, der Server ist dazu eingerichtet, Mails versenden zu können.
Dieses Skript können wir mittels cron in definierten Zeitintervallen ausführen lassen, wozu ein Befehl in crontab hinzugefügt wird. Mit
# crontab -e
können neue Befehle hinzugefügt werden. Wird etwas geändert, lädt cron die neuen Befehle automatisch. Mit
# crontab -l
können alle registrierten cron-Jobs angezeigt werden.
Sollen die Zertifikate z. B. alle zwei Wochen erneuert werden, und zwar montags um 5 Uhr nachts, können wir folgendes mit crontab -e eintragen:
# renew letsencrypt certificates for domain domain.tld every other monday at 5:00 0 5 * * 1 expr `date +\%W` \% 2 > /dev/null || /etc/letsencrypt/renew.sh domain.tld
cron-Regeln testen
Sollten die cron-Regeln eher kryptisch anmuten, ist es mit der Cron Sandbox möglich, sich die nächsten Termine anzeigen zu lassen, die mit der jeweiligen Regel zutreffen.
Komplett manuell ohne Client
Es ist auch möglich, komplett manuell ohne Verwendung des letsencrypt-Clients Zertifikate zu beziehen. Dazu hat jemand eine statische Seite geschrieben, bei der man sich selbst um die Arbeit kümmern muss: https://gethttpsforfree.com/. Dazu sollte man jedoch wissen, wie man Zertifikate mit einem CSR beantragt.
