swarmclaw: деплой LXC 135 (оркестратор над openclaw) + домен swarm.dttb.ru

- LXC 135 Debian/Docker, SwarmClaw 24/7, провайдер OmniRoute, агент Opus 4.8
- gateway-связка с openclaw 137 (device paired, connect ok)
- NPM host swarm.dttb.ru -> 10.0.0.135:3456 (WSS), DNS A-запись в SpaceWeb
- обновлены proxmox-inventory, network-topology, npm-proxy-hosts

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
dttb
2026-06-08 22:31:35 +03:00
parent 199dfedf02
commit b55b33b73b
4 changed files with 100 additions and 5 deletions

View File

@@ -0,0 +1,72 @@
---
date: 2026-06-08
type: decision
tags: [dttb, swarmclaw, openclaw, orchestrator, lxc, docker]
---
# SwarmClaw — оркестратор-надстройка над openclaw (LXC 135)
## Контекст
Олег искал «аналог openclaw — оркестратор + удобный + самообучение». По ходу выяснилось:
1. У openclaw **самообучение уже работает** (Dreaming, embeddings ready, recall с concept-tagging + spaced repetition — см. правку [[openclaw]]). Менять движок не нужно.
2. **SwarmClaw** ([github.com/swarmclawai/swarmclaw](https://github.com/swarmclawai/swarmclaw)) — это не замена, а **control-plane НАД openclaw**: рой агентов, делегирование, расписания, дашборд, и подключение существующих openclaw-gateway. Ровно «оркестратор» из запроса, без миграции стека.
Решение: поставить SwarmClaw на Proxmox (не Mac-app — тот умирает с ноутом) как постоянный дирижёр над Антошкой.
## Где живёт
| Параметр | Значение |
|----------|----------|
| Proxmox LXC | **135** (hostname `swarmclaw`) |
| IP | 10.0.0.135/24, gw 10.0.0.1 |
| ОС | Debian 12, unprivileged + `nesting=1,keyctl=1` |
| Ресурсы | 2 vCPU / 4 GB RAM / 16 GB (rootfs на `work`) |
| Рантайм | Docker 29.5 + compose, образ `ghcr.io/swarmclawai/swarmclaw:latest` |
| Каталог | `/opt/swarmclaw` (репо), данные volume `./data:/app/data` |
| Доступ | `pct exec 135 -- bash`; dashboard `http://10.0.0.135:3456` |
## Доступ к UI/API
- **URL:** `http://10.0.0.135:3456` (LAN/NetBird), слушает `0.0.0.0:3456-3457`.
- **ACCESS_KEY:** `4613e7d05f51229a96d7b1a0dd34b24e` — он же cookie `sc_auth` для API.
- Auth: `POST /api/auth {"key":"..."}` → cookie, либо header `Cookie: sc_auth=<KEY>`. `getAccessKey()=process.env.ACCESS_KEY`, `validateAccessKey` сравнивает строкой.
## Что настроено
1. **Провайдер OmniRoute** (`custom`, OpenAI-compatible):
- `baseUrl=http://10.0.0.179:20128/v1`, `requiresApiKey:false` (внутренний, отдаёт каталог без ключа).
- Каталог 58 моделей; инференс `cc/claude-opus-4-8` подтверждён (stream chat.completions).
2. **Агент «Dirizhyor»** (id `0d388a87`) — provider `omniroute`, model `cc/claude-opus-4-8`.
3. **openclaw-gateway как control-plane:**
- credential `cred_62caf5d0f0de` (provider `openclaw`, зашифрованный gateway-token).
- gateway profile `gateway-0eaf65b0` «Antoshka (openclaw 137)», endpoint `http://10.0.0.239:18789`, `isDefault:true`.
- openclaw gateway token: `20bfbdfed25b87b211a6faa60db3ab8fac75fb5100958ac8` (`gateway.auth.mode=token` на LXC 137).
- device спарен и **approved** на openclaw (`openclaw devices` → 10.0.0.135, `operator.admin`).
- connect `ok:true`.
## Грабли (важно для будущего)
1. **ACCESS_KEY жил только в `/app/.env.local` внутри контейнера** (не в volume). Пересоздание/обновление образа → новый ключ → запертый вход. **Фикс:** скопировал `ACCESS_KEY` (+`CREDENTIAL_SECRET` если будет) в **хостовый** `/opt/swarmclaw/.env.local` (он `env_file` в compose) → ключ постоянен через пересоздания. `CREDENTIAL_SECRET` дополнительно лежит в volume `data/credential-secret`.
2. **Auth rate-limit:** 5 неудачных попыток с IP → лок 15 мин (`authRateLimitMap`, in-memory). Перебор форматов auth (Bearer/x-api-key — оба неверные) триггерит. **Правильный auth — только cookie `sc_auth`.** Сброс лока — `docker compose up -d --force-recreate` (in-memory обнуляется, ключ из env_file сохраняется).
3. **Подключение openclaw требует approve device-pairing.** SwarmClaw `manualConnect` хардкодит `useDeviceAuth=true` (протокол v4, `auth:{token}` + device-signature). openclaw в token-mode создаёт **pending pairing** → пока не сделать `openclaw devices approve <requestId>` на LXC 137, connect молча `{"ok":false}`. Token-only handshake (proto4, `auth.token`, scopes `operator.admin`) проверен рабочим. После approve — connect `ok:true`, device в Paired.
4. **`/api/openclaw/doctor``spawn openclaw ENOENT`** — в контейнере нет bundled `openclaw` CLI; связь идёт по WS, не через CLI. Безвредно.
5. **DNS-FakeIP не словили** (в отличие от LXC 137): github/docker.com резолвятся честно через `1.1.1.1/8.8.8.8` даже без NetBird на 135. NetBird не ставил.
6. Локаль в LXC не настроена (`locale: Cannot set LC_*`) — косметика, при желании `locale-gen en_US.UTF-8`.
## Схема API (для будущих правок headless)
- `POST /api/providers``{id,name,baseUrl,models[],requiresApiKey,isEnabled}` (type всегда `custom`), хранит JSON в таблице `provider_configs`.
- `POST /api/agents` → zod `AgentCreateSchema`; обяз. `name`,`provider`; `ollamaMode` только `local|cloud|null` (не `off`).
- `POST /api/credentials``{provider,name,apiKey}`.
- `POST /api/gateways``{name,endpoint,credentialId,isDefault}`.
- `POST /api/openclaw/gateway` → RPC `{method:"gateway.connect",params:{url,token}|{profileId}}`.
- БД: `/opt/swarmclaw/data/swarmclaw.db` (sqlite, таблицы `*_configs/profiles/agents/credentials` как `id+data JSON`), `memory.db`, `logs.db`.
## Домен swarm.dttb.ru (2026-06-08)
- **NPM proxy host #32** (LXC 103, 10.0.0.195): `swarm.dttb.ru``10.0.0.135:3456`, WSS on, block_exploits.
- **DNS:** wildcard `*.dttb.ru` есть только во **внутреннем** DNS (роутер) — http в LAN/NetBird заработал сразу. Публично wildcard НЕТ (каждый поддомен = отдельная A-запись в SpaceWeb). Добавил `swarm A 176.62.183.186` через [[../snippets/spaceweb-dns-api]] (`add-a`, **один вызов** — зона сверена до/после, 23→24 записи, ничего не задето; бэкап `/tmp/dttb_zone_before.txt`).
- **HTTPS/LE:** challenge сработает после публичной пропагации DNS (~10-15 мин, SpaceWeb negative-cache 600s). Фоновый watcher `/tmp/swarm_cert_finish.sh` ждёт пропагацию (DoH dns.google) → NPM LE cert (`meta:{}` — единств. формат, что проходит валидацию этой версии NPM API; `meta` с полями → "additional properties") → attach к host 32 → `ssl_forced`.
## TODO / опционально
- Снести Mac-app `SwarmClaw.app` (или оставить как клиент).
- Маппинг openclaw starter-агентов на gateway (роли/теги) — через UI.
- Самообучение SwarmClaw (`conversation-to-skill`) — **полуручное** (draft→approve), не автономное; для настоящего автообучения остаётся openclaw Dreaming.
## Связано
- [[openclaw]] — основной бот (LXC 137), теперь под управлением SwarmClaw
- [[2026-05-06-openclaw-opus-4-7-via-max-cliproxy]]