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.06.2021)
  • 18.06.2021:
    • Konfiguration acme.sh, so dass immer Zertifikate über Let’s Encrypt bezogen werden.
  • 03.02.2020:
    • Cipher Suite DHE-RSA-AES256-GCM-SHA384 entfernt.
  • 17.08.2019:
    • acme.sh sollte nicht mit Root-Rechten ausgeführt werden, daher wird für die Ausführung von acme.sh ein spezieller User angelegt.
  • 24.07.2019:
    • Anpassungen für TLSv1.3 (ssl_ciphers und ssl_ecdh_curve).
  • 15.06.2019:
    • ECDHE-RSA-AES256-SHA384 aus den ssl_ciphers entfernt (wird beim Qualys SSL Labs Test als „weak“ eingestuft).
  • 18.05.2019:
    • Hinweis hinzugefügt, dass bei der Generierung der Zertifikate am besten Copy&Paste und „Suchen & Ersetzen“ genutzt wird.
  • 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.

acme.sh sollte nicht mit Root-Rechten ausgeführt werden, daher legen wir einen speziellen User an und fügen diesen der Gruppe www-data hinzu:

adduser letsencrypt 
usermod -a -G www-data letsencrypt

Der User braucht nun die Berechtigungen, um nginx später ohne Passwort neu laden zu können:

visudo

Am Ende wird folgende Zeile hinzugefügt:

letsencrypt ALL=NOPASSWD: /bin/systemctl reload nginx.service

Für die Installation von acme.sh wechseln wird nun den User:

su - letsencrypt

Hinweis: Wenn ein bereits bestehender User für die Generierung der Zertifikate genommen wird, sollte nun kontrolliert werden, ob bereits Conjobs für diesen User angelegt wurden, da acme.sh bei der Installation sämtliche bereits bestehenden Conjobs überschreibt.

Falls bereits Cronjobs eingerichtet sind, dann solltet ihr euch daher vorher die aktuelle Crontab sichern:

crontab -l > crontab.bak

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.

curl https://get.acme.sh | 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 von acme.sh einmal mit dem entsprechenden User ab- und wieder anmelden:

exit
su - letsencrypt

Nun wird acme.sh noch gleich so konfiguriert, dass standardmäßig Zertifikate von Let’s Encrypt bezogen werden (ab dem 01.08.2021 nutzt acme.sh als Standard Zertifikate von ZeroSSL – siehe hier).
Dazu wird vor der Ausstellung des ersten Zertifikats folgender Befehl benötigt:

acme.sh --set-default-ca --server letsencrypt

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

Damit ist die Installation bereits abgeschlossen, so dass wir wieder auf den normalen User wechseln können:

exit

Als nächstes wird das System auf die Verwendung von SSL-Zertifikaten vorbereitet.

Vorbereitung des Systems

Zunächst richten wir die benötigten Verzeichnis ein, die später für die Zertifiakt-Generierung benötigt werden. Ebenfalls passen wir gleich die Berechtigungen entsprechend an:

mkdir -p /var/www/letsencrypt/.well-known/acme-challenge
chown -R www-data:www-data /var/www/letsencrypt
chmod -R 775 /var/www/letsencrypt
mkdir -p /etc/letsencrypt/meinedomain.de
chown -R www-data:www-data /etc/letsencrypt
chmod -R 775 /etc/letsencrypt

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:

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 {
		default_type text/plain;
		root /var/www/letsencrypt;
	}		
}

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.

Zunächst wechseln wir auf den speziell angelegten User:

su - letsencrypt

Ein Zertifikat wird durch einen einzigen Befehl erzeugt.
Tipp: Am besten übernimmt man den Befehl mittels Copy&Paste in einen beliebigen Text-Editor, mit dem man dann die Domain mit „Suchen und Ersetzen“ einfach durch die tatsächlich verwendete Domain einfügt. Auf diese Weise kann man Tippfehler vermeiden.

