Zum Inhalt

Docker-Dienst mit Caddy und HTTPS absichern

Veröffentlicht am 7. August 2026 · Geschätzte Lesezeit: 6 Minuten

Caddy nimmt verschlüsselte HTTPS-Anfragen entgegen und leitet sie intern an einen vorhandenen Docker-Dienst weiter. Für eine öffentliche Domain beschafft und erneuert Caddy die TLS-Zertifikate automatisch. Für DNS, Docker-Netzwerk und Funktionstest solltest du etwa 30 bis 45 Minuten einplanen.

Die Anleitung wurde am 3. August 2026 mit der offiziellen Docker-Anleitung von Caddy, dem HTTPS-Schnellstart und der aktuellen Veröffentlichung v2.11.4 geprüft. Das deutschsprachige Video SSL-Zertifikate fürs Homelab mit Caddy zeigt den grundsätzlichen Aufbau zusätzlich.

Voraussetzungen

  • Ein Linux-Server mit installiertem Docker und Docker Compose
  • Ein bereits laufender Docker-Dienst auf demselben Server
  • Eine eigene öffentliche Domain mit Zugriff auf die DNS-Einstellungen
  • Von außen erreichbare TCP-Ports 80 und 443

1. Erreichbarkeit und Domain prüfen

Lege beim DNS-Anbieter einen A-Eintrag für eine Subdomain wie dienst.example.de an. Er muss auf die öffentliche IPv4-Adresse deines Internetanschlusses zeigen. Nutzt du IPv6, ergänzt du einen passenden AAAA-Eintrag.

Prüfe die DNS-Auflösung auf dem Server. Ersetze <subdomain.example.de> durch deine vollständige Subdomain:

getent ahostsv4 <subdomain.example.de>

Die angezeigte Adresse muss deiner öffentlichen IPv4-Adresse entsprechen.

Leite im Router TCP-Port 80 und TCP-Port 443 auf den Docker-Server weiter. Für HTTP/3 kannst du zusätzlich UDP-Port 443 weiterleiten.

Warning

Bei DS-Lite oder CGNAT besitzt der Anschluss oft keine direkt erreichbare öffentliche IPv4-Adresse. Eine einfache Portweiterleitung funktioniert dann nicht. Kläre zuerst beim Anbieter, ob eingehende Verbindungen möglich sind.

2. Gemeinsames Docker-Netzwerk anlegen

Erstelle auf dem Docker-Server ein externes Netzwerk, über das Caddy den Ziel-Dienst erreicht:

docker network create caddy-net

Falls Docker meldet, dass das Netzwerk bereits existiert, kannst du es weiterverwenden.

3. Ziel-Dienst mit dem Netzwerk verbinden

Öffne die compose.yaml deines vorhandenen Dienstes und ergänze beim gewünschten Dienst das Netzwerk. Ersetze <dienst-name> durch den tatsächlichen Namen des Compose-Dienstes.

services:
  <dienst-name>:
    networks:
      - caddy-net

networks:
  caddy-net:
    external: true

Dieser Ausschnitt wird in die vorhandene Datei eingearbeitet und ersetzt sie nicht. Bestehende Netzwerke bleiben erhalten.

Übernimm die Änderung im Ordner des Ziel-Dienstes:

docker compose up -d

Prüfe anschließend die Netzwerkmitgliedschaft. Ersetze <dienst-container> durch den tatsächlichen Containernamen:

docker inspect <dienst-container> --format '{{json .NetworkSettings.Networks}}'

In der Ausgabe muss caddy-net erscheinen.

4. Caddy-Arbeitsordner erstellen

Lege einen eigenen Ordner samt Konfigurationsverzeichnis an und wechsle hinein:

mkdir -p ~/caddy/conf
cd ~/caddy

5. Caddy-Compose-Datei erstellen

Öffne im Ordner ~/caddy eine neue Compose-Datei:

nano compose.yaml

Füge die folgende Konfiguration ein:

services:
  caddy:
    image: caddy:2.11.4-alpine
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./conf:/etc/caddy:ro
      - caddy_data:/data
      - caddy_config:/config
    networks:
      - caddy-net

networks:
  caddy-net:
    external: true

volumes:
  caddy_data:
    name: caddy_data
  caddy_config:
    name: caddy_config

Speichere mit Strg+O, bestätige mit der Eingabetaste und beende Nano mit Strg+X.

Das Volume caddy_data enthält unter anderem Zertifikate und muss dauerhaft erhalten bleiben. Die feste Versionsnummer verhindert einen unbemerkten Versionswechsel.

6. Weiterleitung im Caddyfile festlegen

Erstelle die Caddy-Konfiguration im eingebundenen Verzeichnis:

nano ~/caddy/conf/Caddyfile

Füge den folgenden Block ein. Ersetze <subdomain.example.de> durch deine Domain, <dienst-name> durch den Compose-Dienstnamen und <container-port> durch den internen Port des Ziel-Dienstes.

<subdomain.example.de> {
    reverse_proxy <dienst-name>:<container-port>
}

Für Uptime Kuma wäre der interne Port beispielsweise 3001, für Node-RED 1880. Verwende nicht den links veröffentlichten Host-Port, sondern den Port innerhalb des Ziel-Containers.

Warning

