NoctisNode
← GuidesSicherheit2026-10-2310 Min.

Caddy Automatic HTTPS: So funktioniert Auto-TLS — und so beheben Sie Fehler

Caddy holt und erneuert TLS-Zertifikate per ACME für jede Domain in Ihrer Konfiguration. HTTP-01, TLS-ALPN-01, Wildcards per DNS-01, On-Demand-TLS und typische Fehler erklärt.

Kurz gesagt: Caddy aktiviert HTTPS automatisch für jede Site-Adresse, die ein öffentlicher Domainname ist. Es fordert per ACME ein Zertifikat an (standardmäßig von Let's Encrypt oder ZeroSSL), weist die Kontrolle über die Domain per HTTP-01- oder TLS-ALPN-01-Challenge auf den Ports 80 und 443 nach, leitet HTTP auf HTTPS um und erneuert das Zertifikat vor Ablauf — ganz ohne zusätzliche Konfiguration.

Ein Caddy-Reverse-Proxy ist schlicht Caddy, das diese HTTPS-Verbindung terminiert und die Anfrage mit der Direktive `reverse_proxy` an eine App auf einem anderen Port, in einem Container oder auf einem anderen Host weiterleitet. Diese Kombination aus TLS und Proxy in wenigen Zeilen ist der Hauptgrund, warum man sich dafür entscheidet.

Reverse Proxy mit SSL in drei Zeilen

Wenn das DNS auf den Server zeigt und die Ports 80 und 443 erreichbar sind, ist dieses Caddyfile ein vollständiger HTTPS-Reverse-Proxy für zwei Hostnamen. Caddy holt beim Start Zertifikate für beide Namen, liefert HTTP/1.1, HTTP/2 und HTTP/3 aus und gibt `X-Forwarded-For`, `X-Forwarded-Proto` und `X-Forwarded-Host` an das Backend weiter. Die Option `email` ist optional, erlaubt der CA aber, Sie wegen ablaufender oder widerrufener Zertifikate zu kontaktieren.

Die Installation aus dem offiziellen apt-Repository und systemd-Grundlagen behandelt die Anleitung zu Caddy als Reverse Proxy; für Container siehe Caddy als Docker-Reverse-Proxy. Änderungen übernehmen Sie mit `sudo systemctl reload caddy`.

# /etc/caddy/Caddyfile
{
	email [email protected]
}

example.com, www.example.com {
	reverse_proxy 127.0.0.1:8080
}

Wie Caddy Auto-TLS unter der Haube funktioniert

Beim Laden einer Konfiguration sammelt Caddy jeden Hostnamen aus den Site-Adressen und entscheidet, wer das jeweilige Zertifikat ausstellen soll. Öffentliche Domains gehen an die öffentlichen ACME-Aussteller; `localhost`, IP-Adressen und rein interne Namen bekommen Zertifikate von Caddys eigener lokaler CA (wie bei `tls internal`). Zertifikate, Schlüssel und das ACME-Konto liegen in Caddys Datenverzeichnis: `/var/lib/caddy/.local/share/caddy` beim apt-Paket, `/data` im offiziellen Docker-Image.

Die Erneuerung läuft im Hintergrund, lange vor dem Ablauf, und Caddy stapelt OCSP-Antworten (Stapling), wo die CA das unterstützt. Schlägt die Ausstellung fehl, versucht Caddy es mit exponentiellem Backoff erneut und nutzt für Wiederholungen den Staging-Endpunkt der CA, um die Produktions-Rate-Limits nicht zu verbrauchen. Mehrere Caddy-Instanzen mit gemeinsamem Speicher koordinieren sich, sodass nur eine ein bestimmtes Zertifikat anfordert.

ChallengeWas die CA prüftVoraussetzungWildcards?
HTTP-01Ein Token unter `http://domain/.well-known/acme-challenge/`Port 80 aus dem Internet erreichbarNein
TLS-ALPN-01Ein spezielles Zertifikat, das beim TLS-Handshake präsentiert wirdPort 443 aus dem Internet erreichbarNein
DNS-01Ein TXT-Record unter `_acme-challenge.domain`API-Token des DNS-Anbieters und ein Caddy-Build mit dem passenden Provider-ModulJa

Wildcard-Zertifikate mit DNS-01

Wildcard-Zertifikate wie `*.example.com` lassen sich nur über die DNS-01-Challenge ausstellen. Das Standard-Binary von Caddy enthält keine DNS-Provider-Plugins, daher bauen Sie eines mit xcaddy (oder wählen den Provider auf der offiziellen Download-Seite) und geben Caddy ein API-Token, das nur DNS-Änderungen für diese Zone erlaubt. DNS-01 funktioniert auch, wenn die Ports 80 und 443 aus dem Internet nicht erreichbar sind, etwa auf einem rein internen Server.

Halten Sie das Token aus dem Caddyfile heraus: Legen Sie es in eine Environment-Datei, die die systemd-Unit nutzt (`sudo systemctl edit caddy`, dann `EnvironmentFile=/etc/caddy/caddy.env` unter `[Service]`), und schränken Sie die Datei mit `chmod 600` ein.

# Build Caddy with a DNS provider module (example: Cloudflare)
xcaddy build --with github.com/caddy-dns/cloudflare

# Caddyfile: one wildcard certificate for all subdomains
*.example.com {
	tls {
		dns cloudflare {env.CF_API_TOKEN}
	}

	@app host app.example.com
	handle @app {
		reverse_proxy 127.0.0.1:3000
	}

	handle {
		respond "Unknown host" 404
	}
}

On-Demand-TLS und Staging

Mit On-Demand-TLS holt Caddy ein Zertifikat beim ersten TLS-Handshake für einen Hostnamen, den es noch nicht kennt. Das ist für Plattformen gedacht, bei denen Kunden ihre eigenen Domains auf Ihren Server zeigen lassen. Konfigurieren Sie immer den `ask`-Endpunkt: Caddy ruft ihn mit `?domain=name` auf und macht nur bei einer 200-Antwort weiter. Ohne ihn könnte jeder beliebige Namen auf Ihre IP zeigen lassen und Sie in die Rate Limits treiben.

Zum Experimentieren wechseln Sie mit der globalen Option `acme_ca` auf die Staging-CA von Let's Encrypt. Staging-Zertifikate sind in Browsern nicht vertrauenswürdig, aber die Limits sind viel höher, sodass Sie gefahrlos Dinge kaputt machen und reparieren können. Entfernen Sie die Option, wenn Sie fertig sind, und löschen Sie optional die Staging-Zertifikate aus dem Datenverzeichnis.

{
	on_demand_tls {
		ask http://127.0.0.1:5555/allowed
	}
}

https:// {
	tls {
		on_demand
	}
	reverse_proxy 127.0.0.1:8080
}

