docs(wiki): mappa-vds-deploy-runbook — деплой/редеплой mappa на VDS (стек 26)

This commit is contained in:
2026-08-23 18:51:59 +03:00
parent bb5483dc7c
commit e3de639161
3 changed files with 90 additions and 0 deletions

View File

@@ -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:<tag> .
docker push registry.kzntsv.site/mappa:<tag>
# 2. НА VDS: docker pull ДО restart стека (иначе застрянет на старом digest!)
ssh vds.kzntsv.site 'docker pull registry.kzntsv.site/mappa:<tag>'
# 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 '<pw>'; 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`).

View File

@@ -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, эмуляция `<tool>` работает, план кастомного провайдера, 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»

View File

@@ -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), порядок хендоффа 16, битый пример = возврат, 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] закрыта.