Claude Code als Homelab-Assistent - Teil 1: Setup & erster Audit
Claude Code als Homelab-Assistent - Teil 1: Setup & erster Audit
Einleitung
Wer ein Homelab betreibt kennt das Muster: Man hat eine Idee, öffnet einen Chat mit Claude, erklärt den Kontext, bekommt einen Vorschlag, kopiert ihn in den Terminal, führt ihn aus, berichtet das Ergebnis zurück, bekommt eine Korrektur - und so weiter. Es funktioniert, aber es ist umständlich. Claude kennt deinen Server nicht, du musst jedes Mal neu erklären was läuft, und zwischen Planung und Ausführung stehst immer du als manueller Zwischenschritt.
Claude Code macht das anders. Es läuft lokal auf deinem Rechner, verbindet sich per SSH direkt mit dem Server, liest Configs, führt Befehle aus und wartet auf deine Bestätigung bevor es etwas ändert. Kein Kopieren, kein Erklären, kein manuelles Hin-und-Her.
Bei mir kommt noch eine Besonderheit dazu: ich arbeite traditionell auf mehreren Systemen gleichzeitig - Stand-PC, Laptop und Tablet. Gerade experimentiere ich zusätzlich mit dem Umstieg auf Linux, arbeite also parallel auf Windows und Linux. Das Setup muss daher auf allen Systemen funktionieren, ohne dass ich es jedes Mal neu aufbauen muss.
In dieser Serie zeige ich wie ich Claude Code als Assistenten für mein Homelab eingerichtet habe - mit wiederverwendbaren Prompts, automatischen Tests und einem Setup das auf jedem Rechner in wenigen Minuten funktioniert.
Teil 1: Konzept, Repo-Aufbau, SSH-Zugang einrichten, erster Security Audit. Teil 2: Ein gefundenes Issue aus dem Audit beheben. Teil 3: Einen neuen Docker Service deployen - von Null bis HTTPS.
Hauptteil
Das Konzept
Die Grundidee ist einfach: Ein privates GitHub Repo das als “Gehirn” für Claude Code dient. Es enthält den Kontext über den Server, wiederverwendbare Prompts als Slash Commands, und Setup Scripts die auf jedem Rechner funktionieren - Windows, Linux, macOS.
homelab-claude/
├── CLAUDE.md <- Kontext, den Claude Code automatisch liest
├── setup.sh <- Einmaliges Setup Linux / macOS
├── setup.ps1 <- Einmaliges Setup Windows
├── .env.example <- Benötigte Secrets (Vorlage)
├── .claude/
│ └── commands/
│ ├── health-check.md <- /health-check
│ ├── security-audit.md <- /security-audit
│ └── deploy-service.md <- /deploy-service
└── prompts/ <- Lesbare Referenz

Das Herzstück ist CLAUDE.md - eine Datei die Claude Code bei jedem Start automatisch
einliest. Darin steht alles was der Assistent über den Server wissen muss: IPs, Services,
URLs, kritische Container die nie ohne Bestätigung angefasst werden dürfen, Konventionen
für neue Stacks, und Verhaltensregeln.
## Kritische Services -- IMMER ZULETZT ANFASSEN
| Service | Container | Warum kritisch |
|---------------|----------------|----------------------------------------------|
| Traefik | traefik | Reverse Proxy -- alle HTTPS-Routen |
| AdGuardHome | adguardhome | DNS -- fällt das aus, ist das Netz offline |
| Tailscale | tailscale | VPN -- einziger externer Zugang |

