Let’s Encrypt™ Zertifikat mit nginx und dehydrated

Update 15.09.2016:
Dieser Beitrag wurde ursprünglich über letsencrypt.sh geschrieben. Aufgrund einer Markenrechtsverletzung wurde letsencrypt.sh jedoch inzwischen in dehydrated umbenannt.
Der folgende Beitrag wurde daher an den neuen Namen angepasst.
Logo Let's Encrypt

Seit kurzem kann man sich kostenlos ein Let’s Encrypt™ Server-Zertifikat ausstellen lassen, das von allen Browsern akzeptiert wird. Bei der Erstellung des Zertifikats bleibt der private Schlüssel auch wirklich privat, da er das eigene System nicht verlässt. Dumm nur, wenn man wie ich als Webserver nginx statt Apache einsetzt, denn damit kann die offizielle Client-Software nicht umgehen. Zudem wird vom offiziellen Client vorausgesetzt, dass man einige zusätzliche Pakete installiert (und sich damit womöglich auch zusätzliche Sicherheitslücken auf den Server holt). Es gibt jedoch auch andere Wege zu einem kostenlosen Let’s Encrypt™ Zertifikat zu kommen. Einer davon führt über das Bash-Skript dehydrated, das nur openssl, curl, sed, grep und mktemp benötigt, die auf den meisten Systemen vorhanden sein dürften: https://github.com/lukas2511/dehydrated. Die Einrichtung ist nicht sehr schwer:

Da ich das Skript dehydrated nicht als root ausführen möchte, wird zunächst ein neuer Nutzer dehydrated ohne Login-Rechte erstellt, der der Gruppe www-data angehört:

adduser --no-create-home --ingroup "www-data" --disabled-login --gecos "" dehydrated

Die Überprüfung, ob man Eigentümer der entsprechenden Domain ist, erfolgt durch Anlegen einer bestimmten Datei auf dem Server unter /.well-known/acme-challenge, die dann der Let’s Encrypt™ Server über http abruft. Dieser Vorgang wird acme-challenge genannt. Hierfür folgenden location-Block in die nginx-Konfiguration des entsprechenden Servers im http-Bereich (Port 80) einfügen:

location /.well-known/acme-challenge {
      alias /var/www/dehydrated;
}

Den Ordner für die acme-challenge erstellen, dem User dehydrated:www-data zuweisen und nginx die oben gemachte Konfigurationsänderung einlesen lassen:

mkdir -p /var/www/dehydrated
chown -R dehydrated:www-data /var/www/dehydrated
nginx -s reload

Zum Testen empfiehlt es sich, eine Datei in diesem Ordner abzulegen, dem user dehydrated:www-data zuzuweisen und zu überprüfen, ob man sie aufrufen kann (die Beispieldomain subdomain.example.com hier und im weiteren Verlauf des Beitrages entsprechend ersetzen). Alternativ zu curl kann der Link auch in einen Browser eingegeben werden:

echo "Test OK" > /var/www/dehydrated/test.html
chown dehydrated:www-data /var/www/dehydrated/test.html
curl http://subdomain.example.com/.well-known/acme-challenge/test.html

Wenn Test OK ausgegeben wird, ist alles OK.

dehydrated von Github clonen und die Konfigurationsdateien in einen externen Ordner kopieren:

cd /usr/local/bin/
git clone https://github.com/lukas2511/dehydrated
mkdir /etc/dehydrated
chown -R dehydrated:www-data /etc/dehydrated
cp dehydrated/docs/examples/config /etc/dehydrated/
cp dehydrated/docs/examples/domains.txt /etc/dehydrated/

Die Domains, für die Zertifikate erstellt werden sollen, müssen in die Datei /etc/dehydrated/domains.txt eingetragen werden (pro Zeile eine Domain mit ihren Subdomains eintragen) – z.B:

example.com www.example.com
example.net www.example.net wiki.example.net

In der Konfiguationsdatei /etc/dehydrated/config muss nichts geändert werden. Optional kann man am Ende der Datei eine E-Mail-Adresse angeben, an die der Let’s Encrypt™ Server eine Benachrichtigung verschickt, sollten die Zertifikate bald ablaufen.

