Explorer
/opt/obsidian-vault/OpenClaw_Troubleshooting_Lessons_Learned.md
← Zurück ↓ Download
# OpenClaw Setup — Troubleshooting & Lessons Learned
**Stand:** 2026-05-10 | **Für:** Nachfolge-KI / zukünftige Sessions
**Zweck:** Dieses Dokument fasst alle Probleme zusammen die bei der Einrichtung von OpenClaw-Instanzen auftraten, was NICHT funktioniert hat, und was die FINALE Lösung war. Ziel: kein erneutes Stochern im Nebel.

---

## TL;DR — Die funktionierende Konfiguration

**Beide OpenClaw-Instanzen (Carlo + Lulu) laufen mit:**
1. **Image-Version:** `ghcr.io/openclaw/openclaw:2026.5.6` (NICHT `:latest`, NICHT v2026.5.7)
2. **Auth-Modus:** `mode: "password"` in openclaw.json
3. **nginx:** Basic Auth davor + Authorization-Header DURCHLEITEN (NICHT clearen)
4. **Erstmaliger Login:** Doppel-Login (nginx Basic Auth + OpenClaw Passwort) → danach gespeichert
5. **Device-Pairing:** Beim ersten Connect manuelle Approval per CLI nötig

---

## Problem 1: v2026.5.7 bricht WebSocket Scope-Resolution

### Symptom
Nach `docker compose pull && docker compose up -d` Update von v2026.5.6 → v2026.5.7:
- Rote Fehlermeldung im UI: `"This connection is missing operator.read, so existing chat history cannot be loaded yet."`
- Container-Logs zeigen: `[ws] ⇄ res ✗ node.list errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read`
- Tritt sekündlich auf für `node.list` Calls

### Was NICHT geholfen hat
- Browser-Cookies löschen
- Container neu starten (`docker restart`)
- Container neu erstellen (`docker compose up -d`)
- nginx-Header `X-OpenClaw-Scopes` mit allen scopes setzen
- Authorization-Header durchleiten statt clearen
- Mode wechseln auf `token` mit injiziertem Bearer-Token
- Stundenlanges Graben im Quellcode (`/app/dist/*.js`)

### Wurzelursache
v2026.5.7 hat das Scope-Handling für WebSocket-Verbindungen in `trusted-proxy` Modus geändert. Die HTTP-Header `X-OpenClaw-Scopes` werden zwar bei HTTP-Requests gelesen (`resolveTrustedHttpOperatorScopes`), aber NICHT korrekt auf die WebSocket-Session übertragen. Das `GatewayClientScopes` Context-Object bleibt leer → alle WS-Methoden die Scopes erfordern (z.B. `node.list` braucht `operator.read`) schlagen fehl.

### FUNKTIONIERENDE LÖSUNG
**Auf v2026.5.6 zurückrollen:**
```bash
docker pull ghcr.io/openclaw/openclaw:2026.5.6
sed -i 's|image: ghcr.io/openclaw/openclaw:latest|image: ghcr.io/openclaw/openclaw:2026.5.6|' /opt/struktur/openclaw-INSTANCE/docker-compose.yml
cd /opt/struktur/openclaw-INSTANCE && docker compose up -d
```

**WARNUNG:** Das Update auf v2026.5.7 NICHT durchführen bis upstream das Scope-Problem fixt. Update-Hinweis im UI ignorieren oder per X wegklicken.

---

## Problem 2: trusted-proxy Modus funktioniert nur teilweise

### Symptom
Auch auf v2026.5.6 mit `mode: "trusted-proxy"`:
- Initialer Login funktioniert
- Erste Tests zeigen UI lädt
- ABER: WebSocket-basierte Funktionen (Chat-Historie laden, Live-Chat) brechen sobald die Browser-Session keinen gespeicherten Device-Token mehr hat (z.B. nach Cookie-Cleanup)

### Wurzelursache
`trusted-proxy` Modus authentifiziert nur HTTP-Requests via Proxy-Header (`X-Forwarded-User`, `X-OpenClaw-Scopes`). WebSocket-Verbindungen brauchen zusätzlich ein im Browser gespeichertes Device-Token. Ohne diesen Token (frische Browser-Session) gibt es keine Scope-Auflösung für WS.

### Was NICHT funktionierte
- nginx-Headers `X-OpenClaw-Scopes` setzen — nur für HTTP wirksam
- `Authorization: ""` setzen — strippt sogar legitime Bearer-Tokens
- Conditional Authorization-Stripping (`if ($http_authorization !~* "^Basic ")`) — half nicht weil Browser nach Storage-Cleanup gar kein Token mehr hat

