diff --git a/.wiki/concepts/mappa-vds-deploy-runbook.md b/.wiki/concepts/mappa-vds-deploy-runbook.md new file mode 100644 index 0000000..a4ffdd9 --- /dev/null +++ b/.wiki/concepts/mappa-vds-deploy-runbook.md @@ -0,0 +1,87 @@ +--- +title: mappa — VDS deploy runbook (БД / образ / Portainer-стек 26 / редеплой / verify) +type: concept +tags: [mappa, vds, deploy, docker, portainer, traefik, postgres, runbook, meta] +related: [[../entities/vds-kzntsv]], [[portainer-stack-management-vds]], [[mappa-prod-infra]] +updated: 2026-08-23 +--- + +# mappa → VDS deploy runbook + +Развёртывание **mappa** (единый meta-сервис цеха: HTTP-ядро + MCP-адаптер, Postgres) +на [[../entities/vds-kzntsv]] (89.253.255.94) рядом с общей БД (решения 1/17/18 спеки +`concepts/mappa`). Первый деплой — 2026-08-23 (#1012, закрыта). + +**Разделение труда (директива 2026-08-23):** деплой/редеплой = АДМИН (таска + письмо); +прод-импорт, verify счётчиков, read-only+фолбэк, ntfy-алерт, артефакты, MCP-регистрация = +mappa (#985). Не делать чужую часть. + +## Артефакты + +- **Код:** `OpeItcLoc03/mappa` @ master. Сборка TS: `npm ci && npm run build` → `dist/`. +- **Образ:** `registry.kzntsv.site/mappa:0.1.0`. Dockerfile в корне репо (multi-stage node:22-alpine; + **обязательный COPY `src/lib/schema.sql` → `dist/src/lib/schema.sql`** — tsc не копирует .sql, + без него migrate() падает «schema.sql not found»). +- **Стек Portainer:** `mappa` (Id 26, endpoint 1). Source-of-truth compose: + `admin/host-stacks/vds-kzntsv/mappa.compose.yml`. +- **БД:** база `mappa` + role `mappa` на общем `postgres:16` VDS (owner = mappa). + Креды: **`pass show mappa/full-env`** (`MAPPA_DB_PASS`, `DATABASE_URL` docker-сетевой: + `postgres://mappa:…@postgres:5432/mappa`; внешний host `postgres.vds.kzntsv.site:5432` — TLS-verify-skip). +- **Endpoint:** `https://mappa.vds.kzntsv.site` (traefik websecure, letsEncrypt, service-port 8731). + +## Реденплой (обновление образа) — быстрый путь + +```bash +# 1. Собрать и запушить новый тег образа (с воркстейшена, Docker Desktop) +cd ~/projects/mappa +docker build -t registry.kzntsv.site/mappa: . +docker push registry.kzntsv.site/mappa: + +# 2. НА VDS: docker pull ДО restart стека (иначе застрянет на старом digest!) +ssh vds.kzntsv.site 'docker pull registry.kzntsv.site/mappa:' + +# 3. Поменять image: в host-stacks/vds-kzntsv/mappa.compose.yml И в Portainer stack 26 +# (обе копии синхронизировать — иначе следующий redeploy из гита откатит тег) + +# 4. Restart стека через Portainer API (НЕ ad-hoc docker compose up!) +# JWT: pass vds-kzntsv/full-env PORTAINER_ADMIN_PASS → POST /api/auth +curl -ksS -X POST "https://portainer.vds.kzntsv.site/api/stacks/26/restart?endpointId=1" \ + -H "Authorization: Bearer $JWT" + +# 5. Verify +curl -ksS https://mappa.vds.kzntsv.site/health # {"ok":true,"service":"mappa"} +curl -ksS https://mappa.vds.kzntsv.site/admin/status # entities/by_type/projects +curl -ksS https://mappa.vds.kzntsv.site/graph/stats # nodes/edges/components +ssh vds.kzntsv.site 'docker ps --filter name=mappa --format "{{.Status}}"' +``` + +## Обновление env (пароль БД и т.п.) + +Через Portainer → Stack 26 → Edit (env array), НЕ файлом на VDS (Portainer string-mode не +материализует .env; env передаётся API-массивом — gotcha 1 `portainer-stack-management-vds`). +`MAPPA_DB_PASS` — единственный env в стеке. + +## Первичный деплой с нуля (cold start) + +1. **БД**: на VDS `docker exec postgres psql -U postgres`: + `CREATE ROLE mappa LOGIN PASSWORD ''; CREATE DATABASE mappa OWNER mappa;` + Пароль → `pass insert -m mappa/full-env`. +2. **Образ**: собрать (см. выше), `docker push`. +3. **Compose**: `admin/host-stacks/vds-kzntsv/mappa.compose.yml` → Portainer create + (standalone string-mode, endpointId=1, env `[{"name":"MAPPA_DB_PASS","value":…}]`). +4. **Проверка миграций**: при старте migrate() сам создаёт таблицы (6 шт: projects/counters/ + entities/edges/leases/logs, owner=mappa) — `docker logs mappa` + `\dt` в БД. +5. **Пинг mappa**: письмо в `mappa/.agents/inbox/` (event: mappa-deployed) — импорт и остальное за ними. + +## Gotchas (из первых деплоев) + +1. **schema.sql в dist** — tsc компилирует только .ts; `migrate()` ищет `.sql` рядом с + `dist/src/lib/`. Без COPY в Dockerfile → контейнер в restart-loop («schema.sql not found»). +2. **docker pull до restart** — Portainer start/stop НЕ тянет новый digest сам по себе; + перезалитый `:0.1.0` без pull на VDS = старый образ (ловил 2× за сессию 2026-08-23). +3. **Не ad-hoc compose** — все стеки VDS через Portainer (VDS ops rule). `docker rm -f` + вручную снёс контейнер — Portainer recreate поднял, но это не путь. +4. **mem_limit 512m** — канон app-стеков, не убирать (cgroup-лимит vs вся память хоста). +5. **Внешний DATABASE_URL** — контейнерный `@postgres:5432` валиден только внутри docker-сети; + для импорта с воркстейшена — `postgres.vds.kzntsv.site:5432` (+ TLS-verify-skip, self-signed). +6. **Закрытие деплоя** — всегда пара «таска + письмо mappa» (канон `mappa-deploy-workflow`). diff --git a/.wiki/index.md b/.wiki/index.md index f776078..0bf0e56 100644 --- a/.wiki/index.md +++ b/.wiki/index.md @@ -22,6 +22,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever ## Concepts - [sched-runtime-to-file-managed-migration](concepts/sched-runtime-to-file-managed-migration.md) — перевод sched slovo+bookva на file-managed (durable config, #991): почему runtime хрупкий (расписания в памяти демона, сироты без data), рецепт миграции (файл in-place → live-sync НЕ конвертирует runtime → DELETE /tasks+/schedules → verify), gotchas (id=taskName vs UUID, ghost-таски, task-runner config кэш→рестарт, SMTP from==auth, URL-encode) +- [mappa-vds-deploy-runbook](concepts/mappa-vds-deploy-runbook.md) — деплой/редеплой mappa на VDS (стек 26, образ registry.kzntsv.site/mappa): БД+role на общем postgres:16 (pass mappa/full-env), сборка образа (schema.sql в dist!), Portainer-реденплой (docker pull до restart), env через Portainer, gotchas - [sched-ozon-creds-stub-contract](concepts/sched-ozon-creds-stub-contract.md) — контракт кредов Ozon slovo/bookva: мисматч-пары (client_id ↔ чужой ключ) — НАМЕРЕННЫЕ заглушки (анти-утечка после tenant-split), матрица 4 sellers, безопасность через break-on-error (2a38fb5), verify по SHA2, НЕ «чинить» - [omniroute-combo-deepseek-web-tuning](concepts/omniroute-combo-deepseek-web-tuning.md) — настройка web-комбо под агента: system_message убивает скилы pi, tool_filter_regex режет тулы, search-режим ломает tool-calling, 503 chat_admission_busy, эмуляция `` работает, план кастомного провайдера, qwen-web baxia-WAF стена - [forgetmeai-free-web-chat-proxies](concepts/forgetmeai-free-web-chat-proxies.md) — семейство бесплатных web-chat прокси ForgetMeAI (DeepSeek/Qwen/GLM/Kimi): паттерн «обход капчи через реальную браузерную сессию», PoW-солвер DeepSeek, браузерный путь через baxia-WAF (fetch в page.evaluate), CloakBrowser, классификаторы капчи; карта «что берём в lwp» diff --git a/.wiki/log.md b/.wiki/log.md index 403fc6a..1bfb5c9 100644 --- a/.wiki/log.md +++ b/.wiki/log.md @@ -1,3 +1,5 @@ +## [2026-08-23] ingest | NEW concepts/mappa-vds-deploy-runbook.md — ранбук деплоя/редеплоя mappa на VDS (стек 26, образ registry.kzntsv.site/mappa:0.1.0, БД на общем postgres:16, endpoint mappa.vds.kzntsv.site). #1012 закрыта; грабли: schema.sql в dist при tsc-сборке, docker pull до Portainer restart, не-ad-hoc compose, внешний DATABASE_URL для импорта. index.md updated (+1). + ## [2026-08-19] ingest | NEW concepts/sched-fnf-testing-method.md — метод F&F-тестирования (урок r10): тест по скомпилированной доке (dev-сервер localhost:5108), порядок хендоффа 1–6, битый пример = возврат, schedjs.com заглушка. index.md updated (+1). ## [2026-08-16] ingest | concepts/pilonuxt-restart-vs-redeploy-2026-08-16.md — день деплоев стека 16 (7 операций): рестарт vs пересборка разведены как отдельные операции. Рестарт сбрасывает in-memory viewModel кэш content-api (цена за м³ подтянулась после рестарта без пересборки); пересборка — только для кода. Анти-симптом: 500 на категориях с логом `@snolla/core viewModels/index.js:419 _.find(x=>x.name)` = код/данные (Content object vs array, admin-api create), рестарт не лечит — фикс snolla core 0.26.7 + admin-api 0.11.0 array-canon (1128ddc → 64c2539). Откат-цепочка образов 64c2539→…→8b7e8c4. +index.md. Монорепа-сторона заингестена прогером (lazy-data-not-found-404, admin-api-content-wire array-canon, cms-edits-cache-restart, v-html-on-component-ssr, admin-api-content-edit). ## [2026-08-14] decision | FormSubmissions.Content ₽→«?» — координация закрыта. ALTER на клиентской stostayer сделан (.admin); snolla опубликовала `@snolla/data@0.15.1` (STRING→TEXT=NVARCHAR(MAX), тесты 7/7); скан живых БД VDS: MoreThenCms+Staging уже nvarchar (ALTER не нужен), VDS-stostayer varchar — не прод, не трогаем (роль — к оператору); legacy stostayer.web на @snollajs 0.7.x — фикс не едет, ALTER покрывает (backport опция `065bb44`); формы есть у всех сайтов тиража (pilorama98 2516/labtools 916 — вопреки гипотезе snolla). Бонус: email-контракт задокументирован snolla (forms-email-contract.md), warn при пустом `to` — ждёт решения vitya. Таска snolla [formsubmissions-content-nvarchar] закрыта.