Zum Testen, ob alles funktioniert, emfpiehlt es sich zunächst den Let’s Encrypt™ Staging-Server zu benutzen, um kein Anfrage-Limit zu überschreiten. Hierfür in der Datei /etc/dehydrated/config folgende Zeile ganz am Ende hinzufügen:

CA="https://acme-staging.api.letsencrypt.org/directory"

Zunächst muss den Nutzungsbedingungen zugestimmt werden mit:

sudo -u dehydrated /usr/local/bin/dehydrated/dehydrated --register --accept-terms

Nun kann vom Staging-Server ein Zertifikat angefordert werden mit:

sudo -u dehydrated /usr/local/bin/dehydrated/dehydrated -c

Wichtig: Falls Fehlermeldungen ausgegeben werden, müssen diese zuerst behoben werden, bevor es weitergeht!

Wenn keine Fehlermeldung ausgegeben wurde, die gerade eingefügte Zeile mit dem Staging-Server am Ende der Datei /etc/dehydrated/config löschen und damit den Let’s Encrypt™ Live-Server aktivieren. Außerdem muss sowohl der Ordner /etc/dehydrated/certs mit den Staging-Zertifikaten als auch der Ordner /etc/dehydrated/accounts gelöscht werden:

rm -r /etc/dehydrated/certs /etc/dehydrated/accounts

Nach erneutem Zustimmen der Nutzungsbedingungen kann das Zertifikat angefordert werden (vom Live-Server):

sudo -u dehydrated /usr/local/bin/dehydrated/dehydrated --register --accept-terms
sudo -u dehydrated /usr/local/bin/dehydrated/dehydrated -c

Die Zertifikate sollten nun erstellt und im Ordner /etc/dehydrated/certs/subdomain.example.com/ abgespeichert worden sein. Die Konfiguration des entsprechenden Servers (unter /etc/nginx/sites-available/) muss nun noch dahingehend geändert werden, dass die neu erstellten Zertifikate eingelesen werden. Im https-Block folgende Zeilen hinzufügen (Pfade anpassen!):

ssl_certificate /etc/dehydrated/certs/subdomain.example.com/fullchain.pem;
ssl_certificate_key /etc/dehydrated/certs/subdomain.example.com/privkey.pem;

Nginx die neue Konfiguration einlesen lassen, damit sie wirksam wird:

nginx -s reload

Ab sofort liefert nginx ein gültiges Let’s Encrypt™ SSL-Zertifikat aus, das alle Browser als vertrauenswürdig einstufen. Überprüfen lässt sich das z.B. mit:

curl -v https://subdomain.example.com/ 2>&1 | grep "^\*"

Da Let’s Encrypt™ Zertifikate nur 90 Tage gültig sind, kann man sich einen Cronjob einrichten, der wöchentlich überprüft wielange das Zertifikat noch gültig ist, es automatisch verlängert (falls die Gültigkeit weniger als 30 Tage beträgt) und dann nginx die neuen Zertifikate einlesen lässt. Klingt kompliziert, ist aber durch Hinzufügen der folgenden Zeile in /etc/crontab erledigt (Überprüfung erfolgt jeden Mittwoch um 07:00 Uhr):

00 07   * * 3 root  sudo -u dehydrated /usr/local/bin/dehydrated/dehydrated -c > /var/log/dehydrated.log 2>&1 && nginx -s reload

Ein Log der letzten Überprüfung findet man unter /var/log/dehydrated.log.

Ab jetzt muss man sich um nichts mehr kümmern. Sehr schön! Ich bin überrascht, wie reibungslos und schnell das alles funktioniert. Durch die Automatisierung per Cronjob muss ich an nichts mehr denken und kann keine Fristen verschlafen. Das Zertifikat wird von allen Browsern akzeptiert und es enthält die gesamte Zertifikatskette, so man damit sogar OCSP-Stapling einrichten kann. Wie man https mit nginx weiter absichern kann, wird sehr gut hier beschrieben: https://www.sherbers.de/howto/nginx/.

Changelog:
15.09.2016: Änderung: letsencrypt.sh —> dehydrated
03.09.2017: Zustimmen der Nutzungsbedingungen hinzugefügt

( Let’s Encrypt™ ist ein Warenzeichen der Internet Security Research Group. Alle Rechte vorbehalten. )

Ein Kommentar on "Let’s Encrypt™ Zertifikat mit nginx und dehydrated"

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.