### FUNKTIONIERENDE LÖSUNG
**Auf `mode: "password"` umstellen** (siehe Problem 3 Setup).

**WICHTIG:** trusted-proxy NICHT verwenden bis das WS-Scope-Issue gefixt ist.

---

## Problem 3: Setup für `mode: "password"` mit nginx Basic Auth davor

### Symptom (initial)
`mode: "password"` mit nginx-Konfiguration aus dem trusted-proxy Setup:
- nginx Basic Auth funktioniert
- ABER: OpenClaw zeigt Connection-Dialog: `"unauthorized: gateway password missing (enter the password in Control UI settings)"`

### Wurzelursache
nginx hatte `proxy_set_header Authorization ""` das den Authorization-Header gelöscht hat. OpenClaw konnte das Bearer-Token vom Browser nicht empfangen.

### FUNKTIONIERENDE LÖSUNG
**nginx Authorization-Header NICHT mehr clearen** (also die Zeile `proxy_set_header Authorization ""` ENTFERNEN). Browser sendet dann sowohl Basic-Auth-Header als auch (nach Login) das OpenClaw-Bearer-Token. OpenClaw ignoriert den Basic-Auth-Header und nutzt sein eigenes Bearer-Token aus Cookies/localStorage.

**Erstmaliger Browser-Login** (Doppel-Login):
1. nginx Basic Auth Dialog → User + Passwort eingeben
2. OpenClaw Connection-Dialog erscheint → Passwort eingeben → "Verbinden"
3. Device Pairing Required Fehler erscheint
4. Auf dem Server: Pairing approven (siehe Problem 4)

Nach erstem Login bleibt das Device-Token im Browser gespeichert → keine erneuten Logins nötig (außer bei Cookie/Storage-Cleanup).

---

## Problem 4: Device Pairing Required nach erstem Login

### Symptom
Nach Eingabe des Passworts im OpenClaw Connection-Dialog:
- Fehler: `"device pairing required (requestId: <UUID>)"`

### Wurzelursache
OpenClaw fordert für jeden neuen Browser/Client eine Device-Pairing-Approval. Standard-Sicherheitsmechanismus.

### FUNKTIONIERENDE LÖSUNG
Auf dem Server per CLI im Container approven:

```bash
docker exec openclaw-INSTANCE node /app/openclaw.mjs devices approve <REQUEST_UUID>
```

Die UUID kommt aus der Fehlermeldung im Browser. Alternative — Pending-Liste anzeigen:

```bash
docker exec openclaw-INSTANCE node /app/openclaw.mjs devices list
```

Nach Approval im Browser auf "Verbinden" klicken — Chat öffnet sich mit voller Historie.

---

## Komplette Setup-Anleitung (Neu-Instanz aufsetzen)

### Voraussetzungen
- Docker mit `struktur-net` Netzwerk (`172.16.0.0/12`)
- nginx mit Let's Encrypt Cert für Subdomain
- htpasswd installiert (`apt install apache2-utils`)

### Schritt 1: Pfadstruktur anlegen
```bash
mkdir -p /opt/struktur/openclaw-INSTANCE/config
mkdir -p /opt/struktur/openclaw-INSTANCE/logs
chown -R 1000:1000 /opt/struktur/openclaw-INSTANCE
```

### Schritt 2: docker-compose.yml
```yaml
services:
  openclaw-INSTANCE:
    image: ghcr.io/openclaw/openclaw:2026.5.6
    container_name: openclaw-INSTANCE
    volumes:
      - ./config:/home/node/.openclaw
      - ./logs:/app/logs
    networks:
      - struktur-net
    ports:
      - "PORT:18789"
    restart: unless-stopped

networks:
  struktur-net:
    external: true
```

### Schritt 3: openclaw.json (config-Ordner)
```json
{
  "gateway": {
    "auth": {
      "mode": "password",
      "password": "INSTANCE_PASSWORD"
    },
    "controlUi": {
      "allowedOrigins": [
        "https://INSTANCE.agentsolutions-mallorca.com",
        "http://localhost:18789",
        "http://127.0.0.1:18789"
      ]
    }
  },
  "models": {
    "providers": {
      "openai": {
        "baseUrl": "http://hermes:3000/v1",
        "apiKey": "dummy",
        "models": []
      }
    }
  },
  "meta": {
    "lastTouchedVersion": "2026.5.6"
  }
}
```