Trage nicht localhost als Ziel ein. Innerhalb des Caddy-Containers bezeichnet localhost nur Caddy selbst. Docker-Dienste werden im gemeinsamen Netzwerk über ihren Dienstnamen erreicht.

7. Konfiguration prüfen und Caddy starten

Prüfe zuerst die Caddyfile-Syntax. Der Befehl wird im Ordner ~/caddy ausgeführt:

docker compose run --rm caddy caddy validate --config /etc/caddy/Caddyfile

Bei einer gültigen Konfiguration startest du Caddy:

docker compose up -d

Beobachte danach die Protokolle, bis Caddy das Zertifikat erfolgreich erhalten hat:

docker compose logs --tail=150 caddy

Danger

Caddy kann nur dann ein öffentlich vertrauenswürdiges Zertifikat anfordern, wenn Domain und Ports korrekt erreichbar sind. Wiederhole fehlgeschlagene Versuche nicht ständig, sondern behebe zuerst DNS, Firewall oder Portweiterleitung.

8. HTTPS von außen testen

Öffne die neue Adresse über ein Mobiltelefon mit ausgeschaltetem WLAN:

https://<subdomain.example.de>

Ersetze den Platzhalter durch deine Domain. Der Browser muss ein gültiges Zertifikat anzeigen und die Oberfläche des Ziel-Dienstes öffnen.

Alternativ prüfst du die Antwort von einem externen Linux-System:

curl -I https://<subdomain.example.de>

Ein HTTP-Status wie 200, 301 oder 302 zeigt, dass eine Antwort über HTTPS ankommt. Welcher Status richtig ist, hängt vom Ziel-Dienst ab.

9. Direkten Zugriff begrenzen

Entferne nach erfolgreichem HTTPS-Test die alte Routerfreigabe des Ziel-Dienstes. Öffentlich weitergeleitet bleiben nur die für Caddy benötigten Ports 80 und 443.

Wenn der Ziel-Dienst ausschließlich über Caddy erreichbar sein soll, kannst du dessen ports-Abschnitt aus der Compose-Datei entfernen. Prüfe vorher, dass Caddy ihn über caddy-net zuverlässig erreicht und du einen Rückweg über das Terminal besitzt.

Tip

Entferne den direkten Host-Port erst nach einem vollständigen Funktionstest. Bei einem Fehler kannst du Caddy stoppen und die frühere Port-Konfiguration des Ziel-Dienstes wiederherstellen.

10. Caddyfile später ändern

Prüfe nach jeder Änderung zuerst die Syntax im laufenden Container:

cd ~/caddy
docker compose exec caddy caddy validate --config /etc/caddy/Caddyfile

Lade eine gültige Konfiguration ohne längere Unterbrechung neu:

docker compose exec -w /etc/caddy caddy caddy reload

11. Backup und Rückweg vorbereiten

Erstelle einen Backup-Ordner und stoppe Caddy:

mkdir -p ~/caddy/backup
cd ~/caddy
docker compose down

Sichere Compose-Datei und Caddy-Konfiguration:

tar -czf "$HOME/caddy/backup/caddy-config-$(date +%F).tar.gz" -C "$HOME/caddy" compose.yaml conf

Sichere zusätzlich das Volume mit Zertifikaten und Kontodaten:

docker run --rm -v caddy_data:/source:ro -v "$HOME/caddy/backup:/backup" alpine:latest tar -czf "/backup/caddy-data-$(date +%F).tar.gz" -C /source .

Starte Caddy danach wieder:

docker compose up -d

Für den schnellen Rückweg stellst du die alte Datei conf/Caddyfile wieder her und lädst sie neu. Bei einem vollständigen Verlust stoppst du Caddy, stellst das Volume aus dem Datenarchiv wieder her und startest den Container erneut.

12. Caddy aktualisieren

Erstelle zuerst ein Backup und prüfe die Veröffentlichungshinweise. Ändere danach die Versionsnummer hinter caddy: in compose.yaml auf die gewünschte geprüfte Version.

Lade das neue Abbild:

cd ~/caddy
docker compose pull

Ersetze den Container mit den vorhandenen Volumes:

docker compose up -d

Prüfe anschließend Protokolle, Zertifikat und den Ziel-Dienst. Bei Problemen trägst du wieder die vorherige Versionsnummer ein und startest Caddy erneut.

13. Typische Fehler beheben

Bei connection refused zum Ziel-Dienst prüfst du, ob beide Container im Netzwerk caddy-net liegen:

docker network inspect caddy-net

Bei Zertifikatsfehlern kontrollierst du die DNS-Auflösung:

getent ahostsv4 <subdomain.example.de>

Prüfe außerdem, ob ein anderer Dienst bereits Port 80 oder 443 belegt:

sudo ss -ltnp | grep -E ':(80|443) '

Erreichst du die Domain über Mobilfunk, aber nicht im Heimnetz, unterstützt dein Router möglicherweise kein NAT-Loopback. In diesem Fall hilft ein lokaler DNS-Eintrag, der die Domain intern auf die Server-IP auflöst.

Fertig

Caddy stellt deinen Docker-Dienst jetzt über eine eigene Domain mit automatisch verwaltetem HTTPS-Zertifikat bereit. Die Einrichtung ist erfolgreich, wenn die Adresse über Mobilfunk ohne Zertifikatswarnung lädt und direkt weitergeleitete Ports des Ziel-Dienstes geschlossen sind.