acme.sh --issue -d meinedomain.de --server letsencrypt --keylength 4096 -w /var/www/letsencrypt --key-file /etc/letsencrypt/meinedomain.de/key.pem --ca-file /etc/letsencrypt/meinedomain.de/ca.pem --cert-file /etc/letsencrypt/meinedomain.de/cert.pem --fullchain-file /etc/letsencrypt/meinedomain.de/fullchain.pem --reloadcmd "sudo /bin/systemctl reload nginx.service"

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

  • -d meinedomain.de

    Gibt die Domain an, für die das Zertifikat erzeugt werden soll.

  • --server letsencrypt

    Gibt an, dass die Zertifikate über Let’s Encrypt bezogen werden sollen. Diese Option ist an dieser Stelle optional, wenn das Standard-Verhalten von acme.sh bereits vorher angepasst wurde (s.o.).

  • --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.

  • -w /var/www/letsencrypt

    Gibt das Verzeichnis an, 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:

acme.sh --list

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

Nun wechseln wir wieder auf den normalen User zurück:

exit

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.

mkdir -p /etc/nginx/dhparams 
openssl dhparam -out /etc/nginx/dhparams/dhparams.pem 4096

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:

mkdir -p /etc/nginx/snippets 
nano /etc/nginx/snippets/ssl.conf

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

# Certificates used
ssl_certificate /etc/letsencrypt/meinedomain.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/meinedomain.de/key.pem;

# This should be ca.pem (certificate with the additional intermediate certificate)
# See here: https://certbot.eff.org/docs/using.html
ssl_trusted_certificate /etc/letsencrypt/meinedomain.de/ca.pem;

# Diffie-Hellman parameter, recommended 4096 bits
ssl_dhparam /etc/nginx/dhparams/dhparams.pem;

# Not using TLSv1 will break:
#	Android <= 4.4.40
#	IE <= 10
#	IE mobile <=10
# Removing TLSv1.1 breaks nothing else!
# TLSv1.3 is not supported by most clients, but it should be enabled.
ssl_protocols TLSv1.2 TLSv1.3;

# Cipher suite from https://cipherli.st/
# Max. security, but lower compatibility 
ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384';

# Cipher suite from https://wiki.mozilla.org/Security/Server_Side_TLS
#ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';

# (Modern) cipher suite from https://mozilla.github.io/server-side-tls/ssl-config-generator/
#ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';

# Use multiple curves.
ssl_ecdh_curve secp521r1:secp384r1;

# Server should determine the ciphers, not the client
ssl_prefer_server_ciphers on;

# OCSP Stapling
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;

resolver 192.168.178.1;

# SSL session handling
ssl_session_timeout 24h;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;

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:

server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name meinedomain.de 192.168.178.60;
	
	include /etc/nginx/snippets/ssl.conf;	
	
	#
	# Here you would add the statements for some web applications, e.g. Nextcloud.
	#
}

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:

service nginx restart

Ü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:

su - letsencrypt 
acme.sh --list

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:

su - letsencrypt 
acme.sh --upgrade

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

