ContextWolf Split-Setup: PostgreSQL auf dem Pi, MCP auf dem Mac
Die ContextWolf-Datenbank muss nicht auf dem Arbeitsrechner laufen. MCP-Server und DB lassen sich auf zwei Maschinen aufteilen: Datenbank auf den Pi, MCP bleibt auf dem Mac. Dieser Artikel zeigt das Setup mit dem neuen Base-Stack aus V5.0.1 - LAN, Tailscale, den PG18-Fallstrick und wie ich das bei mir selbst fahre.
DarkWolfCave.de
ℹ️ Voraussetzungen: Ein Raspberry Pi (4 oder 5, 4 GB RAM reichen) mit Docker, eine feste LAN-IP oder ein Tailscale-Account, der ContextWolf-Hauptartikel als Kontext und die aktuelle context-wolf v5.0.1 Version.
Warum die Datenbank nicht auf dem Mac liegen muss
Der Mac ist mein Arbeitsrechner. Er ist nachts aus, das Netzteil liegt mal mit, mal ohne Mac im Rucksack, und der SSD-Platz ist zu wertvoll für Container, die im Hintergrund laufen sollen. Eine PostgreSQL-Instanz auf dem Arbeitsrechner bedeutet: Beim Herunterfahren wird der Container pausiert, beim nächsten Start geht er wieder hoch. Solange ich das bewusst mache, ist das okay. Der Moment, in dem es nicht okay ist, kommt beim Embedding-Worker, der mitten im Bulk-Import abbricht, weil der Mac in den Ruhezustand gegangen ist.
Auf dem Pi sieht die Rechnung anders aus. Der Pi läuft durch. Backup übers Netzwerk ist gelöst. Die DB ist immer erreichbar, auch wenn ich am Laptop vom Balkon aus arbeite. Und wenn ich mir ein zweites Notebook dazustelle, greift es auf denselben Datenbestand zu, ohne dass ich Dateien synchronisieren muss.
ContextWolf V5 ist genau für diesen Split gebaut. Das Repo hat mit commit f7f6926 eine saubere Base+Overlay-Architektur bekommen: Der Base-Stack enthält nur die Datenbank, der optionale UI-Stack joined das Netzwerk und nutzt dieselbe DB. Der MCP-Server wiederum lebt gar nicht im Docker - er läuft direkt aus dem Python-Paket als Subprocess von Claude Code.
Zwei Komponenten, klar getrennt
Drei Puzzleteile, aber nur zwei davon sind für das Split-Setup relevant:
cm-mcp- der MCP-Server. Wird von Claude Code beim Session-Start als Subprocess gestartet. Transport iststdio. Es gibt keinen HTTP- oder SSE-Transport im Code - wer nachsieht, findet inmcp_server/mcp_context_server.pynur den einenmcp.run()Default-Aufruf. Darum gilt:cm-mcpläuft immer lokal, dort wo Claude Code läuft.cm_postgres- der Datenbank-Container aus demcontext-wolfBase-Repo. PG18 mit pgvector, Daten in einem Bind-Mount unter./data/postgres/, Port 5432 per Default nach außen. Der Container kann auf dem Pi, auf einem NAS oder auf einem anderen Server stehen - solange der Mac ihn per TCP erreicht, funktioniert das Ganze.cm_backend+cm_frontend- das optionale UI-Stack aus demcontext-wolf-uiRepo. Nicht Teil dieses Artikels. Für Setup und Konfiguration gibt es den ContextWolf-Kurs in der Wolf Academy - dort ist die GUI der zentrale Bestandteil.
Du wirst hier einen groben Überblick finden.
Allerdings biete ich dir auch noch etwas mehr Support an:
- Du benötigst persönlichen Support
- Du möchtest von Beginn an Unterstützung bei deinem Projekt
- Du möchtest ein hier vorgestelltes Plugin durch mich installieren und einrichten lassen
- Du würdest gerne ein von mir erstelltes Script etwas mehr an deine Bedürfnisse anpassen
Für diese Punkte und noch einiges mehr habe ich einen limitierten VIP-Tarif eingerichtet.
Falls der Tarif gerade nicht verfügbar ist, kontaktiere mich auf Discord!
Variante A: Pi im lokalen Netz
Diese Variante ist für alle, die den Pi im eigenen LAN stehen haben und nicht von unterwegs auf die DB zugreifen wollen. Weniger Komplexität, keine externen Abhängigkeiten, schneller aufgesetzt.
Schritt 1: Docker auf dem Pi
Falls der Pi noch kein Docker hat, die Anleitung für Docker auf dem Raspberry Pi abarbeiten. Kurz und ohne Umwege. Wer frisch startet, sollte auch das 64-Bit-System auf dem Pi installieren - pgvector braucht ARM64.
Schritt 2: Base-Stack klonen und konfigurieren
Auf dem Pi:
# Repo klonen
git clone https://github.com/DarkWolfCave/context-wolf.git
cd context-wolf
# Env-Template kopieren und Passwort setzen
cp .env.example .env
nano .env
Die .env enthält die drei Werte, die beim Compose-Start eingesetzt werden:
POSTGRES_USER=cm_user
POSTGRES_PASSWORD=EIN_STARKES_PASSWORT
POSTGRES_DB=context_manager
# Optional - Port anpassen falls 5432 schon belegt ist
# POSTGRES_PORT=5433
Wichtig ist das Passwort. Das Default-Passwort changeme aus älteren Versionen existiert im neuen Setup nicht mehr - die .env zwingt dich, einen Wert einzutragen.
Schritt 3: Container starten
Auf dem Pi im context-wolf-Ordner:
docker compose up -d --wait
Das --wait hält die Konsole so lange fest, bis der Healthcheck pg_isready grün ist. Der erste Start dauert auf einem Pi 5 rund 15 Sekunden, die Daten landen unter ./data/postgres/18/docker/.
⚠️ Wichtig: Das neue
docker-compose.ymlmountet bewusst auf das Parent-Verzeichnis/var/lib/postgresql. PG18 legt dort automatisch18/docker/an. Wer versehentlich auf/var/lib/postgresql/datamountet oderPGDATAals Env-Variable setzt, schreibt seine Daten in ein anonymes Docker-Volume und verliert sie beim nächstendown.
Schritt 4: Pi-Firewall öffnen
Der Container bindet per Default auf alle Interfaces des Pis, sobald docker compose up läuft. Auf dem Pi selbst die ufw-Regel setzen, wenn ufw aktiv ist:
# Nur aus dem eigenen Subnetz erlauben (Beispiel)
sudo ufw allow from 192.168.0.0/24 to any port 5432
Wer iptables direkt nutzt oder eine andere Firewall fährt, schränkt entsprechend ein. Wichtig ist: nicht einfach Port 5432 öffentlich ins Internet stellen - psycopg reicht im ContextWolf-Code keine SSL-Parameter durch, das heißt auch bei gesetztem Passwort geht Authentifizierung im Klartext übers Netz.
Schritt 5: Mac-Seite - MCP-Server an die Pi-DB binden
Auf dem Mac das ContextWolf-Repo klonen und cm init mit Option 2 durchlaufen:
git clone https://github.com/DarkWolfCave/context-wolf.git
cd context-wolf
cp .env.example .env
bash setup.sh --init
Das Setup-Skript fragt:
[1] Local Docker (PostgreSQL in container)
[2] External server (remote PostgreSQL)
> 2
Host [localhost]: 192.168.x.x # Pi-LAN-IP
Port [5432]: 5432
Database [context_manager]:
User [cm_user]:
Password: EIN_STARKES_PASSWORT # gleiches wie in .env auf dem Pi
Das schreibt die Werte nach ~/.context/config.yaml mit chmod 600 - das Passwort liegt dort im Klartext, genau wie bei fast jedem Datenbank-Client. Die Datei ist bewusst nur für den eigenen User lesbar.
Schritt 6: Verifizieren
cm doctor # prüft DB-Verbindung und Schema
cm stats # zeigt Projekt- und Session-Counts
Bei mir sieht das dann so aus:
📊 Context Manager Statistics
Backend: POSTGRES
Projects: 85
Actions: 7873
Sessions: 1341
DB Size: 58.00 MB
Ab diesem Punkt funktioniert Claude Code mit dem Pi als DB-Backend.
Du willst ContextWolf auf Raspberry Pi einrichten nicht selbst einrichten? Ich übernehme das für dich — schau dir meine Services an
Variante B: Pi per Tailscale von unterwegs
Die LAN-Variante ist elegant, solange du nicht mobil arbeitest. Sobald du aus einem fremden Netz auf die DB willst, stehen genau zwei Optionen zur Wahl: Port-Forwarding am Router mit allen Risiken - oder ein Mesh-VPN. Bei mir läuft Tailscale, weil es in fünf Minuten eingerichtet ist und keine eigenen Ports im Internet öffnet.
Tailscale auf beiden Geräten
Auf dem Pi:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
# Login-URL im Browser bestätigen
Auf dem Mac das Tailscale-Client-Paket installieren, mit demselben Tailnet verbinden.
Pi-Container an die Tailscale-IP binden
Der Pi hat jetzt zwei IPs: seine LAN-IP und eine Tailscale-IP im Bereich 100.x.x.x. Standard-Bind auf 5432 lauscht auf beiden. Wer bewusst nur Tailscale-Traffic erlauben will, setzt in der .env der Base-Compose:
# Explizit auf Tailscale-IP binden
POSTGRES_PORT=5432
# In docker-compose.yml die ports-Zeile anpassen:
# "100.x.x.x:5432:5432"
Das erfordert eine kleine Anpassung in der Compose-Datei. Wer das nicht will, regelt den Zugriff über die Tailscale ACLs im Admin-Panel - feiner, ohne Compose-Änderung.
Mac-Seite auf Tailscale-IP umstellen
Statt der LAN-IP kommt in ~/.context/config.yaml die Tailscale-IP des Pis. cm init lässt sich erneut durchlaufen oder die YAML direkt editieren:
database:
backend: postgres
postgres:
host: 100.x.x.x # Tailscale-IP des Pis
port: 5432
database: context_manager
user: cm_user
password: EIN_STARKES_PASSWORT
Ab jetzt tunnelt die Verbindung verschlüsselt durchs Tailnet. Auch aus Hotel-WLAN oder ICE-Internet. Das ist die einzige saubere Art, ContextWolf über unsichere Netze zu fahren - solange SSL im Code nicht unterstützt ist.
Der PG18-Mount-Fallstrick
Einen Punkt wiederhole ich bewusst, weil er schon beim Live-Umzug meiner eigenen Instanz fast danebenging.
PostgreSQL 18 hat das Default-Data-Directory geändert. Früher war es /var/lib/postgresql/data/, jetzt ist es /var/lib/postgresql/18/docker/. Das ist in der offiziellen Docker-Hub-Dokumentation beschrieben, aber in vielen bestehenden Compose-Setups noch nicht angekommen - und bricht jede Compose-Datei, die noch auf das alte Verzeichnis mountet. Wer sich das im Detail anschauen will, findet in PostgreSQL in Docker und der Datenverlust die Hintergründe und den sauberen Upgrade-Pfad.
Drei Varianten im Überblick:
| Mount-Ziel | Verhalten bei PG18 | Empfehlung |
|---|---|---|
./data:/var/lib/postgresql/data | Daten landen im anonymen Docker-Volume, Bind-Mount bleibt leer | Finger weg |
PGDATA=/var/lib/postgresql/data setzen | Überschreibt PG-Default, funktioniert, aber Upgrade-Pfad ist blockiert | Workaround |
./data:/var/lib/postgresql (Parent) | PG18 legt 18/docker/ selbst an, Upgrade auf PG19 per pg_upgrade --link möglich | Richtig |
Die neue docker-compose.yml im context-wolf-Repo nutzt Variante 3. Wer von einem alten ContextWolf-Setup migriert, muss das Daten-Verzeichnis entsprechend verschieben. Details stehen im Repo unter docs/.
Performance in der Realität
Die Frage, die bei jedem Remote-DB-Setup aufkommt: Wie viel Latenz kostet das eigentlich? Ich habe es bei mir gemessen, auf dem Pi über WLAN ans Netzwerk angebunden:
| Messung | Wert |
|---|---|
| Ping zum Pi (WLAN) | 4 ms Durchschnitt |
cm search "docker" gesamt | 150 ms |
| DB-Größe im Container | 58 MB |
| Einträge in der DB | 7.873 |
Die 150 ms sind die Gesamtdauer: Python-Import, Tokenizer laden, ONNX-Modell auf dem Mac rechnen lassen, Query gegen den Pi schicken, Ergebnis zurück. Der reine DB-Roundtrip macht davon einen Bruchteil aus - die CLI-Startup-Kosten sind der Löwenanteil.
Im Alltag ist das nicht spürbar. Die MCP-Calls aus Claude Code sind per stdio-Transport eingebettet in die LLM-Response und laufen ohne CLI-Startup. Dort sind Suchen unter 20 ms realistisch, wenn die DB nicht gerade komplett neu indexiert.
Backup - der Punkt, der im README fehlt
Die Daten auf dem Pi sind nur dann sicher, wenn es ein externes Backup gibt. Ein Bind-Mount auf derselben SD-Karte hilft bei Container-Problemen, aber nicht bei einem Kartenausfall.
Auf dem Pi einen Cron-Job einrichten:
# /etc/cron.daily/contextwolf-backup
#!/bin/bash
BACKUP_DIR="/backup/contextwolf"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
mkdir -p "$BACKUP_DIR"
cd /home/USER/context-wolf || exit 1
# Dump im custom-Format (komprimiert, selective restore möglich)
docker compose exec -T postgres pg_dump \
-U cm_user \
-d context_manager \
-F c \
> "$BACKUP_DIR/contextwolf-$TIMESTAMP.dump"
# Alte Dumps nach 30 Tagen wegräumen
find "$BACKUP_DIR" -name "contextwolf-*.dump" -mtime +30 -delete
Das -F c-Format ist das Standard-Custom-Format von PostgreSQL. Komprimiert, und per pg_restore lassen sich einzelne Tabellen zurückspielen, ohne die ganze DB kippen zu müssen. Der Backup-Ordner sollte selbst ein externes Ziel haben - per rsync auf ein NAS, per rclone in verschlüsselten Cloud-Storage oder per externer USB-Platte.
Restore im Ernstfall:
# Base-Stack runter, leere Daten-Volume, Dump zurückspielen
docker compose down
sudo rm -rf data/postgres/18
docker compose up -d --wait
cat backup.dump | docker compose exec -T postgres pg_restore \
-U cm_user -d context_manager --clean
Das habe ich bei mir mehrfach durchgespielt. Gefühlt unspektakulär, genau das Gefühl, das man von einem Restore haben will.
Der Embedding-Worker bleibt auf dem Mac
Intuitiv wäre es naheliegend, auch den Embedding-Worker auf den Pi zu schieben - der Worker berechnet die Vektoren für neue CM-Einträge, das passiert im Hintergrund, der Pi könnte das genauso gut. Theoretisch ja.
In der Praxis läuft der Worker bei mir auf dem Mac als launchd-Job (~/Library/LaunchAgents/dev.context-wolf.embedding.plist, 10-Minuten-Intervall) und spricht den Pi nur als Datenbank-Client an. Drei Gründe:
- Das ONNX-Modell
all-MiniLM-L6-v2belegt rund 90 MB auf der Platte und braucht beim Inferenzlauf ein paar hundert MB RAM. Auf dem Mac läuft es perCoreMLExecutionProviderhardware-beschleunigt, auf dem Pi 5 nur perCPUExecutionProvider. - Neue Einträge entstehen auf meinem Coding-Rechner. Der Worker sieht sie dort sofort.
- Ein zusätzlicher Pi-Prozess ist ein zusätzlicher Punkt, der schiefgehen kann - ohne Mehrwert.
Wer den Worker trotzdem auf den Pi ziehen will, findet den Code im embedding_worker/ Unterordner des Repos. requirements.txt liegt daneben, das Einrichten ist nicht komplizierter als ein normaler Python-Cronjob.
Beide Welten verbinden: ContextWolf UI
Das UI-Stack aus context-wolf-ui ist technisch unabhängig, aber nutzt genau dieselbe Datenbank - per Docker-Network contextwolf-net, das der Base-Stack bereitstellt. Eine DB, ein Datenbestand, keine Synchronisation nötig. Setup, Traefik-Integration, SSL, Nutzer-Authentifizierung und die GUI-Nutzung sind der Stoff, den ich in der Wolf Academy aufbereite - nicht im Blog.
Für das Split-Setup hier bedeutet das: Wer die DB einmal auf dem Pi stehen hat, hat keinen Aufwand mehr, wenn später die GUI dazukommen soll. Der Base-Stack bleibt, das UI-Stack gesellt sich dazu.
Das ganze Setup auf einen Blick
Aus Mac-Sicht läuft alles unverändert: Claude Code starten, Prompt eingeben, MCP-Tools funktionieren. Aus Infrastruktur-Sicht steht die Datenbank woanders:
- Pi: Base-Stack aus
context-wolf, PG18 + pgvector, Bind-Mount, per LAN oder Tailscale erreichbar. - Mac: ContextWolf als Python-Paket, MCP-Server per stdio, Embedding-Worker als launchd-Job, Zugangsdaten in
~/.context/config.yaml. - Latenz: im Alltag unspürbar, unter Claude Code gar nicht sichtbar.
- Backup:
pg_dumpals Cron auf dem Pi, externes Ziel ist Pflicht. - GUI: optional, per UI-Stack auf denselben Pi - Details im Kurs.
Wer diesen Split einmal sauber aufgesetzt hat, hat einen der am schwersten kaputt zu bekommenden Gedächtnis-Stacks, die ich kenne. Der Mac kann neu aufgesetzt werden, ohne dass ein einziger CM-Eintrag verloren geht. Der Pi kann getauscht werden, solange das Bind-Mount-Verzeichnis mitwandert. Und wenn du Claude Code im Alltag nutzt wie ich, ist das genau die Basis, die du willst.
Wer ContextWolf noch nicht kennt, findet den vollständigen Kontext im Hauptartikel zum Projekt - von der vibe-scribe-Vergangenheit bis zum aktuellen Release. Das Repository liegt auf github.com/DarkWolfCave/context-wolf.
Hardware für das Pi-Setup
Wer sich den Pi für ContextWolf zusammenstellen will, findet hier mein komplettes Setup. Ein Pi 5 mit 4 GB reicht für die Datenbank locker, 8 GB geben Luft für spätere Spielereien wie UI-Stack oder einen zweiten Container. Eine NVMe-SSD statt SD-Karte ist beim Dauerbetrieb mit Datenbank-I/O die bessere Wahl - warum ich den Pi 5 von NVMe SSD boote, steht im verlinkten Artikel.
Das komplette Setup für den Raspberry Pi 5 mit NVMe Boot
Mein Raspberry Pi 5 Setting
| Bild | Produkt | Preis | |
|---|---|---|---|
| Produktdaten werden geladen... | |||
Mehr zum Thema Raspberry Pi und Homelab:
Kommentare