Files
knowledge-base/decisions/2026-06-30-cptr-computer-agent.md

45 lines
6.0 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-30
type: decision
tags: [dttb, proxmox, ai, agent, open-webui, computer-use]
---
# cptr (Open WebUI Computer) — агент-песочница, 5-й коннект chat.dttb.ru
## Контекст
Олег попросил завести [open-webui/computer](https://github.com/open-webui/computer) («cptr») и подцепить к Open WebUI. cptr = «компьютер в браузере»: файлы, терминал, git, редактор + AI-агент. Отдаёт **OpenAI-совместимый `/v1/chat/completions`**, где каждый *workspace* виден как модель `cptr/<basename>` с полным агентским доступом (терминал/ФС/web/git) к хосту, где крутится.
## Решение
Отдельный **LXC 146 `cptr`** (песочница) на Proxmox 10.0.0.250 — radius взрыва ограничен контейнером. Мозг агента = OmniRoute Opus 4.8. cptr держим **LAN-only** (авторы: «только доверенная сеть, не в публичный интернет»); публичный chat.dttb.ru ходит к нему server-side по локалке (как Hermes 8642 / openclaw 18789).
## Что развёрнуто
- **LXC 146** Debian 12, unprivileged + `nesting=1,keyctl=1`, Docker 20.10, **2 vCPU / 2 GB / 12 GB** на `work`, onboot.
- IP **10.0.0.166** (nameserver 1.1.1.1, без NetBird). См. грабли с IP ниже.
- Контейнер `ghcr.io/open-webui/computer:latest`: `docker run -d --name cptr --restart unless-stopped -p 8000:8000 -v cptr-data:/data …`. Образ сам стартует `cptr run --host 0.0.0.0 --port 8000 --headless` (из Dockerfile CMD).
- Admin `oleg`/`1qaz!QAZ` (web http://10.0.0.166:8000).
- Workspace `cptr/main``/data/workspaces/main` (persistent в томе).
- **5-й OpenAI-коннект Open WebUI** (idx4): `http://10.0.0.166:8000/v1` + Bearer `sk-cptr-…`. В дропдауне chat.dttb.ru появилась модель `cptr/main`.
## Headless-настройка cptr (всё через API, FastAPI — точные пути из `/openapi.json`)
1. **Startup-токен**: `cptr run` **генерит свой** 64-hex и печатает в логах (`docker logs cptr``…/?token=…`), env `CPTR_STARTUP_TOKEN` игнорится. Брать из логов.
2. **Создать админа**: `POST /api/auth/setup {username,password,token,display_name}``{ok:true}` (даёт cookie `cptr_session`).
3. **Логин**: `POST /api/auth/login {username,password}` → cookie.
4. **Ключ для `/v1`**: `POST /v1/keys {name}` (cookie-auth) → отдаёт `{key:"sk-cptr-…",id,name}` **raw один раз**.
5. **Мозг (brain)**: `POST /api/admin/connections {name,provider:"openai",base_url,api_key,models,enabled}`; проверка `POST /api/admin/connections/{id}/verify`.
6. **Workspace**: `PUT /api/state/workspace?path=/data/workspaces/main` **с JSON-телом** `{"name":"main","path":"…"}` (без тела — 500: роутер читает `request.json()`). После — `cptr/main` появляется в `GET /v1/models` (Bearer-ключ).
7. **В Open WebUI**: `POST /openai/config/update` (полное тело) — добавить URL+key в `OPENAI_API_BASE_URLS`/`OPENAI_API_KEYS` индексом 4 + `OPENAI_API_CONFIGS["4"]={enable,name:"cptr (computer agent)",connection_type:"external",model_ids:["cptr/main"]}`. НЕ затирать idx0-3.
## Грабли (за что наступали)
- ⚠️ **Конфликт IP**: сначала дали **.146** — там реальное устройство **Яндекс-Станция Миди** (MAC `AC:BA:C0:39:82:64`). Тесты прошли (ARP случайно указывал на контейнер), но это мина → Станция перехватит ARP → chat.dttb.ru 502. **Та же грабля, что у LXC 145** ([[2026-06-27-homepage-dashboard-lxc145]]). Перенесли на **.166** (`pct set 146 -net0 …ip=10.0.0.166/24` + `pct reboot`), проверено arping + ping-sweep. **Урок: сверять IP с [[../projects/dttb/network-topology]] ДО раздачи; .145/.146 заняты TP-Link/Яндексом.**
- **Пустой api_key мозга → битый заголовок**: cptr при пустом ключе шлёт `Authorization: Bearer ` (пустой) → httpx «Illegal header value» → verify=false. Лечится **любым непустым** значением (`lan-trust`) — OmniRoute на LAN всё равно отдаёт `cc/claude-opus-4-8` по произвольному Bearer (проверено: `Bearer dummy` → completion 200). Это **отличие от Open WebUI**, где ключ OmniRoute = пустая строка.
- `/v1/models` пустой, пока нет ни одного workspace (модели гейтвея = workspaces, не мозг). Завести через `PUT /api/state/workspace`.
- Workspace-dir держать в томе `/data` (переживает пересоздание контейнера), не в `/home/cptr`.
## Безопасность
Гейт = **Bearer-ключ `sk-cptr-…` (только у Open WebUI) + LAN + admin-only Open WebUI**. Агент исполняет тулы (терминал/ФС) **внутри LXC 146** — проверено: на `hostname`/`uname` агент видит хостнейм контейнера (`d01b45f09cc6`), не Proxmox-хост. Аудит-лог включён (`CPTR_AUDIT_LOG_LEVEL=INFO`). cptr **не** за NPM и без публичного домена.
## Проверено (e2e)
chat.dttb.ru → `cptr/main` → OmniRoute Opus → агент → `run_command`: `uname -a; pwd` вернул `Linux d01b45f09cc6 … x86_64` + cwd `/data/workspaces/main`. `echo cptr-live; whoami``cptr-live`/`cptr`.
См. [[../projects/dttb/proxmox-inventory#LXC 146 — cptr (Open WebUI Computer / агент-исполнитель)]], [[2026-06-22-open-webui-deploy]].