### Schritt 4: nginx-Config (`/etc/nginx/sites-available/INSTANCE`)
```nginx
server {
    listen 443 ssl;
    server_name INSTANCE.agentsolutions-mallorca.com;

    ssl_certificate /etc/letsencrypt/live/CERT_NAME/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/CERT_NAME/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    auth_basic "INSTANCE OpenClaw";
    auth_basic_user_file /etc/nginx/.htpasswd-INSTANCE;

    location / {
        proxy_pass http://127.0.0.1:PORT;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $host;
        proxy_set_header Origin "https://INSTANCE.agentsolutions-mallorca.com";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Cookie $http_cookie;
    }
}

server {
    listen 80;
    server_name INSTANCE.agentsolutions-mallorca.com;
    return 301 https://$host$request_uri;
}
```

**KRITISCH:** KEIN `proxy_set_header Authorization ""` setzen! Browser muss seinen Bearer-Token an OpenClaw weiterleiten können.

### Schritt 5: htpasswd erstellen
```bash
htpasswd -cb /etc/nginx/.htpasswd-INSTANCE BENUTZER 'PASSWORT'
```

### Schritt 6: Aktivieren + Container starten
```bash
ln -s /etc/nginx/sites-available/INSTANCE /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
cd /opt/struktur/openclaw-INSTANCE && docker compose up -d
```

### Schritt 7: Erst-Login Browser
1. Browser öffnen: `https://INSTANCE.agentsolutions-mallorca.com`
2. nginx Basic Auth: BENUTZER / PASSWORT
3. OpenClaw Dialog: INSTANCE_PASSWORD eingeben → "Verbinden"
4. Fehler: "device pairing required (requestId: UUID)"
5. UUID kopieren, auf Server: `docker exec openclaw-INSTANCE node /app/openclaw.mjs devices approve UUID`
6. Im Browser auf "Verbinden" klicken → Chat öffnet sich

---

## Aktuelle Instanzen (Stand 2026-05-10)

### Carlo
- **URL:** `https://carlo.agentsolutions-mallorca.com`
- **Container:** `openclaw-carlo`
- **Port:** `3001`
- **Pfad:** `/opt/struktur/openclaw-carlo/`
- **nginx Basic Auth:** `carlo` / `Carlo2026!`
- **OpenClaw Passwort:** `Carlo2026!`

### Lulu (für Mari)
- **URL:** `https://lulu.agentsolutions-mallorca.com`
- **Container:** `openclaw-lulu`
- **Port:** `3002`
- **Pfad:** `/opt/struktur/openclaw-lulu/`
- **nginx Basic Auth:** `mari` / `Lulu2026!`
- **OpenClaw Passwort:** `Lulu2026!`
- **SSL-Cert:** Nutzt SAN-Cert von `carlo.agentsolutions-mallorca.com` (deckt beide Subdomains)

---

## Verbotene Aktionen (lessons learned)

1. **NICHT auf v2026.5.7 updaten** bevor das WS-Scope-Issue offiziell gefixt ist
2. **NICHT `mode: "trusted-proxy"` verwenden** mit der aktuellen Setup-Konfiguration
3. **NICHT `proxy_set_header Authorization ""`** setzen — bricht OpenClaw Auth
4. **NICHT stundenlang im Quellcode graben** wenn ein simpler Workaround (Version-Pin + password mode) das Problem löst
5. **NICHT mehrere Befehle gleichzeitig im VPS-Terminal** absetzen — Carlo gibt immer nur das Ergebnis von einem Befehl zurück

---

## Update-Pfad (zukünftig)

Wenn ein neues OpenClaw-Release erscheint:
1. **Erst in einer Test-Instanz** prüfen ob trusted-proxy + WS Scope wieder funktioniert
2. Wenn ja: Image-Tag in beiden Instanzen aktualisieren, Container neu starten
3. Wenn nein: auf der gepinnten Version bleiben, weiter beobachten

Update-Befehl pro Instanz:
```bash
sed -i 's|image: ghcr.io/openclaw/openclaw:2026.5.6|image: ghcr.io/openclaw/openclaw:NEUE_VERSION|' /opt/struktur/openclaw-INSTANCE/docker-compose.yml
cd /opt/struktur/openclaw-INSTANCE && docker compose pull && docker compose up -d
```

---

## Bekannte Restthemen (Stand 2026-05-10)

- **Update-Notification im UI** zeigt v2026.5.7 als verfügbar — kann ignoriert werden
- **DeepSeek antwortet englisch** ohne System-Prompt — Persona auf Deutsch konfigurieren noch offen
- **Datenstruktur** für persistente Projekt-Ordner (data-carlo/, data-lulu/) noch nicht angelegt
- **Backup-Strategie** für `/opt/struktur/` noch zu definieren