Skip to content
DE | EN
Go back

Meine Heiminfrastruktur mit Claude Code aufgebaut — ein ehrlicher Erfahrungsbericht

Meine Heiminfrastruktur mit Claude Code aufgebaut — ein ehrlicher Erfahrungsbericht

In Artikel 1 habe ich geschrieben, dass ich beim Aufbau meiner Infrastruktur gelernt habe, wie man die Fallstricke von Claude Code sicher umgeht. Das war keine leere Ankündigung. Dieser Artikel ist die Einlösung dieses Versprechens.

Was hier entstanden ist: ein vollständig selbst gehosteter Blog-Stack — Ghost als headless CMS, Astro als statischer Frontend-Generator, Gitea Actions als CI/CD-Pipeline, Nginx als Reverse Proxy, Cloudflare als einzige externe Abhängigkeit. Alles läuft auf zwei Raspberry Pis im Heimnetzwerk, abgesichert mit einer Firewall-Architektur die sich vor den meisten Corporate-Umgebungen nicht verstecken muss.

Claude Code war beim Aufbau dabei. Aber nicht als Autopilot — sondern als Assistent, dem ich bei jedem einzelnen Schritt über die Schulter geschaut habe.


Das Setup: Klein, aber ernst gemeint

Bevor wir zu Claude Code kommen, kurz zur Infrastruktur selbst. Denn die ist der Kontext der alles andere bestimmt.

graph TD
    Internet([🌐 Internet]) -->|HTTPS| CF[Cloudflare\nZero Trust Tunnel]
    CF -->|Verschlüsselt| UCG[UniFi UCG Max\nFirewall / Router]
    UCG -->|DMZ VLAN| Pi4

    subgraph Heimnetz["🏠 Heimnetzwerk"]
        subgraph DMZ["DMZ Zone"]
            Pi4[Raspberry Pi 4\nGhost CMS\nNginx\nOllama]
        end
        subgraph LAN["LAN Zone"]
            Pi5[Raspberry Pi 5\nGitea\nNAS / Samba]
        end
        Pi4 <-->|Intern| Pi5
    end

    UCG -->|LAN VLAN| Pi5
    Dev([💻 MacBook\nEntwicklung]) -->|SSH / lokal| Pi5
    Dev -->|SSH / lokal| Pi4

Was hier gebaut wurde:

Warum Cloudflare die einzige externe Abhängigkeit ist

Kein offener Port im Router. Kein DynDNS. Kein selbst verwaltetes TLS-Zertifikat das abläuft. Der Cloudflare Tunnel baut eine ausgehende Verbindung von meinem Pi zur Cloudflare-Infrastruktur auf — von außen ist kein Port offen, es gibt keine direkte Angriffsfläche.

Das ist eine bewusste Sicherheitsentscheidung, keine Bequemlichkeit. Wer seinen Homeserver mit einem offenen Port 443 betreibt, setzt sich einem anderen Risikoprofil aus als jemand der Zero Trust als Architekturprinzip umsetzt.

Sicherheit die sich vor Corporate-Umgebungen nicht verstecken muss

Ich höre manchmal den Einwand: "Heimlabor ist doch kein ernst zu nehmender Betrieb." Das sehe ich anders.

Was hier implementiert ist:

Bei zwei Nutzern gibt es eigentlich nur ein Wort zum Thema Performance zu sagen: Genug.


Der Stack: Wie die Teile zusammenspielen

flowchart TD
    classDef cloud   fill:#1e3a5f,color:#93c5fd,stroke:#93c5fd,stroke-width:1.5px
    A[📝 Artikel\nschreiben\nin Ghost] -->|Webhook| B[Gitea\nRepository]
    B -->|Trigger| C[Gitea Actions\nCI/CD Pipeline]
    C -->|Build| D[Astro\nStatic Site\nGenerator]
    D -->|Deploy| E[Dev-Instanz\nzur Prüfung]
    E -->|QG1: Code Review| F[👤 Freigabe 1]
    F -->|QG2: Visuelle Prüfung| G[👤 Freigabe 2]
    G -->|Deploy| H[Nginx Prod\nDocker]
    H -->|Cache-Invalidierung| I[Cloudflare\nTunnel]
    I -->|HTTPS| J[🌐 Leser]

    class F cloud
    class G cloud