Wichtig: Die CLAUDE.md im Repo ist meine persönliche Konfiguration - spezifisch für
mein Setup mit meinen Services, IPs und Konventionen. Wer das nachbaut muss diese Datei
für sein eigenes Homelab anpassen. Das Repo ist ein Startpunkt, kein fertiges Produkt das
man einfach klont und loslegt.
Ich überlege dazu noch einen “Discovery”-Prompt einzubauen: Claude Code verbindet sich mit
einem unbekannten Server, liest docker ps, Netzwerke, Volumes und vorhandene Configs -
und generiert daraus automatisch eine initiale CLAUDE.md. Das wäre der saubere Einstieg
für jeden der bei Null startet. Falls ich das umsetze kommt es als eigener Teil in die Serie.
Kein Erklären mehr bei jedem Chat. Der Kontext ist einmal sauber dokumentiert und immer
verfügbar - auf jedem Rechner, nach jedem git pull.
SSH-Key einrichten
Claude Code verbindet sich über ssh-mcp mit dem Server - ein MCP-Server der SSH-Befehle
ausführt. Dabei gibt es eine wichtige Einschränkung: der SSH-Key darf keine Passphrase
haben. ssh-mcp kann verschlüsselte Keys nicht verwenden.
Für ein internes Homelab das nur per LAN oder Tailscale erreichbar ist, ist das vertretbar. Ich empfehle einen dedizierten Key nur für Claude Code - so lässt er sich bei Bedarf einfach widerrufen ohne den Haupt-Key anzufassen.
Windows (PowerShell):
# Key erstellen -- Passphrase leer lassen
ssh-keygen -t ed25519 -C "homelab-claude" -f "$env:USERPROFILE\.ssh\id_ed25519_homelab"
# Auf den Server übertragen
type "$env:USERPROFILE\.ssh\id_ed25519_homelab.pub" | ssh ronin@192.168.178.22 "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
# Testen
ssh -i "$env:USERPROFILE\.ssh\id_ed25519_homelab" ronin@192.168.178.22
Linux / macOS:
# Key erstellen -- Passphrase leer lassen
ssh-keygen -t ed25519 -C "homelab-claude" -f ~/.ssh/id_ed25519_homelab
# Auf den Server übertragen
ssh-copy-id -i ~/.ssh/id_ed25519_homelab.pub ronin@192.168.178.22
# Testen
ssh -i ~/.ssh/id_ed25519_homelab ronin@192.168.178.22
Wenn die Verbindung ohne Passwort funktioniert, ist alles bereit. In .env eintragen:
SSH_KEY_PATH=~/.ssh/id_ed25519_homelab
Stolperstein: Beim ersten Versuch habe ich meinen bestehenden SSH-Key verwendet - der
hatte eine Passphrase. Claude Code lief los, jeder SSH-Befehl schlug fehl mit
Cannot parse privateKey: Encrypted private OpenSSH key detected. Lösung: neuen Key ohne
Passphrase erstellen, MCPs neu registrieren. Das kostet 5 Minuten, aber man sollte es
gleich richtig machen.

Setup auf einem neuen Rechner
Genau hier zahlt sich das Repo-Prinzip aus. Egal ob Windows, Linux oder macOS - das Setup ist immer gleich:
# Repo clonen
git clone git@github.com:RoninRage/homelab-claude.git
cd homelab-claude
# Secrets konfigurieren
cp .env.example .env
# SSH_HOST, SSH_USER, SSH_KEY_PATH eintragen
Dann je nach System:
# Linux / macOS
./setup.sh
# Windows
powershell -ExecutionPolicy Bypass -File setup.ps1
Das Script installiert Claude Code, registriert drei MCP-Server (SSH LAN, SSH Tailscale, Playwright) und zeigt am Ende welche Server aktiv sind. Da ich gerade zwischen Windows und Linux wechsle, war mir wichtig dass beide Scripts identisch funktionieren - gleiche Ausgaben, gleiche Fehlermeldungen, gleiche Reihenfolge. Kein Unterschied ausser dem Dateinamen.
Dann einmal claude starten - der Browser öffnet sich für den Anthropic-Login, einmalig
pro Rechner. Danach läuft alles.

Slash Commands
Statt Prompts aus Dateien zu kopieren und einzufügen, sind alle Prompts als Slash Commands
direkt in Claude Code verfügbar. Die Dateien liegen in .claude/commands/ - Claude Code
erkennt diesen Ordner automatisch.
/health-check <- Container-Status, Speicher, Backup-Log
/security-audit <- Ausführlicher Sicherheits-Audit
/deploy-service <- Neuen Docker Service deployen
Die gleichen Dateien liegen zusätzlich in prompts/ als lesbare Referenz - zum Nachlesen
was ein Command eigentlich tut, ohne Claude Code öffnen zu müssen.

