// Tutorial · Web · TLS

nginx + Let’s Encrypt per acme.sh: Zertifikate automatisch

📅 02.09.2026 ⏱10 Min. Lesezeit ✍️ Redaktion

HTTPS ist heute Pflicht – das manuelle Zertifikatsmanagement aber nicht. acme.sh stellt Let’s-Encrypt-Zertifikate aus, legt sie direkt in deinen nginx-Serverblock und erneuert sie automatisch. So bekommst du gültige TLS-Zertifikate ohne Wartungsarbeit.

Warum acme.sh?

Let’s Encrypt ist der einfachste Weg zu kostenlosen TLS-Zertifikaten – aber das Ausstellen, Ablegen und Erneuern will trotzdem organisiert sein. Genau hier kommt acme.sh ins Spiel: ein reines Shell-Skript, das Zertifikate beantragt, auf Wunsch direkt in deinen nginx-Ordner legt und über den Cron täglich auf Ablauf prüft.

Der Vorteil gegenüber manuellem Vorgehen: Nach der Einrichtung passiert alles automatisch – du musst nur noch den Serverblock einmal richtig konfigurieren.

Konzept: ACME & Challenge-Typen

acme.sh spricht das ACME-Protokoll der Zertifizierungsstellen. Um zu beweisen, dass dir die Domain gehört, stehen mehrere Challenge-Typen zur Auswahl:

  • Webroot – legt eine Prüfdatei unter /var/www/html/.well-known/acme-challenge/ ab (Port 80 muss erreichbar sein)
  • Standalone – acme.sh belegt kurzzeitig selbst Port 80 (nginx dabei stoppen!)
  • nginx-Modus – acme.sh konfiguriert die Challenge automatisch über nginx
  • DNS-API – legt einen TXT-Record per API an; einzige Option für Wildcard-Zertifikate *.domain.de

Standard-Zertifizierungsstelle ist bei acme.sh inzwischen ZeroSSL. Da dieser Artikel Let’s Encrypt behandelt, stellen wir die Standard-CA um.

Voraussetzungen

Bevor es losgeht, sollten drei Dinge stimmen:

  • DNS: Deine Domain zeigt per A-/AAAA-Record auf die IP des Servers
  • nginx: läuft und bedient die Domain (mindestens auf Port 80)
  • Firewall: Port 80 und 443 sind von außen erreichbar

Für die Zertifikate legen wir einen Ordner an:

sudo mkdir -p /etc/nginx/ssl
Kein Docker nötig: acme.sh läuft direkt auf dem Host als normales Shell-Skript – ohne Container, ohne Root-Daemon. Nur die Installation der Zertifikate nach /etc/nginx braucht sudo.

acme.sh installieren

acme.sh wird ins eigene Verzeichnis ~/.acme.sh installiert und richtet sich selbst einen Cron für die Erneuerung ein:

curl https://get.acme.sh | sh -s email=admin@meine.domain

Wer curl | sh vermeiden will, klont das Repository:

git clone https://github.com/acmesh-official/acme.sh.git
              cd acme.sh
              ./acme.sh --install -m admin@meine.domain

Danach auf Let’s Encrypt umstellen und das Konto registrieren:

acme.sh --set-default-ca --server letsencrypt
              acme.sh --register-account -m admin@meine.domain
Wichtig: Die E-Mail-Adresse wird für Ablauf-Erinnerungen genutzt. Ohne --register-account verlangt Let’s Encrypt die Registrierung spätestens beim ersten Ausstellen.

Zertifikat ausstellen

Die einfachste Variante bei laufendem nginx ist der Webroot-Modus-w zeigt auf das DocumentRoot der Domain:

acme.sh --issue -d web.meine.domain -w /var/www/html
              
              # mehrere Domains in einem Zertifikat (SAN):
              acme.sh --issue -d meine.domain -d www.meine.domain -w /var/www/html
              
              # Wildcard (nur mit DNS-API, z. B. Cloudflare):
              acme.sh --issue -d "*.meine.domain" --dns dns_cf --server letsencrypt

Alternativen: --nginx (acme.sh erledigt die Challenge über nginx) oder --standalone (nginx kurz stoppen, Port 80 frei).

Challenge fehlgeschlagen? Häufigste Ursachen: Webroot-Pfad falsch, Port 80 zu, oder die Prüfdatei wird vom Serverblock nicht ausgeliefert. Zum Testen: http://web.meine.domain/.well-known/acme-challenge/ im Browser öffnen.

nginx & Zertifikatsinstallation