# Global options block for testing
{
	email [email protected]
	# Test against Let's Encrypt staging; remove when everything works
	acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}

Typische TLS-Fehler bei Caddy und ihre Lösung

  1. 01.DNS zeigt nicht auf den Server: Der A- oder AAAA-Record fehlt, zeigt noch auf einen alten Server oder ist gecacht. Ein veralteter AAAA-Record ist eine klassische Falle, weil die CA IPv6 bevorzugt, wenn es existiert. Prüfen Sie beide mit `dig`.
  2. 02.Port 80 oder 443 geschlossen: Die Host-Firewall, eine Cloud-Firewall oder ein Router blockiert eingehenden Traffic, sodass weder HTTP-01 noch TLS-ALPN-01 abgeschlossen werden kann. Öffnen Sie 80/tcp und 443/tcp (und 443/udp für HTTP/3).
  3. 03.Port bereits belegt: Apache, nginx oder ein anderer Container ist an 80 oder 443 gebunden, sodass Caddy nicht lauschen kann. Stoppen Sie den anderen Dienst oder stellen Sie ihn hinter Caddy.
  4. 04.CDN-Proxy davor: Ein Proxy im Stil der „orangen Wolke“ terminiert TLS vor Caddy, was TLS-ALPN-01 brechen kann. Nutzen Sie DNS-01 oder stellen Sie den Record während der Ausstellung auf „nur DNS“.
  5. 05.Rate Limits: Wiederholte Fehlversuche oder ein gelöschtes Datenverzeichnis lassen Sie in die Limits der CA laufen (Let's Encrypt begrenzt fehlgeschlagene Validierungen pro Hostname und Stunde sowie doppelte Zertifikate pro Woche). Beheben Sie die Ursache, nutzen Sie Staging und halten Sie das Datenverzeichnis persistent.
  6. 06.CAA-Record: Ein CAA-Record, der nur eine andere CA erlaubt, blockiert die Ausstellung. Erlauben Sie `letsencrypt.org` und `sectigo.com` (von ZeroSSL genutzt) oder entfernen Sie die Einschränkung.
# Does the name resolve to this server (both IPv4 and IPv6)?
dig +short A example.com
dig +short AAAA example.com
curl -4 -s https://ifconfig.me ; echo

# Are ports 80 and 443 open in the host firewall?
sudo ufw status
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 443/udp

# Is something else already bound to 80/443?
sudo ss -ltnp '( sport = :80 or sport = :443 )'

# What does Caddy say?
sudo journalctl -u caddy --no-pager -n 100

HTTPS auch zum Backend

Die meisten Backends auf demselben Host sprechen einfaches HTTP auf localhost — das ist in Ordnung. Liegt der Upstream auf einer anderen Maschine oder besteht er auf TLS, nutzen Sie einen `https://`-Upstream und sagen Caddy, welcher Name geprüft und welcher CA vertraut werden soll. Vermeiden Sie `tls_insecure_skip_verify` außerhalb schneller Tests, denn damit entfällt der Schutz gegen Abhören zwischen Proxy und Backend. Für Traffic zwischen Servern ist ein privater WireGuard-Tunnel oft einfacher, als Backend-Zertifikate zu verwalten.

Auf einem NoctisNode-VPS mit vollem Root-Zugriff und dedizierter IPv4-Adresse sieht das übliche Setup so aus: einen A-Record (keinen AAAA, sofern der Server kein IPv6 hat) auf den Server zeigen lassen, 80 und 443 öffnen und den Rest Caddy überlassen. Wenn Sie Nicht-HTTP-Traffic weiterleiten müssen, siehe TCP- und SSH-Proxying mit Caddy.

example.com {
	reverse_proxy https://10.0.0.5:8443 {
		transport http {
			tls_server_name backend.internal
			tls_trust_pool file /etc/caddy/backend-ca.pem
		}
	}
}

