Files
knowledge-base/decisions/2026-06-08-swarmclaw-lxc135-deploy.md
dttb b55b33b73b 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>
2026-06-08 22:32:04 +03:00

73 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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]]