Der erste Security Audit
/security-audit
Claude Code verbindet sich per SSH und prüft parallel fünf Bereiche:
- Traefik-Konfiguration - welche Services laufen ohne Auth-Middleware?
- Offene Ports - was hört auf allen Interfaces, nicht nur über Traefik?
- Container-Sicherheit - läuft etwas privileged oder als root?
- Image-Hygiene - welche Images haben
:lateststatt einem fixen Tag? Welche sind veraltet? - Backup-Coverage - welche Services haben Volumes die nicht gesichert werden?

Das Ergebnis erscheint strukturiert im Terminal mit einer priorisierten To-Do-Liste. Nichts wird gespeichert oder committed - man entscheidet selbst was damit passiert.
Wichtig: Claude Code bekommt bei Audits nur Leserechte. Es werden keine Dateien geschrieben, keine Befehle ausgeführt die etwas verändern. Rohdaten wie IPs oder interne Ports landen nicht in Dateien oder Repos - nur die aufbereitete Zusammenfassung.
Stolperstein Nr. 2: Der Audit-Prompt verwendet ss -tlnp um offene Ports zu prüfen.
Beim ersten Durchlauf kam ein Fehler: sudo: a password is required - ssh-mcp kann
kein sudo-Passwort übergeben. Die Lösung ist einfach: ss -tlnp funktioniert auch ohne
sudo, man sieht dann nur keine Prozessnamen. Für einen Port-Audit reicht das vollständig
aus. Der Prompt wurde entsprechend angepasst.


Fazit
Was vorher ein manuelles Hin-und-Her war ist jetzt ein einziger Befehl. Claude Code liest den Kontext, verbindet sich mit dem Server, führt die Checks aus und liefert einen strukturierten Report - ohne dass man den Setup jedes Mal neu erklären muss.
Das Repo-Prinzip hat dabei einen angenehmen Nebeneffekt: der Kontext ist versioniert, auf
jedem Rechner verfügbar, und wächst mit dem Homelab mit. Wenn ein neuer Service hinzukommt,
wird CLAUDE.md aktualisiert - und alle Rechner wissen beim nächsten git pull Bescheid.
Für jemanden der auf mehreren Systemen arbeitet und gerade zwischen Betriebssystemen wechselt
ist das kein nice-to-have, sondern der eigentliche Grund warum das Setup so gebaut ist.
In Teil 2 schaue ich mir einen der Findings aus dem Audit genauer an und behebe ihn - direkt mit Claude Code, Schritt für Schritt mit Bestätigung.
Ein Gedanke zum Abschluss: Was hier manuell per Slash Command ausgeführt wird, lässt sich
prinzipiell auch automatisieren. /health-check und /security-audit könnten als
regelmäßige Cronjobs laufen - jeden Morgen ein automatischer Status-Report, jede Woche ein
Audit. Die Prompts sind dabei nur der Ausgangspunkt: was geprüft wird, wie der Report
aussieht, und was bei einem kritischen Finding passiert - das alles lässt sich den eigenen
Anforderungen anpassen. Wer möchte kann daraus ein vollständiges Monitoring-System bauen,
wer lieber manuell die Kontrolle behält bleibt beim Slash Command. Beides funktioniert mit
derselben Basis.
Das Repo: github.com/RoninRage/homelab-claude-public
Hinweis zum Repo: Das ist ein anonymisiertes Beispiel meines persönlichen Setups -
IPs, Benutzername, Domain und interne Pfade sind durch Platzhalter ersetzt. Die CLAUDE.md
spiegelt mein Homelab wider und ist kein fertiges Template das man einfach übernehmen kann.
Wer das nachbaut muss sich seine eigene CLAUDE.md erstellen - entweder manuell, oder mit
KI-Hilfe: einfach docker ps, docker network ls und die vorhandenen Compose-Files als
Kontext mitgeben und Claude eine initiale CLAUDE.md generieren lassen. Das ist in wenigen
Minuten erledigt und ergibt sofort eine sinnvolle Basis.