DecaTec

Programmieren, Fotografie, Home-Server und einiges mehr

Let’s Encrypt Zertifikate per Cron automatisch erneuern

Let's Encrypt Logo

In meinen Tutorials zu Nextcloud/ownCloud verweise ich ja gerne auf SSL-Zertifikate von Let’s Encrypt. Mit dieser Zertifizierungsstelle können auf einfache Weise TLS-/SSL-Zertifikate erzeugt werden. Auch wenn im privaten Umfeld ein sog. selbst signiertes Zertifikat ausreichen würde, bieten Zertifikate von Let’s Encrypt einen entscheidenden Vorteil: Es handelt sich hierbei um „trusted“ Zertifikate, d.h. dass alle gängigen Browser/Clients stufen diese als vertrauenswürdig ein.

Auch wenn die Erzeugung eines Zertifikats über Let’s Encrypt einfach und schnell von der Hand geht, wird als Kritikpunkt häufig die begrenzte Gültigkeitsdauer aufgeführt: Diese Zertifikate sind aus Sicherheitsgründen nur für einen Zeitraum von 90 Tagen gültig und müssen danach neu generiert werden.

Der folgende Artikel zeigt eine einfache Möglichkeit, wie die Erneuerung von Let’s Encrypt Zertifikaten ganz einfach automatisiert per Cron durchgeführt werden kann.

Update-Historie
  • 08.01.2018:
    • Der Output des Befehls zum Neustarten des Webservers im Cronjob wird nach > /dev/null 2>&1 weitergeleitet, so dass keine E-Mails mehr verschickt werden, wenn ein MTA auf dem System eingerichtet ist.

Warum kein selbst signiertes Zertifikat verwenden?

Selbst signierte Zertifikate haben zwei entscheidende Vorteile:

  • Kostenlos, da die Zertifikat-Dateien selbst erzeugt werden können, z.B. mittels OpenSSL (Zertifizierungsstellen lassen sich ihre Dienste immer fürstlich bezahlen).
  • Den Gültigkeitszeitraum kann man dabei selbst bestimmen (z.B. 10 Jahre). Einmal generiert, muss man sich in der Regel nicht mehr um das Zertifikat kümmern.

Allerdings gibt es hier immer auch einen massiven Nachteil: Selbst signierte Zertifikate werden von Client-Anwendungen nicht als vertrauenswürdig eingestuft, weil ja kein Dritter (die Zertifizierungsstelle) die Echtheit der Website bestätigen kann. Folglich zeigen Browser hier beispielsweise immer eine sehr deutliche Warnung an:

Zertifikat-Warnung im Internet Explorer

Zertifikat-Warnung im Internet Explorer

Andere Clients (z.B. Windows Smartphones bei der Synchronisierung von CardDAV/CalDAV) versagen bei selbst signierten Zertifikaten ihren Dienst.

Diesen Nachteil kann man relativ einfach umgehen: Man installiert das selbst signierte Zertifikat einfach auf sämtlichen Clients. Wie dies z.B. unter Windows bewerkstelligt werden kann, zeigt der Artikel ownCloud auf Ubuntu Server mit nginx, MariaDB und PHP (Abschnitt Zertifikat installieren (nur bei selbst signierten Zertifikaten)).
Dies ist in den meisten Fällen allerdings einfacher gesagt als getan: Solange z.B. für eine selbst gehostete Cloud-Anwendung die Anzahl der Clients überschaubar ist, hält sich der Aufwand hierfür in Grenzen. Aber spätestens wenn viele Clients zum Einsatz kommen, auf die man als Administrator keinen direkten Zugriff hat, wird die Sache kompliziert.

Trotz alledem ist die Verwendung eines selbst signierten Zertifikats nicht unsicher. Solange das Zertifikat richtig erzeugt und eingebunden wurde, ist die Verbindung verschlüsselt (und genau darum geht es ja primär im privaten Umfeld).

