--- 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 .snolla.com` на каждый таргет. Multi-tenant routing в CMS по Host-header → siteId из `dbo.Sites`. **Адреса админок** = `.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 .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=;Password=<...>;MultipleActiveResultSets=True;TrustServerCertificate=True` (паттерн из `stostayer.old/Web.config`). DB-креды — из `pass` (MoreThenCms DB user; тот же, что tandemmebel production.json `DB_USER`/`DB_PASSWORD`). 4. **MinIO-ключи** в ``: 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-список.