Compare commits

...

2 Commits

Author SHA1 Message Date
d4278e79f9 meta(handoff): write NEXT_SESSION — snolla local admin + on-snolla design
Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-20 09:45:32 +03:00
b1b0092cdc design(snolla): local .NET admin restore + on.snolla.com VDS migration
Two linked tasks, spec in .wiki/concepts/ per project-discipline.

Task A — snolla-local-admin-restore: восстановить локальный catch-all IIS-сайт
`snolla` (снесён 2026-06-08) копированием C:\sites\snolla\ с RUVDS (прод-админ
с MinIO drop-in), conn → mssql.kzntsv.site MoreThenCms. Доступ
<alias>.snolla.com/admin через hosts-override, один AppPool. Адреса + siteIds
извлечены из MoreThenCms DB read-only.

Task B — on-snolla-vds-migration (blocked by A): on.snolla.com (siteId
B9ECDB50…, alias on, "Internal Site", culture en) с RUVDS IIS → VDS Node
snolla-app 0.42.1, реконструкция Liquid-шаблонов из боевого сайта+админки
(исходников нет). По рецепту tandemmebel-vds-deploy-runbook.

Board entries: .tasks/STATUS.md + per-task files.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-20 09:45:06 +03:00
5 changed files with 205 additions and 52 deletions

View File