Zertifikate mit Let’s Encrypt

Mit einem Zertifikat von Let’s Encrypt hat man die oben genannten Probleme nicht. Wie diese Zertifikate erzeugt werden und beim Webserver nginx eingebunden werden, habe ich bereits im Artikel ownCloud 9 auf Ubuntu Server 16.04 LTS mit nginx, MariaDB, PHP 7 und Let’s Encrypt ausführlich erklärt. Hier nochmal im Schnelldurchgang, ohne auf die genaue Konfiguration des Webservers einzugehen (diese wurde detailliert im oben genannten Artikel erläutert):

Der Webserver muss auf Port 80 erreichbar sein und über eine Domain angesprochen werden können. Hier reicht auch eine DynDNS-Adresse. Ich verwende hier beispielhaft die Adresse meineseite.goip.de (wer auf der Suche nach einem guten, kostlosen DynDNS-Anbieter ist, sollte mal bei GoIP vorbei schauen). Eine IP ist für den Zertifizierungsvorgang übrigens nicht ausreichend.

Zunächst installiert man Let’s Encrypt. Unter Ubuntu Server 16.04 LTS verwendet man dazu folgende Befehle:

Anschließend kann das Zertifikat erzeugt werden:

Die Zertifikat-Dateien sind dann im Verzeichnis /etc/letsencrypt/live/meineseite.goip.de zu finden.

Das generierte Zertifikat hat eine Gültigkeitsdauer von 90 Tagen. Spätestens vor dem Ablauf dieser Frist muss das Zertifikat erneuert werden. Dazu ist folgender Befehl ausreichend, damit sämtliche bekannten Zertifikate erneuert werden:

Dies ist zwar nur ein Befehl auf der Kommandozeile und geht recht schnell, aber man sollte dies auf keinen Fall vergessen: Wenn das Zertifikat ungültig wird, werden wieder die Warnungen im Browser angezeigt und man hat wieder die gleichen Probleme wie mit einem selbst signierten Zertifikat.

Automatisierung mit Cron

Diese wichtige Aufgabe kann allerdings auch mittels Cron automatisiert werden. Dazu nutzen wir crontab:

Durch das sudo -s ist sicher gestellt, dass der folgende Befehl mit Root-Rechten ausgeführt wird.

Die zu öffnende Datei wird anschließend mit nano (oder jedem anderen beliebigen Texteditor) bearbeitet und folgender Inhalt eingetragen:

Dieser Befehl sorgt für die Erneuerung der Let’s Encrypt Zertifikate um 03:40 jeden Sonntag. Im Zweiten Schritt wird dann nginx anschließend neu geladen (damit das neue Zertifikat auch korrekt eingebunden wird). Der Zeitpunkt des Cronjobs ist hier willkürlich gewählt. Praktischerweise sollte man einen Zeitpunkt wählen, zu dem der Webserver nicht gerade unter last steht.

Der Output der Zertifikat-Erneuerung wird in der Datei /var/log/letsencrypt-renew.log ausgegeben. Hier kann dann kontrolliert werden, ob der Befehl richtig ausgeführt wurde und ob tatsächlich Zertifikate erneuert wurden (dies ist in der Regel abhängig vom Alter der bestehenden Zertifikate – normalerweise werden Zertifikate erst erneuert, wenn die Gültigkeitsdauer weniger als 30 Tage beträgt).

Die neuen Zertifikate sind anschließend im Verzeichnis /etc/letsencrypt/live zu finden. Von dieser Stelle werden sie auch von nginx eingebunden, daher reicht auch ein reload des Webservers nach dem Aufruf von letsencrypt. Damit für das Neustarten des Webservers keine E-Mail versendet wird – dies passiert automatisch, wenn ein passender MTA (Mail Transfer Agent) konfiguriert ist – wird der Output dieses Befehl mitttels > /dev/null 2>&1 ins „Nirvana“ weitergeleitet.
Die alten Zertifikate werden in den Ordner /etc/letsencrypt/archive verschoben. Werden die archivierten Zertifikate nicht mehr benötigt, kann man diese problemlos löschen.

