# DEV TASK: Деплой CLIProxyAPI на mva154 **Статус:** Ready for dev **Проект:** claude-cli-proxy **BRD:** `tasks/claude-cli-proxy/BRD.md` --- ## Цель Поднять CLIProxyAPI в Docker на mva154, подготовить к OAuth авторизации Claude Max подписки. После авторизации — OpenClaw сможет использовать Claude через подписку вместо API токенов. ## Контекст - **CLIProxyAPI** — Go-сервер, оборачивает Claude Code CLI в OpenAI-compatible API - **Docker image:** `eceasy/cli-proxy-api:latest` - **Порт по умолчанию:** 8317 - **OAuth порт (для логина):** 54545 - **Доступ:** только из docker network (OpenClaw контейнер на том же хосте) - **Один аккаунт**, без load balancing --- ## Инфраструктура | Параметр | Значение | |----------|----------| | Сервер | `slin@82.22.50.71` (пароль: `motoZ@yaz2010`) | | SSH | через Node.js ssh2 модуль | | Docker network | та же сеть что у OpenClaw контейнера | | Рабочая директория | `/home/slin/claude-cli-proxy/` | --- ## Задачи ### Task 1: Подготовка файлов на сервере **Шаги:** - [ ] **1.1** Создать директорию и config.yaml: ```bash mkdir -p /home/slin/claude-cli-proxy/auth cat > /home/slin/claude-cli-proxy/config.yaml << 'EOF' port: 8317 remote-management: allow-remote: false secret-key: "" auth-dir: "/root/.cli-proxy-api" auth: providers: [] debug: false EOF ``` Примечание: `auth.providers: []` — отключает проверку API key, используется OAuth токен. - [ ] **1.2** Создать docker-compose.yml: ```bash cat > /home/slin/claude-cli-proxy/docker-compose.yml << 'EOF' version: "3.8" services: cli-proxy-api: image: eceasy/cli-proxy-api:latest container_name: claude-cli-proxy restart: unless-stopped ports: - "127.0.0.1:8317:8317" volumes: - ./config.yaml:/CLIProxyAPI/config.yaml - ./auth:/root/.cli-proxy-api networks: - openclaw_net networks: openclaw_net: external: true EOF ``` ⚠️ **ВАЖНО:** Нужно узнать имя docker network где живёт OpenClaw контейнер. Проверить: ```bash docker network ls docker inspect --format '{{range .NetworkSettings.Networks}}{{.NetworkID}}{{end}}' ``` Заменить `openclaw_net` на реальное имя сети. - [ ] **1.3** Проверить что image скачивается: ```bash cd /home/slin/claude-cli-proxy docker compose pull ``` **Критерий:** Файлы на месте, image скачан. --- ### Task 2: Первый запуск и OAuth авторизация **Шаги:** - [ ] **2.1** Запустить контейнер в режиме логина (одноразово): ```bash cd /home/slin/claude-cli-proxy docker run --rm -it \ -p 54545:54545 \ -v $(pwd)/config.yaml:/CLIProxyAPI/config.yaml \ -v $(pwd)/auth:/root/.cli-proxy-api \ eceasy/cli-proxy-api:latest \ /CLIProxyAPI/CLIProxyAPI --claude-login --no-browser ``` Это выведет URL для авторизации. **Этот URL нужно передать Славе** — он откроет его в браузере и залогинится. ⚠️ Флаг `--no-browser` обязателен (headless сервер, нет GUI). - [ ] **2.2** После успешного логина — проверить что токен сохранился: ```bash ls -la /home/slin/claude-cli-proxy/auth/ # Должен быть файл с OAuth credentials ``` **Критерий:** OAuth токен сохранён в `./auth/`. --- ### Task 3: Запуск сервиса **Шаги:** - [ ] **3.1** Запустить через docker-compose: ```bash cd /home/slin/claude-cli-proxy docker compose up -d ``` - [ ] **3.2** Проверить что контейнер работает: ```bash docker ps | grep claude-cli-proxy docker logs claude-cli-proxy --tail 20 ``` - [ ] **3.3** Проверить API: ```bash # Список моделей curl -s http://127.0.0.1:8317/v1/models | python3 -m json.tool # Тестовый запрос curl -s -X POST http://127.0.0.1:8317/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer dummy" \ -d '{ "model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "Say hello, one sentence only"}], "stream": false }' | python3 -m json.tool ``` - [ ] **3.4** Проверить streaming: ```bash curl -s -X POST http://127.0.0.1:8317/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer dummy" \ -d '{ "model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "Count from 1 to 5"}], "stream": true }' # Должен выдавать SSE chunks ``` **Критерий:** API отвечает, streaming работает. --- ### Task 4: Подключение к docker network OpenClaw **Шаги:** - [ ] **4.1** Определить сеть OpenClaw: ```bash # Найти контейнер OpenClaw docker ps | grep -i openclaw # Посмотреть его сеть docker inspect --format '{{json .NetworkSettings.Networks}}' | python3 -m json.tool ``` - [ ] **4.2** Обновить docker-compose.yml с правильным именем сети (если отличается от `openclaw_net`) - [ ] **4.3** Проверить что OpenClaw контейнер видит прокси: ```bash # Из контейнера OpenClaw docker exec curl -s http://claude-cli-proxy:8317/v1/models ``` **Критерий:** OpenClaw контейнер может достучаться до `claude-cli-proxy:8317`. --- ## Проверка (Acceptance) | # | Проверка | Команда | Ожидаемый результат | |---|----------|---------|---------------------| | 1 | Контейнер запущен | `docker ps \| grep claude-cli-proxy` | STATUS: Up | | 2 | Models endpoint | `curl http://127.0.0.1:8317/v1/models` | JSON с claude моделями | | 3 | Chat completion | `curl POST /v1/chat/completions` | Ответ от Claude | | 4 | Streaming | `curl POST stream=true` | SSE chunks | | 5 | Доступ из OpenClaw | `docker exec openclaw curl ...` | Ответ от прокси | --- ## Ограничения и грабли - ⚠️ SSH только через Node.js ssh2 (бинарный ssh сломан в контейнере OpenClaw) - ⚠️ OAuth логин — **ручной шаг**, нужен браузер Славы. Dev готовит URL, Слава логинится. - ⚠️ `--no-browser` обязателен при логине (headless сервер) - ⚠️ `auth.providers: []` в config — без этого будет требовать API key - ⚠️ Порт 8317 слушает только на 127.0.0.1 (не наружу!) - ⚠️ Имя docker network нужно определить динамически — не хардкодить - 🚫 НЕ открывать порт наружу - 🚫 НЕ запускать несколько инстансов (риск бана) --- ## После деплоя (делает Стрим, не Dev) После успешного Task 4 — Стрим добавит provider в OpenClaw config: ```json { "id": "claude-cli-proxy", "type": "openai", "baseUrl": "http://claude-cli-proxy:8317/v1", "apiKey": "dummy", "models": ["claude-sonnet-4-20250514", "claude-opus-4-20250514"] } ``` И назначит Dev-агенту модель через этот provider. --- ## Деплой-чеклист - [ ] Директория и файлы созданы - [ ] Docker image скачан - [ ] OAuth авторизация пройдена (ручной шаг Славы) - [ ] Контейнер запущен и отвечает - [ ] Streaming работает - [ ] Доступен из docker network OpenClaw - [ ] Порт НЕ открыт наружу --- *Создано: 2026-05-14 | Автор ТЗ: Стрим | Исполнитель: Dev-агент*