@@ -1,73 +1,65 @@
---
_last_updated_: 2026-07-13T19:50:00Z
session_id: 2026-07-13-tandemmebel-8df10ee-deploy
prev_session_id: 2026-07-13-stostayer-loader-deploy
_last_updated_: 2026-07-20T07:00:00Z
session_id: 2026-07-20-snolla-local-admin-on-snolla-design
prev_session_id: 2026-07-13-tandemmebel-8df10ee-deploy
---
# Next session handoff
## Эта сессия — tandemmebel 8df10ee deploy (DONE, прод живой)
## Эта сессия — design: SNOLLA local admin restore + on.snolla.com → VDS
🟢 **[tandemmebel-deploy-drop-fb-tw-gplus-buttons] ЗАКРЫТА.** In-place template bump
`0cd9351 → 8df10ee` на проде (стек 20), убраны FB/Twitter/Google+ share-кнопки
(экстремистистская символика РФ), оставлены ВК+Одноклассники. Template-only
(`apps/web/views/social_buttons.liquid`, 1 file 12 delet), snolla 0.42.1 НЕ менялся.
Спека написана и закоммичена: `.wiki/concepts/snolla-local-admin-and-on-snolla-migration-design.md`
(commit `b1b0092c`). Две таски заведены в `.tasks/` + board-entries в STATUS.md.
- **Верификация поймала расхождение:** tandemmebel-записка утверждала live=`ed96b18`/0.42.0,
фактически `0cd9351`/0.42.1. gitea `compare/0cd9351...8df10ee`=`total_commits:1` → фикс на
правильной 0.42.1 базе, yarn.lock идентичен → регрессии sitemap нет.
- Build на VDS (чистый gitea-архив 8df10ee, build-arg VERDACCIO_TOKEN=books-ci JWT), digest
`sha256:30a7e5ab82f2bf371042f1b5fa0cd7ac5ceda71379d1da59e148dee8166bd560`.
- Completeness-gate: sitemap NEW==PROD **184=184 identical**, 0 регрессий. Live-smoke 4
share-block страницы → vk+ok / fb-tw-gp=0. TLS-серт не дёрнут.
- Swap через Portainer JWT (API-key `ptr_*` даёт 401 → workaround JWT), env 8/8 preserve,
`prune:false, pullImage:true`. Tandemmebel-сессия подтвердила, discrepancy-урок усвоен.
- **Records:** STATUS.md _Updated 2026-07-13; runbook секция In-place bump 8df10ee
(`.wiki/concepts/tandemmebel-vds-deploy-runbook.md`); compose source-of-truth
`host-stacks/vds-kzntsv/tandemmebel.compose.yml` = 8df10ee. Коммиты `632c843f` (records)
+ `fe8e5882` (tasks_close).
- **Откат:** PUT стека 20 → `0cd9351` (0.42.1, {% order %} fix) / `ed96b18` (0.42.0, в registry,
стёрт с VDS при disk-cleanup 2026-07-13 — `pullImage:true` дотянет) / `b02ca18`; ИЛИ revert
DNS→80.64.31.36 (RUVDS IIS жив).
**Task A — snolla-local-admin-restore** (⚪ ready):
Восстановить локальный catch-all IIS-сайт `snolla` (снесён 2026-06-08 при decommission
windows-recovery-host) копированием `C:\sites\snolla\` с RUVDS (текущий прод-админ с уже
применённым MinIO drop-in). Conn → `mssql.kzntsv.site:1433` Catalog=MoreThenCms. Доступ
`<alias>.snolla.com/admin` через hosts-override, **один AppPool**, binding `*:80` + FW block
inbound. Развилка адресации confirmed оператором (catch-all+hosts, не per-port).
### Loose end (low priority, НЕ блокер)
- **Portainer stack 20 file — устаревшие STAGING-комменты** (строки 16-17 «Домен: STAGING»,
53 «STAGING-RULE. Cutover: после flip DNS сменить на Host(...)»). Сама `traefik...rule`
(строка 55) уже LIVE, совпадает с label'ом контейнера — функционально нейтрально. При
деплое 8df10ee обновлён только image-line коммент. При следующем full-sync выровнять
Portainer file под git source-of-truth (косметика).
**Task B — on-snolla-vds-migration** (⚪ ready, blocked by A):
on.snolla.com (siteId `B9ECDB50-2B93-4CE5-B238-A9918B3F9CF7`, alias `on`, Title "Internal Site",
culture `en`) с RUVDS IIS → VDS Node snolla-app 0.42.1. Исходников нет → реконструкция
Liquid-шаблонов из боевого `https://on.snolla.com/` + локального админа (Task A). По рецепту
`tandemmebel-vds-deploy-runbook` (cutover) + `snolla-live-prod-inplace-image-bump` (gate).
### Addresses + siteIds (из MoreThenCms DB, read-only tedious-проб, SA из `pass mssql-vds/sa-password`)
Скрипт `.tmp/dbprobe-sites.mjs` (gitignored). Адреса = `<Alias>.snolla.com/admin`:
- tandemmebel.snolla.com (tandemmebel.ru, 78080707-F6E0-4330-BA30-7922354C2CEF)
- labtools.snolla.com (labtools.ru, D375C419-D787-4FCC-8934-A3B9DC951006)
- labtoolspro.snolla.com (labtools.pro, 663F9410-A6CC-4651-9A5C-62844A313957)
- emspb.snolla.com (emspb.ru, 96EBC481-D26A-47BE-B660-13D49E7D0A61)
- kupimknigi.snolla.com (kupimknigi.spb.ru, E924A354-0377-4E1E-80C6-2EB0194AA55F)
- on.snolla.com (on.snolla.com, B9ECDB50-2B93-4CE5-B238-A9918B3F9CF7)
## Recent commits
- fe8e5882 meta(tasks): close [tandemmebel-deploy-drop-fb-tw-gplus-buttons] in OpeItcLoc03/admin
- 632c843f deploy(tandemmebel): 8df10ee LIVE — drop FB/Twitter/Google+ share buttons
- 94e5d77c meta(tasks): create [tandemmebel-deploy-drop-fb-tw-gplus-buttons] in OpeItcLoc03/admin
- 7e02d611 docs(wiki): vds-kzntsv disk cleanup 94%→74% + container-log rotation guard
- 8230f891 / 2e180029 meta(tasks): vehicles-loader-redeploy-per-group-rate-diff (create + update)
- 135da254 chore: gitignore .zcode/
- b1b0092c design(snolla): local .NET admin restore + on.snolla.com VDS migration
- a02c4b86 wiki: ingest de-vds-3xui source chronicle + gitignore .tmp/.tasks/.lock
- 543ded79 wiki: de-vds-3xui real RF-client confirmed
## Open треки
| Трек | Готовность | Entry-point |
|---|---|---|
| vehicles-loader 0.4.1 runtime verify | 🔴 active — deployed, verify pending | После **07-14 06:21 MSK**: SSH `new.stostayer.ru:20435` (victor, креды `pass stostayer/client`), проверить новый `importRun` `status=ok` + `counts.serviceGenerationRate={replaced:<сотни>, skipped:<~41k>}`, `serviceModificationRate={replaced:<сотни>, skipped:<~5k>}`, `duration < ~93 мин`. Если `replaced` ~44k/6.7k — образ из старого кода (но code-verify уже GREEN: rateDiff.js/replaceGroup.js в образе есть). Откат: `docker tag docker.stostayer.ru/vehicles-loader:0.4.0 vehicles-loader:latest`. User сказал «завтра посмотрим вместе». |
| books-vds → vds-kzntsv консолидация | оценено, НЕ хватает ресурсов | RAM: .94 free 1.7 GiB (swap=0) vs books 23+ GiB (на .133 уходит 3.3 GiB в swap). Диск: .94 было 11 GiB free (94%), после чистки 39 GiB; books тащит ~1520 GiB. CPU хватает (6 ядер idle). Решение за user. |
| ntfy push.kzntsv.site cert-pinning | починено на телефоне (pin убран) | Повтор при каждом LE-renewal ~90д, если pin снова включат. Сервер НЕ трогать. |
| snolla-local-admin-restore (Task A) | ⚪ ready — ждёт SSH RUVDS verify + DB-креды | `.tasks/snolla-local-admin-restore.md`; spec §Task A. Шаг 0: read-only SSH RUVDS (`pass show ruvds-iis/full-env`) — проверить C:\sites\snolla\ + MinIO drop-in в Web.config. |
| on-snolla-vds-migration (Task B) | ⚪ ready, blocked by A | `.tasks/on-snolla-vds-migration.md`; spec §Task B. |
| vehicles-loader 0.4.1 runtime verify | 🔴 active — deployed, verify pending (просрочено с 07-14) | SSH `new.stostayer.ru:20435` (victor, `pass stostayer/client`), проверить importRun status=ok + counts. Откат: `docker tag .../vehicles-loader:0.4.0 vehicles-loader:latest`. |
| books-vds → vds-kzntsv консолидация | оценено, НЕ хватает ресурсов | RAM/disk на .94 не лезет. Решение за user. |
## Спроси user'а
- **books-vds консолидация**: свежий Ubuntu-VDS под books, апгрейд тарифа .94 (Rusonyx: +RAM/+disk), или оставить на EOL CentOS 7 (.133)? Оценка этой сессии — на .94 не лезет (RAM+диск).
- **Durable build-fix в stostayer.new** (cross-project): `packages/vehicles-loader/Dockerfile` — добавить `ENV VERDACCIO_TOKEN=unused` в deps-стейдж (сеть off → токен не нужен) + закоммитить root `.dockerignore`. Сейчас build ломается на unresolved `${VERDACCIO_TOKEN}` (committed в `393b7d3` после Dockerfile) и тащит жирный контекст (node_modules/.worktrees). Делаем коммит в `victor/stostayer.new`?
- **Spec review** — `b1b0092c` / `.wiki/concepts/snolla-local-admin-and-on-snolla-migration-design.md`. Ок? После approve → writing-plans (план в `.tasks/<slug>.md` по дисциплине, не docs/superpowers/).
- **Task A first step:** дать добло на read-only SSH RUVDS (verify source + MinIO state)?
- **Open Q из spec:** (1) имя репо для on.snolla.com (`victor/on-snolla`?); (2) MoreThenCms DB app-аккаунт + путь в `pass` (SA есть `mssql-vds/sa-password`, но админ юзает app-аккаунт — завести/найти?); (3) включать все ~60 сайтов в локальный админ или только тираж(5)+on.snolla.com.
- **books-vds консолидация**: свежий VDS / апгрейд .94 / оставить на EOL CentOS .133?
## Не делать (preemptive guards)
- **НЕ retry-push** в `docker.stostayer.ru` — один push, сбой → стоп + к человеку. Инцидент 2026-06-17: retry-шторм забанил VPN-IP, весь дом→хост :443 лёг.
- **НЕ деплоить vehicles-loader** из кода без rateDiff (`85ca936`). Перед deploy — verify что в образе есть `src/sync/rateDiff.js` (rateSetsEqual) + `src/sync/replaceGroup.js` (replaceRatesForGroups).
- **НЕ чинить ntfy-пин на сервере** — это client-side (телефон). Сервер: cert валиден, ntfy healthy, `/healthz` 200.
- На **vds-kzntsv НЕ netplan** (anti-pattern, outage 2026-05-28).
- **НЕ сжимать** books-стек на .94 — RAM/disk не хватает (оценено этой сессией).
- **pull перед работой** — admin чист (local==origin `7e02d611`); stostayer.new на `b86ed40`. Не забывать pull (user поправлял этой сессией).
- **НЕ SSH-action на RUVDS без добла** — user уже раз отверг tool-call на RUVDS-SSH (хочет явное подтверждение); read-only verify — только после ок.
- **НЕ деплоить vehicles-loader** из кода без rateDiff (`85ca936`). Verify `rateDiff.js`/`replaceGroup.js` в образе.
- **НЕ retry-push** в `docker.stostayer.ru` (бан VPN-IP, инцидент 2026-06-17).
- **НЕ netplan** на vds-kzntsv; **НЕ сжимать** books на .94 (RAM/disk).
- **НЕ ставить URL Rewrite rule** локальному админу (нет traefik → `:port` leak, см. cms-server-port-leak-fix).
- **pull перед работой** — admin на master `b1b0092c` (local, не push'нуто — спросить перед push по Rule 4).
## Memory updates за сессию
- **new**: `ntfy-android-cert-pinning-breaks-on-le-renewal.md` — LE-renewal (~90д) ломает pinned ntfy-клиент («fingerprint mismatch / connection lost»); фикс на телефоне (re-pin или отключить pinning → system CA), сервер не трогать.
- **wiki**: `entities/vds-kzntsv.md` — Known issues += 2026-07-13 disk cleanup (контейнерные логи 19 GiB, owncloud 13 GiB) + logrotate guard (`/etc/logrotate.d/docker-containers`, copytruncate 200M hourly) + hourly cron; Open issues — GC-cron срочность снижена (94%→74%), container-log rotation DONE.
- (пока не сохранял — если design approved, возможно memory: «SNOLLA admin addressing = <alias>.snolla.com/admin catch-all IIS, siteId из dbo.Sites by alias»; и обновить windows-recovery-host entity — планируется восстановление snolla IIS-сайта локально)

View File

@@ -1,4 +1,5 @@
# Admin Task Board
_Updated: 2026-07-20 — ⚪ **заведены [snolla-local-admin-restore] + [on-snolla-vds-migration].** Design: `.wiki/concepts/snolla-local-admin-and-on-snolla-migration-design.md`. **Task A:** восстановить локальный .NET-админ (catch-all IIS `snolla`, снесён 2026-06-08 при decommission) копированием `C:\sites\snolla\` с RUVDS (текущий прод-админ с MinIO drop-in), conn→`mssql.kzntsv.site:1433` Catalog=MoreThenCms, доступ `<alias>.snolla.com/admin` через hosts-override (1 AppPool, 6 адресов: tandemmebel/labtools/labtoolspro/emspb/kupimknigi/on). **Task B** (blocked by A): мигрировать посадочную on.snolla.com (siteId `B9ECDB50-2B93-4CE5-B238-A9918B3F9CF7`, alias `on`, «Internal Site», culture `en`) с RUVDS IIS на VDS как Node snolla-app 0.42.1, реконструируя Liquid-шаблоны из боевого сайта+админки (исходников нет). Addresses + siteIds извлечены из `MoreThenCms` DB read-only (tedious-проб, SA из `pass mssql-vds/sa-password`, скрипт в `.tmp/dbprobe-sites.mjs` gitignored). Развилка адресации confirmed оператором: catch-all `*:80` + hosts (не per-port)._
_Updated: 2026-07-13 — 🟢 **[tandemmebel-web-vds-deploy] in-place template bump 8df10ee LIVE.** Ops-handoff от tandemmebel-сессии (inbox-запрос): убрать FB/Twitter/Google+ share-кнопки (extremist-icon compliance РФ), оставить ВК+Одноклассники. Коммит `8df10ee` в `victor/tandemmebel.ru` master (template-only, `apps/web/views/social_buttons.liquid`, 1 file 12 deletions, snolla pin 0.42.1 НЕ менялся). **Верификация перед сборкой поймала расхождение:** записка утверждала live=`ed96b18`/0.42.0, фактически на проде крутился `0cd9351`/0.42.1 (in-place bump 2026-07-12). gitea compare `0cd9351...8df10ee` = `total_commits:1` → фикс ровно один коммит поверх 0.42.1 (правильная база), yarn.lock идентичен → регрессии sitemap 184→172 нет. Собрал `tandemmebel:8df10ee` на VDS (чистый архив 8df10ee из gitea API, build-arg VERDACCIO_TOKEN=books-ci JWT, digest `sha256:30a7e5ab82f2bf371042f1b5fa0cd7ac5ceda71379d1da59e148dee8166bd560`, layer-cache hit, push OK). Throwaway-staging :5020 → completeness-gate GREEN: sitemap NEW==PROD **184=184 identical** (0 prod-only/new-only), self-consistency 183×200+1×404(/articles benign parity staging==prod), share-block staging vk+ok/fb-tw-gp=0 vs prod-before vk+ok+fb+tw+gp (доказательство — фикс убирает ровно лишнее). Swap стека 20 (Portainer JWT, PUT `/api/stacks/20?endpointId=1`, env 8/8 preserve, `prune:false`, `pullImage:true`), контейнер healthy ~8s. **Live-smoke С VDS GREEN:** robots/`/`/sitemap 200, /articles 404 parity, sitemap 184 locs, 4 share-block страницы (project-post ×2, /furniture/bedrooms, /furniture/kitchens/classic) все 200 → **vk+ok на месте, fb/tw/gp=0** (экстремистские иконы УБРАНЫ с прода), TLS-серт CN=tandemmebel.ru не дёрнут (in-place swap). `/galleries/` нет на 0.42.1 (sitemap-реструктуризация 0.42.x → gallery рендерится на project-post роуте). Rollback = PUT стека 20 назад на `0cd9351` (0.42.1, {% order %} fix, template-only чистый откат) / `ed96b18` (0.42.0, в registry, стёрт с VDS при disk-cleanup 2026-07-13) / `b02ca18` / revert DNS→80.64.31.36. Source-of-truth compose `host-stacks/vds-kzntsv/tandemmebel.compose.yml` актуализирован (8df10ee + LIVE-комменты + история bump'ов). Hygiene-заметка: Portainer stack 20 file несёт устаревшие STAGING-комменты на строках 16-17/53 (rule line 55 уже LIVE) — косметика, не трогал при деплое. Ответ отправлен в tandemmebel inbox._
_Updated: 2026-07-12 — 🟢 **[tandemmebel-web-vds-deploy] CUTOVER COMPLETE — LIVE на VDS.** Владелец флипанул DNS reg.ru `tandemmebel.ru`+`www`→89.253.255.94 (verify авторит. ns1/ns2.reg.ru = оба 89.253.255.94, не только резолвер). LE-порядок соблюдён: DNS first → traefik `Host()`-rule staging→боевой на стеке 20 (env 8/8 preserve, `prune:false`, `pullImage:false` — образ `ed96b18`/0.42.0 не менялся, без пересборки по решению оператора). LE-серт issued on first hit: CN=tandemmebel.ru, SAN оба, issuer YR2, until 2026-10-10. Live-smoke С VDS GREEN: `/`+`/projects`+3×gallery (office/bedrooms/kids)→200, `/articles`→404 (parity benign#3, так и на RUVDS), sitemap **184 page-locs** (было 172 — рост от blog-archive фичей 0.42.0, benign), self-consistency 30/30 sample (только /articles 404 = тот же parity), sharp media `image/webp 200 35KB`, robots из БД (ADR-0009). **Латентный прод-баг починен cutover'ом:** Gotham-Pro.css был 0B на RUVDS → теперь 200/4436B (шрифт заголовков живой). Rollback = revert DNS→80.64.31.36 (RUVDS IIS жив, не тронут) ИЛИ PUT стека 20 назад на `tandemmebel.vds.kzntsv.site`. Compose source-of-truth обновлён. Тираж snolla 0.42.x теперь **полностью живой** (5/5 стеков на VDS)._
_Updated: 2026-07-04 (8) — 🟢 **[tandemmebel-web-vds-deploy] gallery-дефект ЗАКРЫТ на staging — GREEN.** Workshop прислал коррекцию sha → ребилд на `b02ca18` (core 0.16.2, SlugFeedPage-fix). Собрал `tandemmebel:b02ca18` (digest f8672218), передеплой стека 20 (env 8/8, healthy). DoD-чек **12/12 GREEN**: gallery-грид staging == prod ТОЧНО на всех роутах (bedrooms 80/80, kids 138/138, office 26/26 и т.д.). Крошки наполнены (`Главная/Мебель/Галерея идей`, были пустые), title полный (`Фото Офисная мебель…`), байты 28508≈прод 28253. Я флагал сомнение (мой DB-дамп показал: `/gallery` — конвенционный саб-роут, а не feed; SlugFeedPage-fix мог промахнуться) — но жёсткий рендер-чек показал GREEN, фикс сработал. **Cutover ОТЛОЖЕН оператором (не забыть!) — триггер запуска = владелец сайта меняет DNS reg.ru→89.253.255.94**, тогда verify авторит.NS→боевой Host в стек 20→live-smoke (порядок в [[NEXT_SESSION.md]]). Прогеру после разноса от оператора отправлен рабочий green-хендофф на свип 188 URL. RUVDS=rollback._
@@ -50,6 +51,10 @@ _Updated: 2026-05-26 — заведена `bookva-tenant-cutover-prep` ⚪ (7-st
_Updated: 2026-05-25 (`iis-migration-to-ruvds` 🟢 closed Phase 1 per user decision — 9/24 hostnames live на RUVDS, source IIS оставлен running. `migrate-elasticsearch-to-books-vds` 🟢 closed ранее сегодня. 16 IIS hostnames + LE renewal pipeline + decommission — descoped в Closure note, не отдельные tracker tasks.)_
## ⚪ [snolla-local-admin-restore] — восстановить локальный .NET-админ (catch-all IIS `snolla`) с RUVDS, `/admin` для тиража+on.snolla.com. Per-task: `snolla-local-admin-restore.md`. Design: `../.wiki/concepts/snolla-local-admin-and-on-snolla-migration-design.md` §Task A. ⚪ ready (ждёт SSH RUVDS verify + DB-креды). Blocks `on-snolla-vds-migration`.
## ⚪ [on-snolla-vds-migration] — on.snolla.com (siteId B9ECDB50…) с RUVDS IIS → VDS Node snolla-app 0.42.1, реконструкция шаблонов из боевого+админки. Per-task: `on-snolla-vds-migration.md`. Design: `../.wiki/concepts/snolla-local-admin-and-on-snolla-migration-design.md` §Task B. ⚪ ready, blocked by `snolla-local-admin-restore`.
## 🟢 [kupimknigi-deploy-snolla-0-42-0] — VDS-staging образ kupimknigi.spb.ru на snolla@0.42.0 (одностраничник, финал тиража). Per-task: `kupimknigi-deploy-snolla-0-42-0.md`.
**Status:** done — 2026-07-05. ✅ Собрал `registry.kzntsv.site/kupimknigi:9608ff6` (digest `ac7f846`, 583MB) на VDS из sha 9608ff6 (snolla 0.42.0/core 0.24.0/data 0.14.1), запушил. Создал **новый Portainer-стек Id 21 `kupimknigi`** (POST create/standalone, env verbatim 8/8 из стека 20 — тот же тенант) → контейнер **healthy** сразу, running==9608ff6. Staging-host kupimknigi.vds.kzntsv.site.

View File

@@ -0,0 +1,30 @@
# on-snolla-vds-migration
## Goal
Мигрировать посадочную `on.snolla.com` с RUVDS IIS (MoreThenCms .NET) на VDS как Node snolla-app `@snollajs/snolla` 0.42.1. Исходников сайта нет — реконструировать из боевого сайта + админки. **Спека:** [[../.wiki/concepts/snolla-local-admin-and-on-snolla-migration-design.md]] §Task B.
## Facts (из `MoreThenCms` DB)
- `SiteId=B9ECDB50-2B93-4CE5-B238-A9918B3F9CF7`, `Alias=on`, `Title="Internal Site"`, `Culture=en`, `Live=1, Production=1`.
- Контент (DB-строки + ассеты) уже на vds-kzntsv (общая `MoreThenCms` DB + MinIO) — нужно только репо шаблонов+конфига.
## Plan / phases
- [ ] **1. Реконструкция шаблонов** — через локальный админ ([[snolla-local-admin-restore]]) + боевой `https://on.snolla.com/` HTML: для каждой страницы сопоставить вёрстку с DB-контент-структурой → `layout.liquid` + page/partials. Итеративно (пиши→рендерь→сверяй с боевым).
- [ ] **2. Новый репо** `victor/on-snolla` (имя уточнить) — калька `tandemmebel.ru/apps/web` (server.js/index.js/config/views/package.json + deploy/Dockerfile). Пин `@snollajs/snolla` 0.42.1.
- [ ] **3. production.json** — siteId `B9ECDB50…`, siteUrl `https://on.snolla.com`, sequelize→`MoreThenCms` `mssql.kzntsv.site:1433`, s3→`minio.kzntsv.site`, imgproxy→`imgproxy.kzntsv.site`, sharp serve-bytes. Секреты в runtime-env стека.
- [ ] **4. Build на VDS** (обход traefik-499, build-arg VERDACCIO_TOKEN), push `registry.kzntsv.site/on-snolla:<sha>`.
- [ ] **5. Throwaway-staging `:50XX`** из env живого (или нового стека) → completeness-gate: sitemap parity vs прод-on.snolla.com (page-locs NEW==PROD, self-consistency 0 регрессий 404/5xx).
- [ ] **6. Stack** Portainer за traefik `Host(on.snolla.com)`, `mem_limit 512m`, env секреты.
- [ ] **7. Cutover** — verify авторит. NS reg.ru→89.253.255.94 → traefik Host-rule → LE-серт → live-smoke. По `tandemmebel-vds-deploy-runbook`.
## Status
⚪ ready (blocked by [[snolla-local-admin-restore]]). Branch: master.
## Depends on / blocks
- Blocked by: [[snolla-local-admin-restore]] (админ для контент-инспекции).
## Open Q
- Имя репо (`victor/on-snolla`? `victor/on.snolla.com`?).
- Сложность посадочной (объём шаблонов) — узнается при реконструкции.
## Rollback
Образ предыдущего тега в registry / revert DNS reg.ru→80.64.31.36 (RUVDS IIS жив пока DNS не флипнут).

View File

@@ -0,0 +1,34 @@
# snolla-local-admin-restore
## Goal
Восстановить локальный .NET-админ (catch-all IIS-сайт `snolla`) на этой машине (`windows-recovery-host`), снесённый 2026-06-08 при декоммишене. Назад — с RUVDS (текущий прод-админ с MinIO drop-in). Даёт `/admin` для всех сайтов тиража + on.snolla.com локально. **Спека:** [[../.wiki/concepts/snolla-local-admin-and-on-snolla-migration-design.md]] §Task A.
## Why
Тираж уехал на VDS (Node), админка осталась на RUVDS .NET. Нужно локально редактировать контент (особенно on.snolla.com для Task B) без зависимости от RUVDS. Временно — пока админ не мигрирован на VDS.
## Addressing (confirmed оператором)
Catch-all `*:80` + `hosts`-override → `127.0.0.1 <alias>.snolla.com`. Один AppPool `snolla`. URL = `<alias>.snolla.com/admin`:
- tandemmebel.snolla.com/labtools.snolla.com/labtoolspro.snolla.com/emspb.snolla.com/kupimknigi.snolla.com/on.snolla.com
## Plan / phases
- [ ] **0. Verify source (read-only SSH RUVDS)**`pass show ruvds-iis/full-env`; проверить `C:\sites\snolla\` есть, `Web.config` несёт `FileStorage.S3`+`minio.kzntsv.site`, IIS site `snolla` жив. Если MinIO НЕ применён → fallback: build из MoreThenCms source + drop-in `MoreThenCms.FileStorage.S3/deploy/`.
- [ ] **1. Копировать `C:\sites\snolla\`** RUVDS→локально (~8.66 GB, scp/rclone).
- [ ] **2. Репойнт conn-string**`mssql.kzntsv.site,1433;Catalog=MoreThenCms;TrustServerCertificate=True` (DB-креды из `pass`; уточнить app-аккаунт vs SA).
- [ ] **3. MinIO-ключи** в `<fileStorageClients>``minio.kzntsv.site`, бакеты assets/galleries/themes, ключи из `pass show minio-vds/full-env` (если плейсхолдеры). Кэши оставить Local.
- [ ] **4. IIS-сайт `snolla`** — AppPool `snolla` (.NET v4.0 Integrated, AppPoolIdentity), binding `*:80` catch-all. ACL `IIS AppPool\snolla:(OI)(CI)(M)` на `C:\sites\snolla`.
- [ ] **5. hosts-override**`127.0.0.1 <6 aliases>.snolla.com` (elevation).
- [ ] **6. FW** — блок inbound 80 (локальный только). URL Rewrite rule НЕ ставить.
- [ ] **7. Smoke**`curl -H "Host: tandemmebel.snolla.com" http://127.0.0.1/admin/account/login` → 200; on.snolla.com同理; MinIO upload-цикл.
## Status
⚪ ready (ждёт отмашки оператора на SSH RUVDS + креды). Branch: master.
## Depends on / blocks
- Блокирует: [[on-snolla-vds-migration]] (нужен админ для контент-инспекции on.snolla.com).
## Open Q
- MoreThenCms DB app-аккаунт + путь в `pass` (SA есть `mssql-vds/sa-password`, но админ юзает app-аккаунт).
- Включать все ~60 сайтов или только тираж(5)+on.snolla.com — catch-all даёт все, решает hosts-список.
## Rollback
Удалить IIS-сайт `snolla` + `C:\sites\snolla\` + откатать hosts. Прод-RUVDS не тронут.

View File

@@ -0,0 +1,92 @@
---
title: SNOLLA local .NET admin restore + on.snolla.com VDS migration — design
type: concept
tags: [snolla, morethencms, iis, admin, minio, vds, migration, on-snolla, design]
related: [[../entities/windows-recovery-host]], [[../entities/ruvds-iis-host]], [[../entities/vds-kzntsv]], [[tandemmebel-vds-deploy-runbook]], [[snolla-live-prod-inplace-image-bump]], [[portainer-stack-management-vds]], [[filestorage-s3-provider@MoreThenCms]]
updated: 2026-07-20
---
# SNOLLA local .NET admin restore + on.snolla.com → VDS migration
Две связанные задачи. **Task A** восстанавливает локальный .NET-админ (чтобы редактировать контент всех сайтов тиража + on.snolla.com). **Task B** мигрирует посадочную `on.snolla.com` с RUVDS на VDS как Node snolla-app, реконструируя отсутствующие исходники из боевого сайта + админки. Task A → питает Task B (без рабочего админа не увидеть контент/структуру on.snolla.com).
## Контекст
- **Тираж SNOLLA** (5 сайтов) уже на VDS как Node snolla-app `@snollajs/snolla` 0.42.1, читают контент из общей MSSQL `MoreThenCms` на `mssql.kzntsv.site:1433` + ассеты из MinIO `minio.kzntsv.site`. Стеки Portainer: labtools.ru(17), emspb.ru(18), labtools.pro(19), tandemmebel(20), kupimknigi(21). Публичный snolla-app **без админки** (`apps/web` не несёт admin-роутов).
- **На RUVDS IIS** (`80.64.31.36`, Windows Server 2025 Core) остались: catch-all IIS-сайт `snolla` (MoreThenCms .NET 4.8, `/admin` для всех `*.snolla.com`) + посадочная `on.snolla.com`. МинIO-поддержка в .NET-админ добавлена (drop-in `MoreThenCms.FileStorage.S3`, см. MoreThenCms `.wiki/concepts/filestorage-s3-provider.md`).
- **Локальный админ-хост** = этот рабочий PC (`windows-recovery-host`, DESKTOP-NSEF0UK). IIS-сайт `snolla` + `C:\sites\snolla\` были снесены 2026-06-08 (RUVDS забрал прод-админ). Живой локальный аналог остался: `stostayer`(:8090)/`stostayer.old`(:8091) — тот же движок MoreThenCms, `/admin`, conn → `mssql.kzntsv.site,1433`. Это рабочий шаблон конфига.
- **on.snolla.com** — `dbo.Sites`: `SiteId=B9ECDB50-2B93-4CE5-B238-A9918B3F9CF7`, `Alias=on`, `Title="Internal Site"`, `Culture=en`, `Live=1, Production=1`. Лендинг самого SNOLLA. Отдельного репо/исходников нет.
## Task A — восстановить локальный .NET-админ (catch-all IIS `snolla`)
### Адресация (confirmed оператором)
Catch-all IIS-сайт `snolla`, binding `*:80` (локально — `127.0.0.1:80` или `*:80` без публикации наружу), **один AppPool `snolla`**. Доступ через `hosts`-override: `127.0.0.1 <alias>.snolla.com` на каждый таргет. Multi-tenant routing в CMS по Host-header → siteId из `dbo.Sites`.
**Адреса админок** = `<Alias>.snolla.com/admin`:
| Адрес | PrimaryDomain | siteId |
|---|---|---|
| `tandemmebel.snolla.com/admin` | tandemmebel.ru | 78080707-F6E0-4330-BA30-7922354C2CEF |
| `labtools.snolla.com/admin` | labtools.ru | D375C419-D787-4FCC-8934-A3B9DC951006 |
| `labtoolspro.snolla.com/admin` | labtools.pro | 663F9410-A6CC-4651-9A5C-62844A313957 |
| `emspb.snolla.com/admin` | emspb.ru | 96EBC481-D26A-47BE-B660-13D49E7D0A61 |
| `kupimknigi.snolla.com/admin` | kupimknigi.spb.ru | E924A354-0377-4E1E-80C6-2EB0194AA55F |
| `on.snolla.com/admin` | on.snolla.com | B9ECDB50-2B93-4CE5-B238-A9918B3F9CF7 |
Catch-all обслужит `/admin` для любого сайта из DB при добавлении `127.0.0.1 <alias>.snolla.com` в hosts — тираж = 5 + on.snolla.com минимум, при желании все ~60.
### Источник `C:\sites\snolla\`
**Рекомендация — копировать с RUVDS** (`scp`/`rclone`): RUVDS держит `C:\sites\snolla\` (8.66 GB) = текущий прод-админ **с уже применённым MinIO drop-in**. Копируем → получаем админ с MinIO из коробки, без пересборки solution и без ручного патча DLL. Альтернативы (build из MoreThenCms source + применить S3 drop-in вручную; restore с kreknin-backup) дольше и требуют повторной MinIO-настройки.
### Шаги
1. **Verify source (read-only SSH RUVDS, креды `pass show ruvds-iis/full-env`):** `C:\sites\snolla\` есть; `Web.config` несёт `storageType="MoreThenCms.FileStorage.S3.*"` + endpoint `minio.kzntsv.site`; IIS site `snolla` жив. Если MinIO НЕ применён — fallback: build из source + drop-in из `MoreThenCms.FileStorage.S3/deploy/` (3 DLL + `fileStorageClients-s3.sample.config`).
2. **Копировать `C:\sites\snolla\`** RUVDS → локально `C:\sites\snolla\` (~8.66 GB; rsync недоступен на Core — `scp -r` или `rclone copy`, resume через rclone).
3. **Репойнт conn-string** в локальном `Web.config``Data Source=mssql.kzntsv.site,1433;Initial Catalog=MoreThenCms;User ID=<snolla-db-user>;Password=<...>;MultipleActiveResultSets=True;TrustServerCertificate=True` (паттерн из `stostayer.old/Web.config`). DB-креды — из `pass` (MoreThenCms DB user; тот же, что tandemmebel production.json `DB_USER`/`DB_PASSWORD`).
4. **MinIO-ключи** в `<fileStorageClients>`: endpoint `https://minio.kzntsv.site`, бакеты `assets`/`galleries`/`themes`, `accessKey`/`secretKey` — из `pass show minio-vds/full-env`. Если в скопированном Web.config ключи плейсхолдеры `__SET_ON_DEPLOY__` — подставить реальные. Кэши (`imageCache`/`uploadCache`/`contentCache`/`sessionFiles`) оставить `Local`.
5. **IIS-сайт `snolla`** воссоздать: AppPool `snolla` (.NET v4.0 Integrated, `ApplicationPoolIdentity`), binding `*:80` catch-all (как на проде). Локальный доступ гарантируется FW-блоком inbound 80 + `hosts`-override → 127.0.0.1 (внешние не достучатся). Multi-tenant по Host-header.
6. **ACL**: `icacls C:\sites\snolla /grant "IIS AppPool\snolla:(OI)(CI)(M)" /T` (паттерн `snolla-admin-appdata-acl-500`).
7. **hosts-override**: добавить `127.0.0.1 tandemmebel.snolla.com labtools.snolla.com labtoolspro.snolla.com emspb.snolla.com kupimknigi.snolla.com on.snolla.com` в `C:\Windows\System32\drivers\etc\hosts` (нужен elevation).
8. **URL Rewrite rule** (X-Forwarded-Proto→HTTPS server-vars) — **НЕ ставить** локально (нет traefik; ходим по http, иначе `:port` leak как в `cms-server-port-leak-fix`).
9. **Firewall**: НЕ открывать 80/443 inbound — локальный только.
10. **Smoke**: `curl -H "Host: tandemmebel.snolla.com" http://127.0.0.1/admin/account/login` → 200 логин-форма; аналогично для on.snolla.com. MinIO: залить тестовый ассет через админку → виден через `minio.kzntsv.site`/фронтом (приёмка #5 drop-in'а).
### Гочи (специфичные)
- **`appSettings/sitePath`** в catch-all `Web.config``C:\sites\snolla\` (multi-tenant; siteId резолвится из Host-header, не из appSettings — в отличие от per-site stostayer.old где `siteId` в appSettings).
- **machineKey** — оставить из скопированного Web.config (общий для всех tenant'ов админ-сессий).
- **`customErrors mode="Off"`** — обязательно (иначе fatal config error после ASP.NET reload, см. `cms-server-port-leak-fix` side-regression).
- **MSSQL-коннект с workstation** — уже работает (stostayer.old его использует); `TrustServerCertificate=True` обязательно (mssql.kzntsv.site cert self-signed/не-Microsoft).
## Task B — on.snolla.com → VDS (Node snolla-app, реконструкция)
on.snolla.com = MoreThenCms-сайт на RUVDS (посадочная). На VDS (Linux) .NET Framework не бежит → становится Node snolla-app по образцу `victor/tandemmebel.ru`. Контент (DB-строки + ассеты) уже на vds-kzntsv (общая `MoreThenCms` DB + MinIO). Нет репозитория шаблонов+конфига — собираю из боевого сайта + админки.
### Реконструкция
1. **siteId найден**: `B9ECDB50-2B93-4CE5-B238-A9918B3F9CF7` (alias `on`, culture `en`).
2. **Новый репо** `victor/on-snolla` (имя уточнить у оператора) — структура как `tandemmebel.ru`: `apps/web/{server.js,index.js,config/,views/,package.json}`, `deploy/Dockerfile` (multi-stage node:22-slim, `yarn install --immutable`, non-root, healthcheck `/robots.txt`). `apps/web/package.json` пин `@snollajs/snolla` 0.42.1 (parity с тиражом).
3. **production.json**: `siteId=B9ECDB50…`, `siteUrl=https://on.snolla.com`, `data.sequelize``MoreThenCms` DB `mssql.kzntsv.site:1433` (Catalog `MoreThenCms`), `s3``minio.kzntsv.site`, `imgproxy``imgproxy.kzntsv.site`, `media` sharp serve-bytes, `mailSettings`. Секреты в runtime-env стека (Portainer), НЕ в образе/гите — как tandemmebel (8 секретов).
4. **Liquid-шаблоны (views/)** — реверс-инжиниринг с боевого `https://on.snolla.com/`: для каждой страницы смотрим HTML, сопоставляем с DB-контент-структурой (секции/блоки через локальный админ из Task A), пишем `layout.liquid` + page/partials. Содержимое (текст/картинки) идёт из DB; шаблоны = layout + разметка. Итеративно: пиши шаблон → рендерь на staging → сверяй с боевым HTML (byte/structure parity).
5. **Build на VDS** (обход traefik-499), **throwaway-staging `:50XX`**, **completeness-gate** (sitemap parity vs прод-on.snolla.com — page-locs NEW==PROD, self-consistency), **stack** за traefik (`Host(on.snolla.com)`), **DNS-flip** reg.ru→89.253.255.94. По рецепту `tandemmebel-vds-deploy-runbook` (cutover) + `snolla-live-prod-inplace-image-bump` (gate). `mem_limit 512m`.
### Trade-off реверс-инжиниринга
Боевой HTML даёт вёрстку, но Liquid-примитивы snolla (sections/blocks/feeds) надо сопоставить с DB-структурой — итеративно. Риск: сложная посадочная с нестандартными блоками = больше итераций. Митигация: on.snolla.com Title="Internal Site" culture `en` — вероятно простой лендинг, объём шаблонов ограничен.
## Последовательность и зависимости
1. **Task A** — восстановить локальный админ (RUVDS→scp→IIS→MinIO→smoke). Блокирует Task B (нужен админ для контент-инспекции).
2. **Task B** — через локальный админ + боевой HTML собрать on.snolla.com snolla-app → build на VDS → cutover.
## Load-bearing допущения (verify в плане)
- RUVDS `C:\sites\snolla\` несёт MinIO drop-in (SSH read-only — первый шаг Task A). Если нет — fallback на build+drop-in.
- MinIO-ключи в RUVDS Web.config — реальные, не `__SET_ON_DEPLOY__` (иначе подтянуть из `pass`).
- MoreThenCms DB-креды (snolla-user) в `pass` — найти путь (кандидаты: `mssql-vds/...`, общий env). SA-доступ есть (`pass show mssql-vds/sa-password`) — но админ использует app-аккаунт, не SA; уточнить у оператора.
- on.snolla.com siteId/контент доступны в общей `MoreThenCms` DB (подтверждено: строка в `dbo.Sites` есть).
- `hosts`-override + IIS-воссоздание требуют elevation (admin-сессия на workstation).
## Rollback
- **Task A:** удалить IIS-сайт `snolla` + `C:\sites\snolla\` + откатать hosts-записи. Прод на RUVDS не тронут — rollback = просто не пользоваться локальным админом.
- **Task B:** образ предыдущего тега в registry (или RUVDS IIS жив для on.snolla.com пока DNS не флипнут — revert DNS→80.64.31.36).
## Open questions (для оператора)
- Имя нового репо для on.snolla.com (`victor/on-snolla`? `victor/on.snolla.com`?).
- MoreThenCms DB-креды: app-аккаунт + путь в `pass` (или использовать SA локально / завести отдельный read-write аккаунт).
- Включать ли в локальный админ ВСЕ сайты (~60) или только тираж(5)+on.snolla.com — catch-all даёт все бесплатно, решает hosts-список.