Trusted Zertifikat mit praktisch unbegrenzter Gültigkeitsdauer

Der Artikel hat gezeigt, wie man mit wenig Aufwand die Erneuerung von Let’s Encrypt Zertifikaten automatisieren kann. Damit hat man immer ein As im Ärmel: ein Zertifikat, welches von allen Clients als vertrauenswürdig eingestuft wird und praktisch eine unbegrenzte Gültigkeitsdauer hat.

Daher nach wie vor mein Tipp: Bevor ihr einfach auf selbst signierte Zertifikate setzt, gebt Let’s Encrypt eine Chance. Ihr werdet damit als Administrator weniger Verwaltungsaufwand haben und die Clients, die auf eure Web-Anwendung zugreifen, werden es euch danken.

Weiterführende Artikel

Links

, , , , , , ,

Kommentare: 17

  • Stefan sagt:

    Hallo, wie immer ne klasse Anleitung. Für mich als nicht Profi sind alle Anleitungen auf dieser Seite sehr verständlich.

    Vielen Dank dafür!

  • Bernd sagt:

    da schließe ich mich gerne an!
    einfach super!

    Gruß Bernd

  • Michael Beck sagt:

    Ich hab mal eine Frage zu den angeschlossenen Nextcloud Clients. Wenn ich mich per Nextcloud Windows Client auf den Nextcloud Server verbinde, nehme ich ja auch die https URL des Servers. Dabei muss ich ebenfalls ein Zertifikat annehmen. Muss ich dies dann auch jedesmal annehmen, wenn das Let`s Encrypt Zertifikat erneuert wird?
    Danke im Voraus.

    • Jan sagt:

      Hallo Michael,

      wenn das Let’s Encrypt-Zertifikat erfolgreich erstellt und eingebunden wurde, sollte eigentlich keine Warnung mehr in den Nextcloud Clients kommen. Diese Warnung zeigt ja eben genau an, dass etwas mit dem Zertifikat nicht stimmt (nicht trusted, falscher Hostname, der nicht zum Zertifikat passt, etc.).
      Was besagt die Warnung bei dir genau? Kannst mir auch gern eine Mail mit Screenshot schicken.

      Gruß,
      Jan

  • Stanley sagt:

    Danke für die Anleitung. Soweit so gut, aber wie mache ich das, wenn ich ein Zertifikat für Webmail benötige? Das muss ja in die config von roundcube eingetragen werden, habe bisher keinen Weg gefunden, wie man das per Cron lösen kann.

    Vielleicht weiß ja jemand mehr? Das Zertifikat von Plesk ist hier keine Lösung.

  • Hans sagt:

    Hallo Jan,

    weißt du zufällig wie lange die alten Zertifikate im Archiv aufbewahrt werden?

    Bei jeder Erneuerung wird im Archiv Verzeichnis immer wieder ein neuer Ordner angelegt.

    /etc/letsencrypt/archive

    Zudem erhalten ich einmal im Monat folgende Info.

    Cron lletsencrypt renew >> /var/log/letsencrypt-renew.log && /etc/init.d/nginx reload

    Mit dem Inhalt Reload ngnix configuration (via systemctl): ngnix.service

    Zusätzlich muss ich dann letsencrypt renew ausführen und erhalte erst dann neue Zertifikate.

    Vielen Dank

    Gruß Hans

    • Jan sagt:

      Hi Hans,

      wie lange die Zertifikate im Archiv aufbewahrt werden weiß ich leider nicht. Im Zweifelsfall werden die Zertifikat-Dateien jedes mal dort hin kopiert und bleiben einfach dort. Was stört dich daran? Das sind ja keine großen Datenmengen. Wenn du diese unbedingt löschen möchtest, könntest du natürlich den Cronjob entsprechend anpassen oder einen neuen anlegen, der dir dann automatisiert die alten Zertifikate löscht.

      Ich verstehe nur nicht, was du mit der zweiten Frage meinst: Wo bekommst du diese Meldung (in einer Log-Datei)? Was mir hier spontan nur auffällt, ist das doppelte ‚l‘, wenn es sich nicht um einen Tippfehler handelt. Einfach mal per contab -e checken, ob die Befehle hier richtig eingegeben wurden. Mein Cronjob läuft schon seit Ewigkeiten problemlos und ich muss mich um das Erneuern der Zertifikate gar nicht mehr kümmern.

      Gruß,
      Jan

      • Hans sagt:

        Hallo Jan, habe ich von Postfix bekommen.

        Die Zertifikate werden per Cron nicht automatisch erneuert und ich erhalte vom Postfix die genannte Meldung.

        Gruß Hans

        • Jan sagt:

          Hi Hans,

          wenn das manuelle Erneuern der Zertifikate klappt, dann stimmt wohl etwas an dem Cron-Job nicht. Daher nochmal kontrollieren.
          Was steht im Logfile (/var/log/letsencrypt-renew.log)?

          Gruß,
          Jan

          • Hans sagt:

            Hallo Jan,

            das Log schaut soweit ganz gut aus. Die Zertifikate müssen am 18.12 erneuert werden, dass warte ich jetzt mal ab und würde mich ggf. dann nochmal melden.

            Gruß Hans

  • Hans sagt:

    Hallo Jan,

    im Log (/etc/letsencrypt/renewal/letsencrypt.log) befindet sich folgender Fehler.

    Beim Seitenaufruf erhalte ich den Fehler das dass Zertifikat nicht mehr gültig ist.

    Traceback (most recent call last):
    File „/usr/bin/letsencrypt“, line 9, in
    load_entry_point(‚letsencrypt==0.4.1‘, ‚console_scripts‘, ‚letsencrypt‘)()
    File „/usr/lib/python2.7/dist-packages/letsencrypt/cli.py“, line 1946, in main
    args = prepare_and_parse_args(plugins, cli_args) File „/usr/lib/python2.7/dist-packages/letsencrypt/cli.py“, line 1638, in prepare_and_parse_args
    return helpful.parse_args()
    File „/usr/lib/python2.7/dist-packages/letsencrypt/cli.py“, line 1206, in parse_args
    parsed_args = self.parser.parse_args(self.args)
    File „/usr/lib/python2.7/dist-packages/configargparse.py“, line 216, in parse_args
    env_vars = env_vars)
    File „/usr/lib/python2.7/dist-packages/configargparse.py“, line 349, in parse_known_args
    self, args=args, namespace=namespace)
    File „/usr/lib/python2.7/argparse.py“, line 1733, in parse_known_args
    namespace, args = self._parse_known_args(args, namespace)
    File „/usr/lib/python2.7/argparse.py“, line 1939, in _parse_known_args
    start_index = consume_optional(start_index)
    File „/usr/lib/python2.7/argparse.py“, line 1879, letsencrypt.log

    Gruß Hans

    • Jan sagt:

      Hi Hans,

      also bei mir kann ich das Problem nicht nachvollziehen, hier läuft der Cron-Job ordentlich durch.
      Hast du an deinem System irgend etwas verändert/neu aufgesetzt? Der Fehler sieht nicht nach einem Fehler in der Webserver-Konfiguration aus, sondern nach einem Fehler in LE selbst.
      Daher würde ich erst einmal probieren, was passiert, wenn du die Befehle manuell ausführst, also einfach sudo letsencrypt renew. Wenn hier eine ordentliche Meldung kommt („The following certs are not due for renewal yet“ oder dass das entsprechende Zertifikat korrekt erneuert wurde), dann stimmt etwas mit der Definition des Cron-Jobs nicht. Wenn hier der gleiche Fehler kommt, dann stimmt irgend etwas bei der LE-Installation nicht. Dann würde ich mal die „Erst-Ausstellung“ des Zertifikats probieren (letsencrypt certonly –webroot -w /var/www/letsencrypt -d meineseite.goip.de –rsa-key-size 4096).
      Wenn alle Stricke reißen, dann würde ich Lets Encrypt mal neu installieren.

      Gruß,
      Jan

      • Hans sagt:

        Hallo,

        ich habe gehofft das ich um eine Neuinstallation herum komme.

        Leider nein!

        Danke jedoch für den Tipp!

        Gruß Hans

        • Jan sagt:

          Hi Hans,

          hat es mit der Neuinstallation von LE zumindest funktioniert?
          Kamen beim Ausführen der manuellen Kommandos die gleichen Fehlermeldungen?

          Gruß,
          Jan

          • Hans sagt:

            Hi Jan,
            die gleichen Fehler. Inzwischen erhalte ich diese Meldung.

            An unexpected error occurred:
            There were too many requests of a given type :: Error creating new cert :: too many certificates already issued for exact set of domains

            File „/usr/bin/letsencrypt“, line 9, in
            load_entry_point(‚letsencrypt==0.4.1‘, ‚console_scripts‘, ‚letsencrypt‘)()
            File „/usr/lib/python2.7/dist-packages/letsencrypt/cli.py“, line 1986, in main
            return config.func(config, plugins)
            File „/usr/lib/python2.7/dist-packages/letsencrypt/cli.py“, line 706, in obtain_cert
            _, action = _auth_from_domains(le_client, config, domains, lineage)
            File „/usr/lib/python2.7/dist-packages/letsencrypt/cli.py“, line 474, in _auth_from_domains
            lineage = le_client.obtain_and_enroll_certificate(domains)
            File „/usr/lib/python2.7/dist-packages/letsencrypt/client.py“, line 269, in obtain_and_enroll_certificate
            certr, chain, key, _ = self.obtain_certificate(domains)
            File „/usr/lib/python2.7/dist-packages/letsencrypt/client.py“, line 252, in obtain_certificate
            return self.obtain_certificate_from_csr(domains, csr) + (key, csr)
            File „/usr/lib/python2.7/dist-packages/letsencrypt/client.py“, line 229, in obtain_certificate_from_csr
            authzr)
            File „/usr/lib/python2.7/dist-packages/acme/client.py“, line 319, in request_issuance
            headers={‚Accept‘: content_type})
            File „/usr/lib/python2.7/dist-packages/acme/client.py“, line 652, in post
            return self._check_response(response, content_type=content_type)
            File „/usr/lib/python2.7/dist-packages/acme/client.py“, line 568, in _check_response
            raise messages.Error.from_json(jobj)
            Error: urn:acme:error:rateLimited :: There were too many requests of a given type :: Error creating new cert :: too many certificates already issued for exact set of domains

            Gruß Hans

          • Jan sagt:

            Hi Hans,

            LE unterstützt hat eine Begrenzung für ausgestellte Zertifikate pro Domain: 20/Woche pro registrierter Domain und 5/Woche für erneuerte Zertifikate für eine (Sub-)Domain (siehe hier).
            In dieses Problem kann man schnell kommen, wenn man bei einem großen Free-DynDNS-Anbieter ist, wo für viele Subdomains auch viele Zertifikate ausgestellt werden. Die einzige Lösung, die mir dazu spontan einfällt: Eine eigene Sub-Domain, die man als DynDNS-Domain verwendet. Das bieten bereits einige Webspace-Provider an. Hier kommt man dann nicht so schnell ans Limit, außer man versucht in zu kurzer Zeit zu viele Zertifikate für die gleiche Subdomain ausstellen will.

            Gruß,
            Jan

Schreibe einen Kommentar

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