acme.sh legt die Zertifikate standardmäßig nur in ~/.acme.sh ab. Für nginx installieren wir sie an einen festen Ort und sorgen dafür, dass nginx nach jeder Erneuerung neu geladen wird:

acme.sh --install-cert -d web.meine.domain \
                --key-file /etc/nginx/ssl/web.meine.domain.key \
                --fullchain-file /etc/nginx/ssl/web.meine.domain.fullchain \
                --reloadcmd "systemctl reload nginx"

Der Serverblock nutzt dann diese Pfade – inklusive HTTP→HTTPS-Weiterleitung:

server {
                  listen 80;
                  server_name web.meine.domain;
                  return 301 https://$host$request_uri;
              }
              
              server {
                  listen 443 ssl;
                  http2 on;
                  server_name web.meine.domain;
              
                  ssl_certificate     /etc/nginx/ssl/web.meine.domain.fullchain;
                  ssl_certificate_key /etc/nginx/ssl/web.meine.domain.key;
                  ssl_protocols       TLSv1.2 TLSv1.3;
              
                  root /var/www/html;
                  index index.html;
              }

Konfiguration prüfen und neu laden:

sudo nginx -t && sudo systemctl reload nginx
nginx ≥ 1.25: Dort ist listen 443 ssl http2; veraltet – stattdessen listen 443 ssl; plus http2 on; verwenden. Ältere Versionen weiter mit listen 443 ssl http2;.

Automatische Erneuerung

acme.sh installiert bei der Installation einen Cron, der täglich prüft, ob Zertifikate in weniger als 60 Tagen ablaufen – und sie dann erneuert. Der --reloadcmd sorgt dafür, dass nginx die neuen Dateien sofort lädt:

# manueller Test-Lauf (macht nichts kaputt):
              acme.sh --cron
              
              # Liste aller verwalteten Zertifikate:
              acme.sh --list
              
              # Erneuerung erzwingen (nur bei Bedarf!):
              acme.sh --renew -d web.meine.domain --force
Rate Limits beachten: Let’s Encrypt begrenzt Duplikate pro Woche. Für Experimente den --staging-Server nutzen, erst dann die Produktion. --renew --force sparsam einsetzen.

Betrieb & Absicherung

  • Backup: Neben /etc/nginx/ssl gehört auch ~/.acme.sh (mit Account- und CA-Infos) ins Backup – dann ist ein Umzug auf einen neuen Server problemlos möglich.
  • Rechte: Private Key nur für root lesbar halten: sudo chmod 600 /etc/nginx/ssl/*.key
  • Prüfen: Nach der Einrichtung mit curl -I https://web.meine.domain oder dem Browser testen; Uptime-Kuma überwacht danach dauerhaft.
  • Upgrade: acme.sh aktualisiert sich bei Cron-Läufen selbst – oder manuell mit acme.sh --upgrade.

Häufige Probleme (FAQ)

ProblemLösung
Challenge schlägt mit 404 fehlWebroot-Pfad prüfen, .well-known darf nicht per Rewrite blockiert werden; Port 80 muss offen sein
„Too many certificates“Rate Limit von Let’s Encrypt – 1 Woche warten oder mit --staging testen
Erneuerung findet nicht stattCron prüfen (crontab -l), acme.sh --cron manuell testen, --reloadcmd gesetzt?
Es kommt ZeroSSL statt Let’s Encryptacme.sh --set-default-ca --server letsencrypt ausführen
Wildcard wird abgelehntWildcards funktionieren nur mit DNS-API-Challenge, nicht per Webroot
Zertifikat nach Server-Umzug ungültigAltes Zertifikat entfernen und neu ausstellen lassen (--renew -d domain --force)

Fazit

Mit acme.sh und nginx bekommst du ein Zertifikatssystem, das sich nach der Einrichtung selbst verwaltet: Ausstellen, Ablegen, Erneuern und nginx-Reload laufen automatisch. Übrig bleibt nur ein sauber konfigurierter Serverblock – und eine Domain, die dauerhaft unter HTTPS erreichbar ist.

Merksätze:~/.acme.sh + /etc/nginx/ssl gehören ins Backup.
② Ohne --reloadcmd lädt nginx neue Zertifikate nicht.
③ Port 80 muss für die HTTP-Challenge offen bleiben.
④ Erst mit --staging testen, dann produktion.
📝
....

Wir betreiben unsere komplette Infrastruktur selbst auf Open-Source-Software und schreiben nur über Tools, die wir im Alltag wirklich einsetzen. Fragen zum Artikel? Schreib uns.