100 Kommentare zu „Let’s Encrypt Zertifikate mit acme.sh und nginx“

  1. Hallo Jan,

    wie würde so etwas aussehen, wenn man 2-3 Webseiten mit unterschiedlichen Domain am laufen hat auf einem Server?

    Gruß Danny

    1. Hi Danny,

      das ist ganz einfach: Für die weiteren Domains einfach weitere Zertifikate ausstellen lassen, pro Webseite dann ein vHost und hier die Zertifikate entsprechend einbinden.
      Man kann auch mehrere Domains in ein Zertifikat „zusammen fassen“ (dann einfach beim Aufruf von acme.sh den Parameter „-d“ mehrfach angeben), das mache ich aber persönlich nicht, da ich gerne für jede Domain ein Zertifikat habe, welches ich dann auch separat verwalten kann.

      Gruß,
      Jan

  2. Hallo!

    Vielen Dank für die ausführtliche Anleitung. Ich bin diese Punkt für Punkt durchgegangen, um Zertifikate für meine Nextcloud zu erhalten. Leider klappte es nicht.

    Ein Problem, das ich lösen konnte war, dass man zur Benutzung der acme.sh zuerst eine Emailadresse hinterlegen muss, bevor man ihren Befehl ausführen kann.

    Was ich aber nicht verstehe, ist folgendes:

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

    […]“

    Mir ist nicht klar, was der virtuelle Host ist. Nach einiger Recherche, habe ich folgendes ausgeführt:

    mkdir /etc/nginx/sites-available/
    nano /etc/nginx/sites-available/meine.domain.conf

    und ihren server {…}-Block dort eingefügt.

    Dann stolperte ich noch über folgendes:

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

    In welche Datei gehört nun dieser server {…}-Block?

    Gruß

    Frank

    Mit freundlichem

    1. Hi Frank,

      bei acme.sh musste ich noch nie eine Mail-Adresse hinterlegen, das scheint dann wenn neu zu sein.
      Virtuelle Hosts sind die Dateien, die bestimmen, was der Webserver ausliefert. Diese lege ich immer in das Verzeichnis /etc/nginx/conf.d, du kannst aber auch das Verzeichnis /etc/nginx/sites-enabled nutzen. Das wird bei dir vermutlich der Fehler sein, wenn in „sites-available“ werden die vHosts nicht geladen, sondern quasi nur geparkt.

      Gruß,
      Jan

  3. Hallo,

    zunächst: vielen Dank für Ihre Anleitungen, sie helfen mir sehr.
    Seit ein paar Tagen erreiche ich meine Nextcloud nicht mehr per Browser (keine sichere Verbindung). Ich habe also diese Anleitung angewandt, habe jedoch keinen Erfolg.

    Beim Abrufen der Zertifikate erscheint folgende Meldung:
    [Mon Oct 17 21:04:03 UTC 2022] Using CA: https://acme-v02.api.letsencrypt.org/directory
    [Mon Oct 17 21:04:03 UTC 2022] Single domain=’struck.dedyn.io‘
    [Mon Oct 17 21:04:03 UTC 2022] Getting domain auth token for each domain
    [Mon Oct 17 21:04:06 UTC 2022] Getting webroot for domain=’struck.dedyn.io‘
    [Mon Oct 17 21:04:06 UTC 2022] Verifying: struck.dedyn.io
    [Mon Oct 17 21:04:07 UTC 2022] Pending, The CA is processing your order, please just wait. (1/30)
    [Mon Oct 17 21:04:10 UTC 2022] struck.dedyn.io:Verify error:217.229.219.81: Fetching http://struck.dedyn.io/.well-known/acme-challenge/9SsyXqUNBibFYZz4y7hYz7_8OS97NtyDtD_2ssg6zC8: Connection refused
    [Mon Oct 17 21:04:11 UTC 2022] Please check log file for more details: /home/acmeuser/.acme.sh/acme.sh.log

    Zugriffsrechte und Ordnerzugehörigkeiten sind kontrolliert und funktionieren (Testdatei kann erstellt, jedoch nicht aufgerufen werden).

    Ein weiteres Problem taucht nun auf, wenn ich versuche NGINX neu zu starten. Hier erscheint die Meldung:
    Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
    Active: failed (Result: exit-code) since Mon 2022-10-17 21:09:25 UTC; 4s ago
    Docs: https://nginx.org/en/docs/
    Process: 9530 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=1/FAILURE)

    Oct 17 21:09:24 struckloud systemd[1]: Starting nginx – high performance web server…
    Oct 17 21:09:24 struckloud nginx[9530]: nginx: [emerg] a duplicate default server for 0.0.0.0:80 in /etc/nginx/conf.d/http.conf:2
    Oct 17 21:09:25 struckloud systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
    Oct 17 21:09:25 struckloud systemd[1]: nginx.service: Failed with result ‚exit-code‘.
    Oct 17 21:09:25 struckloud systemd[1]: Failed to start nginx – high performance web server.

    Die Config-Datei sieht wie folgt aus:
    server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name struck.dedyn.io 192.168.178.60;

    root /var/www;

    location ^~ /.well-known/acme-challenge {
    default_type text/plain;
    root /var/www/letsencrypt;
    }
    }

    Ich hoffe, sie können mir helfen.

    Vielen Dank und viele Grüße

    1. Hi Sebastian,

      wenn ein Kommentar nicht gleich erscheint, ist dieser vermutlich im Spam-Filter hängen geblieben. Das kann schnell mal passieren, wenn z.B. Code im Kommentar enthalten ist. In diesem Fall muss ich den Kommentar manuell freigeben, daher kann es eine Weile dauern.

      acme.sh kann nur funktionieren, wenn der Webserver läuft, was bei dir nicht der Fall ist. Hier sind zwei vHosts so definiert, dass diese auf Port 80 lauschen wollen. Hier kann immer nur ein vHost lauschen, daher musst du den anderen entfernen. Ich vermute bei dir mal stark, dass da noch der default-vHost aktiv ist (/etc/nginx/conf.d/default.conf). Diesen kannst du im Normalfall einfach löschen oder die Dateiendung ändern (z.B. auf ‚default.conf-disabled‘). Danach sollte nginx sich wieder starten lassen.

      Bitte nun auch nicht die Zertifikats-Generierung zig mal hintereinander ausführen, da kommst du schnell an ein Rate-Limit und dann ist die Domain erst einmal für 7 Tage gesperrt. Bitte vorher manuell ausprobieren, ob die „acme-chellenge“ richtig funktioniert. Beschrieben ist das Ganze in diesem Abschnitt.

      Gruß,
      Jan

      1. Hallo Jan,

        tausend Dank für deine Antwort und entschuldige den Doppelpost. Ich war mir nur unsicher, ob ich versehentlich was falsch gemacht habe.

        Habe nun alle conf-Dateien im conf.d-Ordner „abgeschaltet“. Ich schaffe es jedoch nicht, sowohl eine http.conf als auch eine https.conf wie von dir beschrieben nebeneinander laufen zulassen. Nginx meldet dann sofort wieder den Fehler. Wenn ich nur die http.conf aktiviere, dann funktioniert nginx. Was mache ich falsch?

        1. Hi Sebastian,

          ja, wenn nginx nicht läuft, kann der Webserver die Anfrage nicht beantworten, daher muss zunächst einmal nginx wieder starten.
          Kann es sein, dass nginx bei dir nicht /etc/nginx/conf.d verwendet, sondern /etc/nginx/sites-enabled? Ist in diesem Ordner noch was vorhanden?
          Was sagt bei dir „nginx -t“?

          Gruß,
          Jan

          1. Die Ausgabe lautet wie folgt:
            nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
            nginx: configuration file /etc/nginx/nginx.conf test is successful

            Der Ordner sites-enabled ist nicht vorhanden.

            Was kann ich noch tun?

          2. Hi Sebastian,

            ein „service nginx restart“ und anschließendes „service nginx status“ gibt aus, dass der Webserver läuft?
            Wenn dann der manuelle acme-challenge-Test nicht funktioniert, sollte in der /var/log/nginx/error.log ein Fehler aufgeführt werden, dass er die gesuchte Datei nicht finden kann. Das zeigt dann zumindest einmal, dass der Request auf beim Server ankommt. In diesem Fall stimmte dann die Konfiguration von nginx nicht.
            Sollte im Logfile nichts dergleichen aufgeführt werden, kommt der Request gar nicht an und der Fehler liegt „davor“, z.B. bei der Firewall oder IP/DynDNS-Konfiguration.

            Gruß,
            Jan

  4. Hallo Jan,
    entschuldige, ich kann auf deine Antwort nicht mehr antworten, deswegen ein neuer Kommentar.
    Ich frage mich immer noch, wie ich die beiden Einträge für Port 80 und 443 in eine Datei bekomme. Wenn ich zwei conf-Dateien habe, weigert sich nginx, mit oben beschriebener Fehlermeldung zu starten. Also habe ich aktuell nur die conf-Datei mit den Einträgen für Port 80.

    Bin nun bei der acme.sh weitergekommen und erhalte folgenden Fehler:
    … Can not write token to file …
    Mir scheint, es geht dabei um den gleichen Fehler, wie bei dem Fehler das der Test mit der Text-Datei fehlschlägt. An welcher Stelle kann ich da nochmal gucken? Wieso ist die Test-Datei nicht erreichbar? Bin Schritt für Schritt alles durchgegangen.
    Grüße, Sebastian

    1. Hi Sebastian,

      schau dir mal diesen Artikel an: Hier ist das Ganze noch mal Schritt für Schritt erklärt.
      Prinzipiell muss es bei dir mehrere vHosts geben, die auf dem gleichen Port laufen sollen. Das ist der Grund warum nginx dann nicht startet.
      Dieses „Cannot write token to file“ klingt eher wie ein Berechtigungsproblem. Stimmen die Berechtigungen des Users für Let’s Encrypt? Ist dieser Teil der Webserver-Gruppe?`

      Gruß,
      Jan

      1. Hallo Jan,

        ich gehe nachher alles nochmal Schritt für Schritt durch, aber wenn ich das richtig verstehe, werden hier auch vHost-configs erzeugt: /etc/nginx/conf.d/nextcloud.meinedomain.de.conf
        /etc/nginx/conf.d/HttpGateway.conf

        Verzeihe, ich vergaß: Der User für Let’s encrypt ist Teil der www-data Gruppe und die Ordner sind für die Gruppe schreibberechtigt.

        Es tut mir leid, aber irgendwie komme ich da nicht weiter und weiß nicht woran es liegt.

        Grüße,
        Sebastian

        1. Hi Sebastian,

          wirklich nochmal alles Schritt für Schritt durchgehen würde ich hier auch empfehlen. Meistens wurde hier ein kleiner Schritt übersehen, der aber doch wichtig ist.
          Und ja: Mehrere vHosts sind normal, der eine hört eben auf Port 80, der andere auf 443. Es dürfen nur keine zwei vHosts auf den gleichen Port und server_name hören.

          Gruß,
          Jan

          1. Hallo Jan,

            jetzt muss ich sicherheitshalber nochmal nachfragen: ich lasse also in der https.conf den Servername einfach weg? Was ist diese IP-Adresse eigentlich?

            Viele Grüße und nochmal Danke für deine ganze Hilfe

          2. Hi Sebastian,

            nein, einen server_name sollte jeder vHost haben. Ich meinte nur, dass sich die vHosts irgendwie unterscheiden müssen, der server_name kann dazu genutzt werden. Das sollte für dich aber keine Rolle spielen, es geht ja nur um eine Domain, oder? Der server_name sollte immer zur Domain passen.

            Gruß,
            Jan

  5. Hallo Jan,

    ich habe irgendwas kaputt-konfiguriert. Bei nginx geht bei mir gar nichts mehr. Gibt es irgendwie einen eleganten Weg, das Grundsystem komplett neu aufzusetzen (dabei gleichzeitig Ubuntu zu updaten) und dabei die Dateien (auf einer Extra-Festplatte) und die Strukturen (Benutzer mit ihren Passwörtern etc.) zu behalten?

    Danke für die Hilfe und viele Grüße

    1. Hi Sebastian,

      wenn nginx nicht mehr mag, kann das auch mal eine Kleinigkeit sein. Was ergibt der Befehl „nginx -t“?

      Du kannst natürlich ein Backup aller Sachen machen, die auf dem Server laufen, Ubuntu neu aufsetzen und anschließend die Backups zurück spielen. Ich weiß nicht, was alles bei dir installiert ist, aber für Nextcloud können dazu beispielsweise diese Skripte verwendet werden.
      Das Ziel des Backups muss natürlich etwas sein, was das Neuaufsetzen des Servers überlebt, z.B. eine externe Festplatte oder auf ein Samba-Share im Netzwerk.

      Gruß,
      Jan

Kommentar verfassen

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