DecaTec

Home-Server | Linux | Nextcloud | Raspberry Pi | Programmierung | Fotografie

Let’s Encrypt Zertifikate mit acme.sh und nginx

Let's Encrypt Logo

Wer eine eigene Website oder auch eine Nextcloud-Instanz betreibt, der sollte auch großen Wert auf Sicherheit legen. In der heutigen Zeit gehört dabei HTTPS zum Sicherheits-Standard, wenn es um die verschlüsselte Übertragung von Daten im Internet geht.

Um die eigene Seite mittels HTTPS abzusichern, ist zunächst einmal ein SSL-Zertifikat notwendig. Früher musste man sich ein solches Zertifikat von einer Zertifizierungsstelle für viel Geld kaufen. Im Jahr 2015 trat jedoch Let’s Encrypt auf den Plan – eine Zertifizierungsstelle, die kostenlos Zertifikate für TLS anbietet, um damit verschlüsselte Verbindungen im Web zum Standard zu machen. Gerade im privaten Bereich hat sich Let’s Encrypt zu einem de-facto Standard entwickelt.

Seitdem kann sich jedermann selbst Zertifikate für HTTPS ausstellen lassen. Dazu wird lediglich ein Let’s Encrypt Client benötigt, der die eigentliche Generierung der Zertifikate übernimmt. In meinen Tutorials habe ich bisher immer Certbot als Client für Let’s Encrypt empfohlen, da dieses Programm in den Paketquellen fast aller Distributionen enthalten ist. Dennoch könnte sich genau dieser Umstand als Nachteil erweisen. So schaltet Let’s Encrypt aus Sicherheitsgründen das Validierungsverfahren „TLS-SNI-01“ bald ab. Nutzer von Debian laufen bald Gefahr, dass die Zertifikate nicht mehr erneuert werden können, da die Version von Certbot in Debian Stable zu alt ist und keine anderen Validierungsmethoden unterstützt (siehe hier).

Ein alternativer Let’s Encrypt Client ist acme.sh. Wie der Name bereits vermuten lässt, handelt es sich hierbei um ein reines Shell-Skript, welches die Generierung der Zertifikate übernimmt. Man ist damit nicht mehr von Programmen in den Paketquellen der Linux-Distributionen abhängig. Darüber hinaus ist acme.sh ein sehr fortschrittlicher Client, der bisher alle Features von Let’s Encrypt unterstützt. Grund genug, die diesen Let’s Encrypt Client einmal genauer anzusehen.

Der Artikel basiert dabei auf Ubuntu Server 18.04 LTS, alle gezeigten Schritte sollten sich aber auch auf anderen Distributionen umsetzen lassen. Als Webserver kommt nginx zum Einsatz.

Update-Historie (letztes Update 18.02.2019)
  • 18.02.2019:
    • Hinweis für Meldung „-bash: /home/user/.acme.sh/acme.sh.env: Permission denied“ hinzugefügt.
  • 13.02.2019:
    • Hinweis für die Berechtigungen des Verzeichnisses /var/www/letsencrypt hinzugefügt.
  • 11.02.2019:
    • Anleitung zum Upgrade von acme.sh hinzugefügt.
    • Hinweis auf Überschreiben der Crontab durch Installation von acme.sh hinzugefügt/Sichern der bestehenden Crontab.
  • 09.02.2019:
    • Hinweis auf neuen Artikel zum Umstieg von Certbot auf acme.sh hinzugefügt.

 

Installation von acme.sh

Es handelt sich bei acme.sh nur um ein Skript, jedoch kann es in gewisser Art installiert werden. Die Installation beinhaltet hauptsächlich die Einrichtung eines Cronjobs zur automatischen Erneuerung ausgestellter Zertifikate.

Alle folgenden Befehle werden mit Root-Rechten ausgeführt:

Wichtig: Falls bereits Cronjobs (für den Root-User) eingerichtet sind, dann solltet ihr euch vorher die aktuelle Crontab sichern, da acme.sh diese bei der Installation ungefragt überschreibt:

