浪人
DE | EN
Claude Code als Homelab-Assistent  -  Teil 2: Einen Bug finden und beheben
tech

Claude Code als Homelab-Assistent - Teil 2: Einen Bug finden und beheben

Zurück zum Blog
3 Min. Lesezeit

Claude Code als Homelab-Assistent - Teil 2: Einen Bug finden und beheben

Einleitung

In Teil 1 haben wir Claude Code als Homelab-Assistenten eingerichtet - SSH-Zugang, Slash Commands, erster Security Audit. Am Ende stand die Frage: was passiert wenn der /health-check tatsächlich etwas findet?

Die Antwort kam schneller als erwartet. Beim ersten echten Health Check war sofort ein Problem sichtbar: ein Container im Status unhealthy - seit 9 Stunden, unbemerkt.

Was folgte zeigt vielleicht besser als jedes Beispiel warum dieser Workflow funktioniert: Claude Code hat nicht nur den Status gemeldet, sondern die Ursache gefunden, den Fix erarbeitet, und die Lösung PR-ready geliefert. Alles in einem Durchgang, ohne dass ich selbst einen einzigen Docker-Befehl eingetippt habe.


Hauptteil

Der Kontext: timetracker-plus

timetracker-plus ist ein Projekt das ich gerade entwickle - eine React-Anwendung zur Arbeitszeiterfassung. Das Ziel ist simpel: Arbeitszeiten einmal erfassen und dann in unterschiedliche Formate verteilen - für eigene Aufzeichnungen, für die Firma in zwei verschiedenen Formaten, und bei Bedarf auch für den Kunden in deren jeweiligem Format.

Der Stack ist eine Docker-gehostete React-App mit Datenbank, deployed über GitHub Actions mit einem lokal gehosteten Runner direkt auf dem Homelab-Server. Sprich: ein git push auf main löst den Deploy aus, der Runner baut das Image und startet den Container neu.

Das läuft automatisch - und genau das macht den Bug interessant. CI/CD hatte den Container erfolgreich deployed, GitHub Actions zeigte grün, alles schien in Ordnung. Was niemand bemerkt hatte: der Container war seit dem letzten Deploy unhealthy.

Der Health Check schlägt an

/health-check

Healthcheck-output

Der Report war eindeutig:

[ERR]  timetracker-plus-web-1 — unhealthy (seit 9h)
[OK]   Alle anderen 19 Container laufen stabil
[WARN] Docker Build Cache (5.2 GB) + dangling Images (4 GB) reclaimable

Neun Stunden. Der letzte Deploy war am Abend davor - seitdem lief der Container technisch, aber der Healthcheck schlug bei jedem Versuch fehl. 1106 Fehlversuche, alle 30 Sekunden.

Claude Code fragte direkt: “Soll ich die Logs von timetracker-plus-web-1 anschauen?”

Die Diagnose

Healthcheck-log

Die Ursache war schnell gefunden - und klassisch:

exec: "curl": executable file not found in $PATH
FailingStreak: 1106 (seit ~9 Stunden, alle 30s)

Der Healthcheck im Compose-File rief curl auf um den /api/health Endpunkt zu prüfen. Das Problem: das Next.js-Image ist ein schlankes Node-Alpine-Image - und curl ist dort nicht installiert.

Der Container selbst lief einwandfrei. Die Logs zeigten Ready in 177ms, alle Requests wurden normal beantwortet. Nur der Healthcheck schlug fehl, weil er ein Tool aufrief das im Image schlicht nicht vorhanden war.

Claude Code fasste es treffend zusammen:

Note: Der Container funktioniert einwandfrei - nur der Healthcheck ist falsch konfiguriert. Fix: Healthcheck auf wget oder einen nativen Node-Check umstellen.

Den Fix erarbeiten

Healthcheck-log-fix-long

Claude Code hat sich als nächstes das Git-Repo angeschaut - der Actions Runner Workdir war auf dem Server sichtbar, Branch main. Der Fix gehört in docker-compose.prod.yml:

# vorher
healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:3000/api/health"]

# nachher (wget)
healthcheck:
  test: ["CMD-SHELL", "wget -qO- http://localhost:3000/api/health || exit 1"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 30s

Bevor der Fix feststand, kam noch eine gute Frage von mir: läuft der Healthcheck wirklich innerhalb des Containers? Port 3000 ist der interne Port - von außen ist der Service auf einem anderen Port erreichbar.

Claude Code bestätigte: Healthchecks laufen im Container-Namespace, Port 3000 ist korrekt. Die Logs bestätigten das zusätzlich - next start hört intern auf 3000, von außen ist ein anderer Port gemappt.

Healthcheck-log-fix

Dann noch eine schnelle Prüfung ob wget überhaupt im Image vorhanden ist:

docker exec timetracker-plus-web-1 which wget 2>&1
docker exec timetracker-plus-web-1 which curl 2>&1

Ergebnis: /usr/bin/wget - wget ist da, curl nicht. Der Fix mit wget ist der richtige Weg, PR-ready.

Der Fix landet im Repo

docker-compose.prod.yml angepasst, committed, auf main gepusht. Der GitHub Actions Runner hat den Deploy automatisch ausgelöst - neues Image gebaut, Container neugestartet.

Healthcheck-github-action-run

Beim nächsten /health-check war die Welt wieder in Ordnung:

Healthcheck-fixed

timetracker-plus-web-1 — jetzt healthy, neu gestartet vor 7 Minuten.
Alle 20 Container laufen stabil.

Fazit

Was mich an diesem Durchgang am meisten beeindruckt hat: der Bug war nicht neu. Er war beim letzten Deploy entstanden und hatte 9 Stunden unbemerkt existiert - GitHub Actions zeigte grün, der Container lief, alles schien normal. Ohne den regelmäßigen Health Check hätte ich das möglicherweise erst bemerkt wenn jemand explizit nachgeschaut hätte.

Das ist der eigentliche Wert dieses Setups. Nicht dass Claude Code einen Bug behebt den man selbst auch hätte finden können - sondern dass er überhaupt gefunden wird, bevor er zum Problem wird.

Der Workflow von Fund bis Fix hat keine 15 Minuten gedauert. Ich habe keinen einzigen Docker-Befehl selbst eingetippt, keine Log-Datei manuell durchsucht, keinen Compose-File-Syntax nachgeschlagen. Claude Code hat das alles übernommen - ich habe die Schritte bestätigt und den Push gemacht.

In Teil 3 setzen wir einen neuen Service auf - von einem leeren Ordner bis zu einer funktionierenden HTTPS-URL, mit Traefik-Integration und automatischem Playwright-Test am Ende.

Das Repo: github.com/RoninRage/homelab-claude-public