Files
orchestrator/docs/operations/REPLICATION.md

13 KiB
Raw Blame History

REPLICATION — тираж платформы на новую инфраструктуру (ORCH-101)

RUNBOOK фундамента тиража (эпик ORCH-10, слой 10-common). Как развернуть оркестратор на чужом хосте без правки кода: переменные → секреты → smoke. Тираж stateless: данные/БД/секреты боевого хоста НЕ переносятся ни на одном шаге — на целевой инфре всё создаётся заново.


1. Границы: 10-common vs Lite vs Bundled

Слой Что это Статус
10-common (этот док) фундамент: все хост-значения параметризованы (env/конфиг), секреты выпускаются заново, smoke-процедура с PASS/FAIL ORCH-101
Type A — Lite инструкция «поставь Plane+Gitea сам, подключи оркестратор» поверх 10-common ORCH-102 — docs/deployment/LITE_SETUP.md
Type B — Bundled комплект «всё в одном» (Plane+Gitea+оркестратор) поверх 10-common ORCH-103 — docs/deployment/BUNDLED_SETUP.md

Этот док НЕ описывает установку Plane/Gitea — только параметризацию, секреты и smoke самого оркестратора (анти-скоуп-крип Р-5).

Платформенные конвенции тиража (нормативно, ADR-001 D3/D4)

  • Репо платформы обязан называться orchestrator. Имя — узел безопасности (SELF_HOSTING_REPO, на него завязаны все *_repos-leaf'ы «empty CSV → self-hosting only»); оно сознательно НЕ конфигурируется.
  • Имена compose-сервисов/профиля (orchestrator, orchestrator-staging, orchestrator-watchdog, профиль staging) — константы платформы.
  • Контейнерные пути (/app/data, /repos, /opt/claude-code) — layout контейнера, не хост-значения; не параметризуются.

2. Карта переменных нового хоста

Принцип (ADR-001 D1): дефолт каждой переменной = боевое значение текущего хоста — пустой .env ⇒ поведение байт-в-байт; на новом хосте задаёшь только то, что отличается. Одно env-имя = один факт: pydantic Settings читает имя из env_file, compose-интерполяция ${VAR:-default} — из .env проекта/shell (⚠️ НЕ из env_file сервиса: .env.staging на интерполяцию не влияет — значения для маунтов/uid/портов живут в .env).

2.1. Хост-параметризация (новое в ORCH-101)

Переменная Дефолт Назначение
ORCH_AGENT_HOME_DIR /home/slin HOME всех акторов (агенты, finalizer, monitor) + таргет маунтов .claude/.claude.json/.ssh + ARG APP_HOME (группа ORCH-040 двигается вместе)
ORCH_AGENT_GIT_NAME claude-bot git-имя коммитов агентов
ORCH_GIT_EMAIL_DOMAIN mva154.local домен git-email всех акторов (claude-bot@…, deploy-finalizer@…, post-deploy-monitor@…)
ORCH_STAGING_PORT 8501 порт staging; читают image_freshness И compose command:; guard: совпадение с прод-портом → отказ fail-closed (ORCH-058 AC-9)
ORCH_HOST_REPOS_DIR /home/slin/repos каталог репозиториев на хосте (источник маунта /repos)
ORCH_HOST_CLAUDE_DIR /home/slin/.claude источник маунта ~/.claude
ORCH_HOST_CLAUDE_JSON /home/slin/.claude.json источник маунта ~/.claude.json
ORCH_HOST_SSH_DIR /home/slin/.orchestrator-ssh источник маунта ssh-ключей (→ $HOME/.ssh:ro)
ORCH_HOST_CLAUDE_CODE_DIR /usr/lib/node_modules/@anthropic-ai/claude-code дистрибутив claude-code на хосте
ORCH_HOST_NODE_BIN /usr/bin/node бинарь node на хосте
ORCH_RUN_UID / ORCH_RUN_GID 1000 / 1000 uid:gid контейнера (user: + ARG APP_UID/APP_GID); = uid владельца ORCH_HOST_REPOS_DIR (ORCH-040)
ORCH_DOCKER_GID 999 gid группы docker хоста (group_add, «МИНА 1» — обязателен для docker.sock); узнать: getent group docker
ORCH_DEPLOY_PROD_TARGET_PORT 8500 (реюз) прод-порт; интерполируется в command: прод-сервиса
ORCH_DEPLOY_SSH_USER / ORCH_DEPLOY_HOST_REPO_PATH slin / /home/slin/repos/orchestrator (реюз) ssh-юзер хука и чекаут платформы на хосте; REPO= передаётся хуку явно из конфига

2.2. Обязательные ключи идентичности нового хоста

Переменная Где взять
ORCH_PLANE_API_URL / ORCH_PLANE_WEB_URL / ORCH_PLANE_WORKSPACE_SLUG инсталляция Plane целевого хоста
ORCH_GITEA_URL / ORCH_GITEA_PUBLIC_URL / ORCH_GITEA_OWNER инсталляция Gitea целевого хоста
ORCH_PROJECTS_JSON обязателен на новом хосте: встроенный fallback (src/projects.py) несёт Plane-UUID исходного хоста — чужие UUID безвредны (не сматчатся), но без своего реестра конвейер не увидит проекты. Сгенерировать: scripts/onboard_project.py apply печатает merged-значение
Когерентность портов сменил прод-порт → синхронно ORCH_DEPLOY_PROD_TARGET_PORTWATCHDOG_METRICS_URLORCH_POST_DEPLOY_BASE_URL

Полный справочник всех остальных флагов — .env.example (канон) и docs/operations/INFRA.md (карта env).


3. Секреты нового хоста (FR-4 / AC-5)

Нормативно: боевые секреты текущего хоста НЕ копируются ни на одном шаге. Для нового хоста всегда выпускается новый комплект.

3.1. Генерация локальных webhook-секретов

python3 scripts/gen_secrets.py            # печать .env-фрагмента в stdout
python3 scripts/gen_secrets.py --write    # создать .env (существующий → отказ exit=2)
python3 scripts/gen_secrets.py --write --force  # перезапись только явно

Скрипт stdlib-only (secrets.token_hex(32) — 32 байта энтропии); повторный запуск даёт другие значения; существующий .env никогда не перезаписывается молча.

Секрет Генерируется Куда вписать
ORCH_PLANE_WEBHOOK_SECRET локально (gen_secrets) .env + настройка webhook в Plane (см. SETUP_WEBHOOKS.md)
ORCH_GITEA_WEBHOOK_SECRET локально (gen_secrets) .env + webhook Gitea (создаёт onboard_project.py apply)

3.2. Чек-лист внешних токенов

Секрет Где выпустить Куда вписать Как проверить
ORCH_PLANE_API_TOKEN Plane UI → Workspace Settings → API tokens .env curl -H "X-API-Key: $TOKEN" $ORCH_PLANE_API_URL/api/v1/workspaces/<slug>/projects/ → 200
ORCH_PLANE_BOT_* (7, опциональны) Plane UI: bot-аккаунты per-агент; пусто → fallback на ORCH_PLANE_API_TOKEN .env комментарий в Plane от имени бота
ORCH_GITEA_TOKEN Gitea UI → Settings → Applications → Generate Token (scope: repo, admin:repo_hook) .env curl -H "Authorization: token $TOKEN" $ORCH_GITEA_URL/api/v1/user → 200
ORCH_TELEGRAM_BOT_TOKEN BotFather (/newbot) .env curl https://api.telegram.org/bot$TOKEN/getMe → ok
ORCH_TELEGRAM_CHAT_ID (несекретный) id чата оператора .env тестовое сообщение
WATCHDOG_TG_BOT_TOKEN / WATCHDOG_TG_CHAT_ID отдельный бот sidecar-watchdog (ORCH-100, независимый канал) .env.watchdog алерт от sidecar

3.3. Полнота

.env.example — канон 100% ключей старта (секретные значения — только плейсхолдеры). Состав вывода gen_secrets.py сверяется с .env.example тестом (tests/test_secrets_gen.py).


4. Smoke-верификация тиража (FR-5 / AC-3)

Процедура «инстанс → тестовый проект → тестовая задача → конвейер доехал» из существующих кирпичей; каждый шаг имеет явный PASS/FAIL. Итог — однозначный вердикт: все шаги PASS ⇒ тираж PASS; любой шаг FAIL ⇒ тираж FAIL (собери логи контейнера docker logs orchestrator и снапшот GET /queue и разбирайся).

Воспроизводимость без нового железа: процедура прогоняется на текущей инфре — staging-песочница (порт ORCH_STAGING_PORT, дефолт 8501) + sandbox-проект. Stateless: ни один шаг не предполагает перенос данных/БД/секретов.

# Шаг Команда PASS FAIL
0 Конфиг резолвится docker compose config резолв без ошибок; при пустом env значения = боевым дефолтам ошибка интерполяции / неожиданные значения
1 Инстанс жив curl -fsS http://127.0.0.1:<port>/health HTTP 200, "status":"ok" не-200 / таймаут
2 Контракты отвечают curl -fsS …/queue и …/metrics JSON со штатными блоками; /metricsschema_version: 1 не-JSON / 5xx
3 Тестовый проект python3 scripts/onboard_project.py planapplyverify (sandbox) verify зелёный (статусы/лейблы/repo/webhook на месте) verify красный / manual-step не выполнен
4 Тестовая задача создать issue в Plane → статус «To Analyse» задача в БД, analyst-job виден в GET /queue задача не появилась (webhook/секрет/реестр)
5 Минимальный сигнал «конвейер доехал» дождаться окончания analysis артефакты 0104 в ветке задачи: git ls-tree origin/<branch> docs/work-items/<id>/ стадия не завершилась / артефактов нет
6 Расширенный режим (опционально) Approved → … → Confirm Deploy задача дошла до done застряла (разбор по GET /queue + логам)

Ручной запуск deploy-хука на нестандартных портах — всегда с явными REPO=/TARGET_PORT= (wired-путь оркестратора передаёт их сам из конфига; дефолты хука — staging текущего хоста).


5. Что НЕ переносится (stateless, решение 10.06)

  • БД (data/orchestrator.db) — создаётся пустой при первом старте;
  • .env / .env.staging / .env.watchdog — собираются заново (§2§3);
  • worktree'ы/runs/логи — рабочее состояние, не данные;
  • боевые секреты — никогда (§3).

RUNBOOK ORCH-101. Поддерживать при добавлении хост-переменных (карта §2 + .env.example + INFRA.md в том же PR). Анти-регресс возврата хардкодов — tests/test_no_host_hardcodes.py; параметризация инфра-файлов — tests/test_infra_parametrization.py.