Nach der Installation von acme.sh können mittels dieser Datei die „alten“ Cronjobs wieder mit contab -e hinzugefügt werden.

Diese Installation besteht eigentlich nur in der Ausführung des Skripts mit bestimmten Parametern und gestaltet sich recht einfach. Dazu gibt es eine spezielle Seite, die das Skript zur Installation beinhaltet: https://get.acme.sh.

Hinweis: Es ist immer gefährlich, eine unbekannte Quelle direkt in die Shell zu pipen, da man nie so genau weiß, was diese Quelle (in diesem Fall das Skript genau ausführt). Man sollte sich die Quelle (in diesem Fall https://get.acme.sh) vor der Ausführung des Befehle genau ansehen und überprüfen, ob hier nichts verdächtiges passiert. Für wen das Pipen auf die Shell nicht in Frage kommt, der findet noch ein paar alternative Installationsmöglichkeiten auf der Wiki-Seite des GitHub-Projekts.

Die "Installation" von acme.sh

Die „Installation“ von acme.sh

Nach der Installation muss das Terminal einmal geschlossen und wieder geöffnet werden. Alternativ kann man den Rechner auch einfach neu starten.

Hinweis: Es kann sein, dass nach dem Login auf der Konsole mit einem (non-Root) User eine Fehlermeldung erscheint:

-bash: /home/user/.acme.sh/acme.sh.env: Permission denied

Während der Installation wurde hier ein Alias für acme.sh konfiguriert, so dass das Skript einfach nur mit „acme.sh“ aufgerufen werden kann (ohne Angabe des vollständigen Pfades). Da die Installation im Kontext des Root-Users vorgenommen wurde, kann acme.sh für einen normalen User so nicht aufgerufen werden. Aus diesem Grund erscheint auch die Meldung beim Login. Allerdings schränkt dies dies nicht die Funktionsfähigkeit von acme.sh ein. Daher kann diese Meldung einfach ignoriert werden.

Damit ist die Installation bereits abgeschlossen. Als nächstes wird das System auf die Verwendung von SSL-Zertifikaten vorbereitet.

Vorbereitung des Systems

Zunächst richten wir dazu das Verzeichnis ein, in dem später die Zertifikate gespeichert werden:

Ich nutze hier immer einen Unterordner, der mit der Domain übereinstimmt, für welche die Zertifikate ausgestellt werden sollen (in diesem Beispiel einfach meinedomain.de).

Als nächstes muss der Webserver in der Lage sein, über HTTP (Port 80) im Unterverzeichnis /.wellknown/acmechallenge für Let’s Encrypt erreichbar zu sein. Im virtuellen Host für die entsprechende Domain könnte dies dann folgendermaßen aussehen:

Falls noch nicht geschehen, wird noch das Verzeichnis für Let’s Encrypt angelegt und der Webserver-User wird als Owner festgelegt:

Zertifikate mit acme.sh erzeugen

Nach den Vorbereitungen sind wir nun soweit, dass wir Zertifikate über acme.sh ausstellen lassen können.

Ich gehe im folgenden davon aus, dass auf dem System bereits nginx als Webserver installiert und eingerichtet wurde. Für die Generierung der Zertifikate wird daher der sog. Webroot-Modus genutzt. acme.sh unterstützt allerdings auch andere Modi (z.B. einen Standalone-Modus, wenn kein Webserver auf dem System läuft). Es gibt auch einen speziellen Modus für nginx, allerdings werden hier die virtuellen Hosts vom Webserver bei der Generierung/Erneuerung der Zertifikate kurzzeitig verändert/ausgetauscht. Da ich meine vHosts lieber unangetastet lassen möchte, nutze ich daher immer nur den Webroot-Modus.

Ein Zertifikat wird durch einen einzigen Befehl erzeugt:

Mit den Parametern werden die Details zu Generierung der Zertifikate angegeben:

  • Mit  -d meinedomain.de  wird die Domain angegeben, für die das Zertifikat erzeugt werden soll.
  • --keylength 4096  gibt die Schlüssellänge des RSA-Zertifikats an. Standardmäßig werden hier 2048 Bit verwendet. Das ist in der Regel ausreichend, jedoch sollte man für erhöhte Sicherheit auf eine Schlüssellänge von 4096 Bit setzen.
  • Mit -w /var/www/letsencrypt  wird das Verzeichnis angegeben, in dem die Challenge-Dateien gespeichert werden. Dies muss das Verzeichnis sein, welches bei nginx als root Verzeichnis für /.well-known/acme-challenge angegeben wurde (im jeweiligen virtuellen Host).
  • acme.sh speichert die Zertifikat-Dateien im Verzeichnis ~/.acme.sh/meinedomain.de. Es wird davon abgeraten, diese Dateien direkt in den virtuellen Hosts des Webservers zu referenzieren. Aus diesem Grund wird mit den Parametern --key-file , --ca-file , --cert-file  und --fullchain-file  die Speicherorte der Dateien angegeben, wo die entsprechenden Dateien „installiert“ werden sollen. Nur diese Dateien werden dann später in den vHosts von nginx eingebunden.
  • --reloadcmd  gibt den Befehl an, der nach erfolgreicher Ausstellung/Erneuerung der Zertifikate ausgeführt werden soll. Damit der Webserver die neuen Zertifikate korrekt einbinden kann, wird nginx hier einfach kurz neu gestartet. Wenn hier mehrere Befehle ausgeführt werden sollen, sind diese durch ein Semikolon zu trennen.

Nach dem Generieren können alle von acme.sh ausgestellten Zertifikate auf dem System durch folgenden Befehl angezeigt werden:

Ebenfalls wird durch diesen Befehl die Gültigkeitsdauer der Zertifikate angezeigt (dazu später mehr).

Diffie-Hellman-Parameter erzeugen

Die Zertifikate selbst sind der wichtigste Punkt, wenn es um die Verschlüsselung der Verbindung über HTTPS geht. Um die Sicherheit noch weiter zu erhöhen, sollten noch sog. Diffie-Hellman-Parameter genutzt werden. Ohne nun die technischen Details zu beleuchten, geht es um einen sicheren Schlüsselaustausch bei Verbindungsaufbau. Die Generierung des Schlüssels muss dabei nur einmal erfolgen.

Achtung: Die Erzeugung der Diffie-Hellman-Parameter dauert gerade auf schwächerer Hardware sehr lange. Hier muss man bis zur Fertigstellung u.U. mehrere Stunden warten. In diesem Fall kann auch eine Schlüssel mit „nur“ 2048 Bit berechnet werden (die Zahl des zweiten Befehls gibt hierbei die Länge des Schlüssels in Bit an). Auf stärkerer Hardware ist allerdings eine Schlüssellänge von 4096 Bit empfehlenswert.

Einbinden der Zertifikate in nginx

Die Zertifikate können nun einfach mit nginx verwendet werden. Ich beschränke mich hier auf das reine Einbinden der Zertifikate und der entsprechenden SSL-Einstellungen.

Damit das Ganze übersichtlich bleibt, lagere ich die SSL-Settings immer in eine spezielle Datei aus, die dann später in die virtuellen Hosts eingebunden wird. Auf diese Weise sind alle Einstellungen bzgl. SSL nur an einem Ort zu finden.

Dazu legen wir zunächst eine neue Datei an:

Hier werden dann ausschließlich die Anweisungen für SSL aufgeführt:

Neben dem Einbinden der eigentlichen Zertifikate dienen alle weiteren Anweisung ebenso der Sicherheit/Verschlüsselung. Daher bitte auch die Kommentare in der Datei beachten.

Im jeweiligen virtuellen Host für HTTPS ist dann einfach diese ssl.conf einzubinden:

Wichtig: Die SSL-Anweisungen dürfen nicht doppelt im server-Block für HTTPS aufgeführt werden. Wenn hier bereits Optionen angegeben sind, die ebenfalls in der Datei ssl.conf aufgeführt sind, dann sind diese im server-Block für HTTPS zu entfernen.

Nach einem Neustart des Webservers sollten die Zertifikate korrekt eingebunden worden sein:

Überprüfung der Zertifikate

Abschließend lohnt eine Überprüfung der Zertifikate. Hierzu ist der SSL Server Test von Qualys SSL Labs gut geeignet. Mit der gezeigten Konfiguration sollte ein Rating mit A+ und 100% in allen Kategorien erreicht werden:

Ergebnis des SSL-Tests

Ergebnis des SSL-Tests

Falls hier eine niedrigere Bewertung angezeigt werden sollte, liegt dies vermutlich an der SSL-Konfiguration des Webservers. In diesem Fall sollten die entsprechenden Anweisungen der Datei ssl.conf nochmals kontrolliert werden.

Erneuerung der Zertifikate

Die Zertifikate von Let’s Encrypt sind nur für die Dauer von 90 Tagen gültig (Begründung siehe hier) und müssen anschließend erneuert werden.

Bei der Installation von acme.sh wurde ein Cronjob angelegt, der regelmäßig prüft, ob Zertifikate erneuert werden müssen und diese Erneuerung dann ggf. automatisch ausführt. Im Grunde genommen muss man sich daher gar nicht weiter um die Zertifikate kümmern.

Dennoch sollte man nach dem initialen Ausstellen der Zertifikate und Ablauf der 90 Tage kontrollieren, ob die automatische Erneuerung auch wirklich durchgeführt wurde.

Die Gültigkeitsdauer der installierten Zertifikate kann wieder mit folgendem Befehl ermittelt werden:

Upgrade von acme.sh

Für acme.sh werden regelmäßig auch Updates veröffentlicht (siehe GitHub Release-Page). In diesem Fall kann das Skript mit nur einem Befehl auf den neusten Stand gebracht werden:

Das Reizvolle daran ist nun, dass man diese Updates komplett ohne Abhängigkeiten von den Paketquellen der jeweiligen Distributionen einspielen kann.

Fazit

acme.sh macht als Let’s Encrypt Client einen sehr soliden Eindruck. Die Bedienung gestaltet sich recht einfach und da es sich um ein reines Shell Skript handelt, ist man unabhängig von Programmversionen in den Paketquellen einzelner Linux-Distributionen. Ebenfalls wird automatisch ein Cronjob für die Erneuerung der Zertifikate angelegt, so dass man sich nach der ersten Generierung der Zertifikate nicht mehr um deren Erneuerung kümmern muss. Aus genau diesen Gründen werde ich in Zukunft auch acme.sh als Let’s Encrypt Client empfehlen.

Abschließend noch ein Hinweis für Webserver-Admins, die noch einen anderen Let’s Encrypt Client verwenden und auf acme.sh umsteigen wollen: Der nächste Artikel hier im Blog wird den Umstieg zu acme.sh im Detail beleuchten…

Update: Der Artikel zum Umstieg von Certbot auf acme.sh ist online: Let’s Encrypt: Umstieg von Certbot auf acme.sh (nginx)

Weiterführende Artikel

Links

, , , , , , , , , , ,

Kommentare: 14

  • Hans sagt:

    Hallo Jan,

    kannst du die Quelle unbedenklich empfehlen?

    Gruß Hans

    • Jan sagt:

      Hi Hans,

      ich denke es geht um die Installation von acme.sh durch das Pipen einer URL in die Bash: Aus meiner Sicht ja. Ich habe den Hinweis hauptsächlich hinzugefügt, weil das für viele Leute ein absolutes No-Go ist.
      Falls du Bedenken hast, einfach mal einen Blick auf die alternativen Installations-Methoden werfen.

      Gruß,
      Jan

  • Marcus sagt:

    Vielen Dank für die Anleitung!
    Wie entfernt man denn den Certbot sauber?
    Sonst laufen die Zertifikate ja parallel oder?

    • Jan sagt:

      Hi Marcus,

      für Umsteiger von Certbot (so wie ich das in meinen Tutorials immer empfohlen habe) auf acme.sh wird die Tage noch ein Folge-Artikel online gehen. Da sollten dann alle Details erklärt werden.

      Gruß,
      Jan

  • Stefan sagt:

    Hallo Jan,

    hat wunderbar geklappt, konnte meine Test NC erfogreich unstellen.

    Gruß Hans

  • Thomas sagt:

    Hallo Jan,
    für meine Nextcloud-Installation habe ich von aussen nur 443 geöffnet, bzw. oder redirect auf meinem ddl-router konfiguriert.
    Für dieses Verfahren benötigt man ja Port 80.
    Gibt es eine Möglichkeit die Öffnung von Port 80 ins Internet zu verhindern und alternativ einen anderen Port zu verwenden?
    Viele Grüße
    Thomas

    • Jan sagt:

      Hi Thomas,

      ich glaube, dass Let’s Encrypt nur über Port 80 geht. Aber das sollte kein Problem sein: Wenn du die Weiterleitung auf Port 80 aktivierst, kannst du ja über den virtuellen Host regeln, dass ausschließlich Anfragen von Let’s Encrypt entgegen genommen werden. Alles andere kann entweder blockiert werden (deny all) oder auf den entsprechenden HTTPS-Server-Block weiter geleitet werden.

      Gruß,
      Jan

  • Thoams sagt:

    Hallo Jan,

    kannst Du mir noch einen konkreten Hinweis geben, wie ich diesen Ausschuss über den Virtuellen Host bewerkstelligen kann?

    Als Basis: Ich habe mich bisher immer an Deine Konfiguration gehalten.

    Vielen Dank und Grüße

    Thomas

    • Jan sagt:

      Hi Thomas,

      ich würde es mal mit diesem server-Block für HTTP probieren:
      server {
      listen 80 default_server;
      listen [::]:80 default_server;
      server_name meinedomain.de 192.168.178.60;

      root /var/www;

      location ^~ /.well-known/acme-challenge {
      proxy_pass http://127.0.0.1:81;
      proxy_redirect off;
      }

      deny all;
      }

      Damit sollten eigentlich nur noch Anfragen von Let’s Encrypt durchkommen.

      Gruß,
      Jan

      • Thomas sagt:

        Hallo Jan,

        habe heute morgen auch erfolgreich auf Acme.sh umgestellt. Vielen Dank für die Erklärung auch im anderen Post. Eine Bemerkung noch: bei mir hat das purge dazu geführt, dass auch die alten Zertifikate weg waren :-/

        Viele Grüße

        Thomas

        • Jan sagt:

          Hi Thomas,

          vielen Dank für den Hinweis! Da war eh irgendwie der Wurm drin, da Certbot seine Zertifikate in einem anderen Verzeichnis speichert (/etc/letsencrypt/live/meinedomain.de). D.h. das umständliche Umkopieren der Zertifikate war gar nicht notwendig. Ich habe das Tutorial gleich mal angepasst. Nun sollte der Umstieg generell noch einfacher von der Hand gehen.
          Sorry für die Unannehmlichkeiten!

          Gruß,
          Jan

  • Ole sagt:

    Hallo und erst einmal vielen Dank für dein Howto. eine Frage:

    „Bei der Installation von acme.sh wurde ein Cronjob angelegt, der regelmäßig prüft …“

    Seit der Installation des Scriptes bekomme ich folgende Fehlermeldung:
    >>> -bash: /home/user/.acme.sh/acme.sh.env: Keine Berechtigung

    Viele Grüße
    Ole

    • Jan sagt:

      Hi Ole,

      diese Meldung kannst du ignorieren. Sie wird dadurch verursacht, dass das Skript als Root-User installiert/ausgeführt wird. Der normale User, mit dem du erst einmal in der SSH-Session „ankommst“, hat ja zunächst einmal keine Root-Rechte (erst nach dem „sudo -s“).
      Das Skript läuft aber trotzdem einwandfrei, auch wenn die Meldung nach dem Login etwas irreführend ist.

      Ich habe hier noch einen Hinweis im Artikel ergänzt.

      Gruß,
      Jan

Schreibe einen Kommentar

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