Ghost läuft als headless CMS in einem Docker-Container — kein Theme, nur die Content API. Artikel werden in Ghost geschrieben und verwaltet, aber das Frontend ist komplett von Ghost getrennt.

Astro mit dem AstroPaper Theme generiert aus den Ghost-Inhalten statische HTML-Seiten. Statisch bedeutet: kein serverseitiges Rendering, kein PHP, keine Datenbank-Anfragen beim Seitenaufruf. Schnell, sicher, wartungsarm.

Gitea Actions übernimmt die CI/CD-Pipeline: Ghost löst per Webhook einen Build aus, Gitea Actions zieht die Inhalte über die Ghost Content API, Astro baut die statische Site. Dabei gibt es zwei Quality Gates — kein Artikel geht ohne explizite Freigabe live.


Claude Code im Einsatz: Was ich wirklich gemacht habe

Jetzt zum eigentlichen Thema. Wie habe ich Claude Code beim Aufbau eingesetzt — und was habe ich dabei gelernt?

Die Grundregel: Nur was ich bewerten kann

Ich habe für mich eine klare Regel aufgestellt: Claude Code kommt nur dort zum Einsatz, wo ich das Ergebnis selbst beurteilen kann. Das klingt selbstverständlich — ist es in der Praxis aber nicht immer. Die Versuchung ist groß, einen generierten YAML-Block einfach zu übernehmen weil er "plausibel aussieht".

Das habe ich bewusst nicht getan. Jeder Schritt wurde freigegeben, nachdem ich verstanden hatte was er tut.

Was Claude Code gut gemacht hat

Gitea Actions Workflows waren ein klarer Stärkebereich. Die YAML-Syntax ist verbose und beim Schreiben fehleranfällig — ein falsches Leerzeichen reicht für einen Fehler. Im Betrieb ist sie dafür sehr stabil und zuverlässig. Claude Code hat mir funktionierende Grundgerüste geliefert die ich dann angepasst und reviewt habe.

# Beispiel: Generiertes Workflow-Grundgerüst für Astro-Build
name: Build and Deploy
on:
  repository_dispatch:
    types: [ghost-webhook]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      - name: Install dependencies
        run: npm ci
      - name: Build Astro site
        run: npm run build
        env:
          GHOST_API_URL: ${{ secrets.GHOST_API_URL }}
          GHOST_CONTENT_API_KEY: ${{ secrets.GHOST_CONTENT_API_KEY }}

Nginx-Konfigurationen für Reverse Proxy und SSL-Termination — Claude Code hat solide Ausgangspunkte geliefert. Die Cloudflare-spezifischen Header musste ich ergänzen — genau das Szenario das ich in Artikel 1 beschrieben habe: Claude Code kennt meinen Kontext nicht, wenn ich ihn nicht liefere.

Bash-Skripte für Deployment, Backup und Monitoring — hier war Claude Code am zuverlässigsten. Überschaubare Aufgaben, gut definierte Eingaben und Ausgaben, einfach zu reviewen.

Wo ich korrigieren musste

Sicherheitsrelevante Konfigurationen — hier war ich am kritischsten. Claude Code hat mir Nginx-Konfigurationen generiert die technisch korrekt, aber nicht security-hardened waren. Fehlende Security-Header, zu permissive CORS-Einstellungen, Standardwerte die in Produktion nichts zu suchen haben.

Das ist kein Vorwurf an Claude Code. Es ist eine Bestätigung der Kernthese aus Artikel 1: das Modell kennt meinen Sicherheitsanspruch nicht, wenn ich ihn nicht explizit in den Prompt bringe.

Gitea-spezifische Eigenheiten — Gitea Actions ist GitHub Actions sehr ähnlich, aber nicht identisch. Claude Code hat mir mehrfach GitHub-Actions-Syntax generiert die in Gitea nicht funktioniert. Nach dem ersten Mal habe ich das immer explizit im Prompt erwähnt: "Das läuft auf Gitea Actions, nicht GitHub Actions."