FAQ

QWas ist ein Caddy-Reverse-Proxy?

ADas ist der Caddy-Webserver, der Client-Verbindungen annimmt, meist HTTPS terminiert und Anfragen mit der Direktive `reverse_proxy` an einen oder mehrere Backend-Dienste weiterleitet. Die TLS-Zertifikate dafür holt und erneuert Caddy automatisch.

QErneuert Caddy Zertifikate automatisch?

AJa. Caddy erneuert Zertifikate im Hintergrund lange vor ihrem Ablauf und lädt sie ohne Neustart neu, solange die Domain weiterhin auf den Server auflöst und die Challenge-Ports erreichbar bleiben.

QWarum bekommt Caddy kein Zertifikat?

ADie häufigsten Ursachen sind DNS-Records, die woandershin zeigen (einschließlich eines veralteten AAAA-Records), blockierte Ports 80 und 443, ein anderes Programm auf diesen Ports oder Rate Limits nach wiederholten Fehlschlägen. `journalctl -u caddy` zeigt den genauen ACME-Fehler.

QKann Caddy ein Wildcard-Zertifikat ausstellen?

AJa, aber nur über die DNS-01-Challenge. Dafür brauchen Sie einen Caddy-Build mit dem Modul Ihres DNS-Anbieters und ein API-Token für diese Zone.

QWie deaktiviere ich Automatic HTTPS in Caddy?

AVerwenden Sie für eine einzelne Site eine `http://`-Site-Adresse oder setzen Sie die globale Option `auto_https off`. Mit `auto_https disable_redirects` behalten Sie die Zertifikate, schalten aber die Umleitung von HTTP auf HTTPS ab.

Caddy Automatic HTTPS: So funktioniert Auto-TLS — und so beheben Sie Fehler · NoctisNode