Infrastructure as Code Struktur — Claude Code hat funktionierende, aber nicht wartbare Skripte generiert. Zu viele hartcodierte Werte, keine Parametrisierung, keine Fehlerbehandlung. Das habe ich immer nachgebessert — und dabei viel gelernt.

Was ich daraus gelernt habe

Das ist der eigentlich wertvolle Teil. Nicht der generierte Code — sondern was ich durch das kritische Review des generierten Codes gelernt habe.

Wenn ich einen Nginx-Block reviewe den Claude Code generiert hat, muss ich verstehen warum jede Direktive da ist. Das zwingt mich dazu, tiefer in die Dokumentation einzutauchen als ich es ohne KI-Unterstützung vielleicht getan hätte. Claude Code hat mir nicht die Arbeit abgenommen — es hat mir einen Ausgangspunkt gegeben, über den ich nachgedacht habe.

Das ist ein Nutzungsmuster das ich empfehle: Claude Code als Gesprächspartner und Ausgangspunkt, nicht als Autopilot.


Das Ergebnis: Eine Pipeline die funktioniert

Nach einigen Wochen Aufbau, Review-Zyklen und Anpassungen läuft der Stack stabil. Hier der vollständige Deployment-Flow mit beiden Quality Gates:

sequenceDiagram
    participant T as Thomas
    participant G as Ghost CMS
    participant GA as Gitea Actions
    participant AS as Astro Build
    participant DEV as Dev-Instanz
    participant AP1 as Quality Gate 1\nCode Review
    participant AP2 as Quality Gate 2\nVisuelle Prüfung
    participant PROD as Nginx Prod
    participant CF as Cloudflare

    T->>G: Artikel veröffentlichen
    G->>GA: Webhook auslösen
    GA->>AS: Astro Build triggern
    AS->>AP1: Build fertig → Code Review
    T->>AP1: ✅ Code freigeben
    AP1->>DEV: Deploy auf Dev-Instanz
    T->>DEV: Visuell prüfen
    T->>AP2: ✅ Visuell freigeben
    AP2->>PROD: Deploy auf Produktion
    PROD->>CF: Cache-Invalidierung via API
    Note over CF: Leser sehen neue Version

Zwei Quality Gates — Code Review und visuelle Prüfung auf der Dev-Instanz — bevor etwas produktiv geht. Jeder Pfeil in diesem Diagramm ist ein Schritt den ich verstehe, den ich reviewt habe, und für den ich geradestehen kann. Das war das Ziel.


Fazit: Selbst bauen, selbst verstehen, selbst verantworten

Was ich aus diesem Projekt mitgenommen habe geht über den Tech-Stack hinaus.

Erstens: Ein Heimlabor kann — mit dem richtigen Architekturansatz — eine ernstzunehmende Infrastruktur sein. Zonenarchitektur, Zero Trust, Infrastructure as Code, automatisierte Pipelines mit manuellen Gates — das sind keine Enterprise-Exklusivitäten.

Zweitens: Claude Code ist ein ausgezeichnetes Werkzeug für genau diesen Kontext — wenn man es richtig einsetzt. Als Ausgangspunkt, als Gesprächspartner, als Beschleuniger für Aufgaben die man selbst beurteilen kann. Nicht als Ersatz für das eigene Verständnis.

Drittens: Der Review-Prozess ist nicht der Overhead — er ist der Mehrwert. Ich habe durch das kritische Durcharbeiten von Claude Code-Output mehr über Nginx, Gitea Actions und Bash gelernt als durch passives Lesen von Dokumentation.

Self-hosting ist für mich keine Nostalgie und kein Protest. Es ist eine bewusste Entscheidung für Kontrolle, Verständnis und Souveränität — über meine Daten, meine Infrastruktur, und meinen Tech-Stack.


Dieser Artikel gibt ausschließlich meine persönliche Meinung wieder und steht in keinem Zusammenhang mit beruflichen Tätigkeiten.


Share this post:

Previous Post
Masterbuilt Gravity 1050: Bypass Panel — vom Design zum fertigen Teil
Next Post
AI Without the Cloud — What Actually Works, and What Doesn't