Compare commits
12 Commits
d4278e79f9
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 95168e301a | |||
| ec3ac79272 | |||
| 535ed6170f | |||
|
|
50e263860d | ||
|
|
bec7784ffa | ||
|
|
4c4d19382b | ||
|
|
9705468ef4 | ||
| 019f5bae26 | |||
| 73ad7669b4 | |||
| dcc84cec4b | |||
| 863b11be28 | |||
| c196964d03 |
@@ -1,65 +1,73 @@
|
||||
---
|
||||
_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
|
||||
_last_updated_: 2026-07-21T00:00:00Z
|
||||
session_id: 2026-07-21-ruvds-decomm
|
||||
prev_session_id: 2026-07-20-on-snolla-cutover-done
|
||||
---
|
||||
|
||||
# Next session handoff
|
||||
|
||||
## Эта сессия — design: SNOLLA local admin restore + on.snolla.com → VDS
|
||||
## Эта сессия — RUVDS DECOMM 2026-07-21. Погашен, забыт.
|
||||
|
||||
Спека написана и закоммичена: `.wiki/concepts/snolla-local-admin-and-on-snolla-migration-design.md`
|
||||
(commit `b1b0092c`). Две таски заведены в `.tasks/` + board-entries в STATUS.md.
|
||||
[[ruvds-iis-host]] (80.64.31.36) декоммишнен 2026-07-21. Аудит: на RUVDS не осталось живого — весь snolla-тираж на VDS (стеки 17-22), локальный .NET-админ независим. Финальный offsite-снимок на kreknin верифицирован (8.8G, 7-day retention, прогон 04:30 success). rimiz.ru/www.rimiz.ru (последний публичный домен на RUVDS, мёртвый 404) — DNS переправлен оператором на 89.253.255.94, авторит. NS verified. **На RUVDS — 0 публичных доменов.** Коммиты `535ed617`, `ec3ac792` запушены.
|
||||
|
||||
**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).
|
||||
### ОСТАЁТСЯ ОПЕРАТОРУ (один ручной шаг)
|
||||
- **Отказаться от RUVDS у провайдера** — личный кабинет https://ruvds.com (креды в `pass ruvds-iis/full-env`). Машина выключена/забыта на нашей стороне; cancelling у провайдера = экономия денег. Не горит — daily-бэкап с RUVDS прекратится сам (таска умрёт с хостом), это ОК: offsite-копия уже на kreknin, локальный админ жив.
|
||||
|
||||
**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).
|
||||
### Предыдущая сессия — Task B (on.snolla.com → VDS) DONE 2026-07-20.
|
||||
on.snolla.com live на VDS как Node snolla-app `@snollajs/snolla` 0.42.1, за traefik, LE-серт issued.
|
||||
~~Прод-оракул был RUVDS IIS (80.64.31.36) — не тронут, жив (rollback = revert DNS).~~ **RUVDS DECOMM — rollback только образ-тегом (см. on-snolla-vds-deploy-runbook § Rollback).**
|
||||
|
||||
### 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)
|
||||
🟢 **[on-snolla-vds-migration] ЗАКРЫТА.** Спека: `.wiki/concepts/snolla-local-admin-and-on-snolla-migration-design.md` §Task B.
|
||||
Runbook (as-built + gotchas): `.wiki/concepts/on-snolla-vds-deploy-runbook.md`. Таска: `.tasks/on-snolla-vds-migration.md` (as-built).
|
||||
|
||||
## Recent commits
|
||||
- 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
|
||||
### As-built
|
||||
- **Репо** `victor/on.snolla.com` (git.kzntsv.site, запушен) — структура-калька tandemmebel.ru. Commit `473923e494db`.
|
||||
- **Образ** `registry.kzntsv.site/on-snolla:473923e494db` (+:latest), собран на VDS (обход traefik-499).
|
||||
- **Стек Portainer 22** (`on-snolla`), `mem_limit 512m`, 8 env-секретов (переиспользованы из tandemmebel стека 20 — общая snolla-инфра), rule `Host(on.snolla.com)`, LE-серт CN=on.snolla.com (YR1, until 2026-10-18).
|
||||
- **DNS**: reg.ru `on.snolla.com` A `80.64.31.36`→`89.253.255.94` (operator flip; авторит. NS ns1/ns2.reg.ru verified → VDS before rule swap, LE-порядок соблюдён).
|
||||
- **Реконструкция**: `views/layout.liquid` = bootstraptor-лендинг **byte-identical** прод-HTML (28413 байт, verified direct diff + live). Content-поля пустые → лендинг baked в layout. Form "Join us" baked (POST `/` → snolla `forms` middleware → `form_ajax_response.liquid`). StaticPages `/yandex_…` + `/4a052808276c.html`. `/c` = 404 dead-link (parity с продом — prod /c тоже 404; snolla sitemap несёт его → 3/3 loc parity).
|
||||
- **Completeness-gate GREEN**: sitemap 3/3 parity {/,/c,/yandex}, homepage + /yandex byte-identical, 0 регрессий. Live-smoke external: TLS verify=0, `/`+`/robots.txt`+`/sitemap.xml`+`/yandex`=200, `/c`=404.
|
||||
|
||||
### Гочи (в runbook + memory)
|
||||
- **snolla robotsTxt крашится на undefined `app.locals.domain`** — on.snolla.com не имеет row в MoreThenCms `Domains`. Фикс в `apps/web/index.js`: после initApp, если `!app.locals.domain`, synthesized `{robotsTxt: site.robotsTxt}`. Без shared-DB мутации. Memory `snolla-robotstxt-crash-no-domains-row`.
|
||||
- **Form "Join us" не имеет Liquid form-tag** — форма HTML baked в layout, POST — `forms` middleware (мэтч по Path `/`). Legacy reCAPTCHA v1 мертва — parity, не чиним.
|
||||
- **Portainer JWT short-lived** — в node-скрипте GET stack + GET file + PUT: jwt из GET-фазы протух к PUT (первый PUT 401). Re-auth прямо перед PUT.
|
||||
- **hosts override на воркстейшне** — Task A оставил `127.0.0.1 on.snolla.com` в hosts. External verify прод-on.snolla.com = только через `curl --resolve on.snolla.com:443:89.253.255.94`.
|
||||
|
||||
### MinIO upload-acceptance (ручной follow-up оператора — НЕ сделано)
|
||||
Логин в админку on.snolla.com (на RUVDS .NET, `/admin`) → залить тест-ассет → проверить объект в `minio.kzntsv.site` bucket=assets. S3-провайдер был admin-self-test green на RUVDS; Web.config 1:1 → должно работать. Креды админа в `MoreThenCms.dbo.Accounts` (SQL-user `snolla` / SA `pass mssql-vds/sa-password`).
|
||||
|
||||
## Recent commits (.admin)
|
||||
- 4c4d1938 feat(on-snolla): CUTOVER DONE — on.snolla.com live on VDS (stack 22, LE cert)
|
||||
- 6b5cb5fa feat(on-snolla): Portainer stack 22 source-of-truth (staging Host, mem_limit 512m, 8 env secrets)
|
||||
- 73ad7669 (projects-meta) close vehicles-loader-redeploy-per-group-rate-diff 🟢
|
||||
- 019f5bae (projects-meta) close on-snolla-vds-migration 🟢
|
||||
- (on.snolla.com repo) 473923e feat(on-snolla): scaffold snolla-app — byte-identical landing reconstruction
|
||||
|
||||
## Open треки
|
||||
|
||||
| Трек | Готовность | Entry-point |
|
||||
|---|---|---|
|
||||
| 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. |
|
||||
| books-vds → vds-kzntsv консолидация | оценено, не лезет по RAM/disk | Решение за user. |
|
||||
| MinIO upload-acceptance on.snolla (ручной) | ⚪ follow-up оператора | Логин `/admin` (RUVDS) → тест-ассет → MinIO bucket=assets. |
|
||||
|
||||
## Спроси user'а
|
||||
- **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?
|
||||
- (нет pending-решений — Task B закрыт полностью)
|
||||
|
||||
## Не делать (preemptive guards)
|
||||
- **НЕ 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).
|
||||
- **НЕ пушить без добла** (Rule 4) — на эту сессию добл был ("разрешаю всё, погнали").
|
||||
- **НЕ сжимать** books на .94; **НЕ netplan** на vds-kzntsv.
|
||||
- **hosts override активен** — `internal.snolla.com` → 127.0.0.1 (локальный админ Task A; алиас `on` переименован в `internal` 2026-07-20). Боевой on.snolla.com (VDS) с воркстейшна — только через `--resolve :443:89.253.255.94` или off-hosts. **Публичного on.snolla.com/admin не существует** (никогда не было) — админка только локальная: `http://internal.snolla.com/admin`.
|
||||
|
||||
### Alias rename `on`→`internal` (2026-07-20, follow-up оператора)
|
||||
- `Sites.Alias`+`LoweredAlias`: `on`→`internal` (siteId B9ECDB50, PrimaryDomain остался `on.snolla.com`).
|
||||
- `C:\sites\snolla\Web.config` `primaryAlias`: `on`→`internal` (иначе catch-all NRE-500 на ВСЕХ запросах — primaryAlias ссылается на переименованный алиас).
|
||||
- hosts: `on.snolla.com`→`internal.snolla.com` под маркером `# snolla-local-admin`.
|
||||
- **Инцидент:** я обнулил hosts своей elevated-правкой (Get-Content -Raw в RunAs-контексте вернул пусто → Set-Content записал пусто). Восстановил: Windows default header + snolla-local-admin блок (с internal.snolla.com). LAN-DNS CMS-перехват через DNS-резолвер, не hosts → потерь нет. Урок в memory `snolla-catch-all-primaryalias-depends-on-alias`.
|
||||
- VDS prod on.snolla.com НЕ затронут (snolla-app использует config.siteId, не alias) — byte-identical, smoke GREEN.
|
||||
- **НЕ откатывать DNS on.snolla.com** без явного запроса — cutover LIVE, RUVDS IIS жив как rollback-target.
|
||||
|
||||
## Memory updates за сессию
|
||||
- (пока не сохранял — если design approved, возможно memory: «SNOLLA admin addressing = <alias>.snolla.com/admin catch-all IIS, siteId из dbo.Sites by alias»; и обновить windows-recovery-host entity — планируется восстановление snolla IIS-сайта локально)
|
||||
- **NEW** `snolla-robotstxt-crash-no-domains-row` — snolla sites без Domains row крашатся на /robots.txt; фикс в index.js domain-drop fallback.
|
||||
- (candidate) on.snolla.com мигрирован на VDS 2026-07-20 (stack 22, LE). Тираж snolla на VDS: labtools(17)/emspb(18)/labtools-pro(19)/tandemmebel(20)/kupimknigi(21)/on-snolla(22).
|
||||
- (candidate) обновить entity `windows-recovery-host.md`: on.snolla.com более не обслуживается локальным IIS как прод — прод на VDS; локальный IIS `snolla` = только админ-хаб (hosts override on.snolla.com→127.0.0.1 теперь pointing на админ-копию, не прод).
|
||||
@@ -1,4 +1,5 @@
|
||||
# Admin Task Board
|
||||
_Updated: 2026-07-20 (2) — 🟢 **[snolla-local-admin-restore] CLOSED.** Локальный .NET-админ поднят: selective tar-copy `C:\sites\snolla\` ~100MB с RUVDS (исключил stale App_Data 8.76GB — assets/galleries/themes теперь в MinIO), Web.config уже → `mssql.kzntsv.site,1433` Catalog=MoreThenCms (user `snolla`) + MinIO S3 drop-in (ключи реальные, placeholder_count=0). Elevated setup `scripts/local-snolla-admin-restore/setup-local-snolla-admin.ps1` (ASCII-only, PS5.1 BOM-less-safe): AppPool `snolla` (.NET v4.0, AppPoolIdentity, recycle@200MB), IIS site `*:80` catch-all, ACL `IIS AppPool\snolla:(OI)(CI)(M)`, hosts-override `127.0.0.1 <6 aliases>.snolla.com`, FW block inbound 80. Smoke GREEN: `tandemmebel/labtools/labtoolspro/emspb/kupimknigi/on .snolla.com/admin/account/login` → 200, реальная MoreThenCms-логинформа (`<title>SNOLLA</title>`, `<form action="/admin/login">`). **Unblocks [on-snolla-vds-migration]** (Task B — админ для контент-инспекции готов). МинIO upload-acceptance = ручной follow-up оператора. RUVDS SSH через plink `-hostkey SHA256:r/vSKU5WzH4B8T7RiXyXlg0D8XZ9hlBxzmdrPzuPWzE` (креды `pass show ruvds-iis/full-env`)._
|
||||
_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)._
|
||||
@@ -51,9 +52,19 @@ _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`.
|
||||
## 🟢 [snolla-local-admin-restore] — closed 2026-07-20 — локальный .NET-админ (catch-all IIS `snolla`) поднят с RUVDS, `/admin` для тиража+on.snolla.com. Per-task: `snolla-local-admin-restore.md`. Selective tar-copy ~100MB (НЕ 8.76GB, исключил stale App_Data assets/galleries/themes). Web.config уже на mssql.kzntsv.site+MinIO (repoint не нужен, ключи реальные). Elevated setup: `scripts/local-snolla-admin-restore/setup-local-snolla-admin.ps1`. Smoke GREEN: 6 адресов `/admin/account/login` → 200 (tandemmebel/labtools/labtoolspro/emspb/kupimknigi/on), реальная MoreThenCms-логинформа. unblocks `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`.
|
||||
## 🟢 [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`.
|
||||
|
||||
## As-built (2026-07-20)
|
||||
- Repo `victor/on.snolla.com` pushed (git.kzntsv.site). Structure-clone of tandemmebel.ru.
|
||||
- Image `registry.kzntsv.site/on-snolla:473923e494db` (+:latest), built on VDS.
|
||||
- Portainer stack Id 22, `mem_limit 512m`, 8 env secrets, rule `Host(on.snolla.com)`, LE cert.
|
||||
- `on.snolla.com` DNS reg.ru A 80.64.31.36→89.253.255.94 (operator flip). RUVDS IIS untouched (rollback = revert DNS).
|
||||
- Reconstruction: layout.liquid = bootstraptor landing byte-identical prod; form "Join us" baked (POST / → forms middleware); StaticPages /yandex + /4a052808276c; /c = 404 dead-link (parity).
|
||||
- robotsTxt fix in index.js: on.snolla.com has no Domains row → snolla robotsTxt crashes on undefined app.locals.domain; synthesized domain drop from site.robotsTxt.
|
||||
- Completeness-gate: sitemap 3/3 parity, homepage + /yandex byte-identical, 0 regressions.
|
||||
<!-- closed-by: OpeItcLoc03@DESKTOP-NSEF0UK / 2026-07-20T10:17:07.799Z / note: DONE 2026-07-20 — on.snolla.com live on VDS (stack 22, image on-snolla:473923e494db, snolla 0.42.1). LE cert issued (CN=on.snolla.com, YR1, until Oct 18). Homepage byte-identical prod-HTML. Sitemap 3/3 parity {/,/c,/yandex}. Live-smoke GREEN. -->
|
||||
|
||||
## 🟢 [kupimknigi-deploy-snolla-0-42-0] — VDS-staging образ kupimknigi.spb.ru на snolla@0.42.0 (одностраничник, финал тиража). Per-task: `kupimknigi-deploy-snolla-0-42-0.md`.
|
||||
|
||||
@@ -1581,13 +1592,14 @@ Cutover DNS уже сделан (07-02) — тут только смена об
|
||||
|
||||
---
|
||||
|
||||
## 🔴 [vehicles-loader-redeploy-per-group-rate-diff] — Пересобрать и задеплоить @stostayer/vehicles-loader на прод клиента с новым кодом per-group rate diff. Код уже на origin/master (запушено 85ca936, 5 коммитов b0e7b58..85ca936). Изменение: rate-группы с неизменённым мультимножеством {standardHours,notes} теперь skip'аются вместо слепого DELETE+INSERT — объём записей в БД 51 203 → 1 963 rate-rows/день (−96%), счётчик replaced=реальные записи, skipped=пропущенные группы. Read-consistency сохранена (изменившиеся группы — та же короткая транзакция). Write-примитив replaceGroup не менялся. Валидировано двумя dry-run против prod (0 ошибок, SG skipped=41089/replaced=1555, SM skipped=5131/replaced=408) + 36 unit-тестов.
|
||||
## 🟢 [vehicles-loader-redeploy-per-group-rate-diff] — Пересобрать и задеплоить @stostayer/vehicles-loader на прод клиента с новым кодом per-group rate diff. Код уже на origin/master (запушено 85ca936, 5 коммитов b0e7b58..85ca936). Изменение: rate-группы с неизменённым мультимножеством {standardHours,notes} теперь skip'аются вместо слепого DELETE+INSERT — объём записей в БД 51 203 → 1 963 rate-rows/день (−96%), счётчик replaced=реальные записи, skipped=пропущенные группы. Read-consistency сохранена (изменившиеся группы — та же короткая транзакция). Write-примитив replaceGroup не менялся. Валидировано двумя dry-run против prod (0 ошибок, SG skipped=41089/replaced=1555, SM skipped=5131/replaced=408) + 36 unit-тестов.
|
||||
|
||||
**Status:** active
|
||||
**Where I stopped:** DEPLOYED + image-verified. Built docker.stostayer.ru/vehicles-loader:0.4.1 from master@b86ed40 (incl 85ca936 rate-diff). Pushed (one shot, digest sha256:228f2b24). Host: pulled + tagged :latest (image c3c4a83b15bd). New code confirmed in image: rateDiff.js(rateSetsEqual×2), replaceGroup.js(replaceRatesForGroups×2). Old tags 0.4.0/0.3.0 retained for rollback. Timer armed, next run Tue 2026-07-14 06:21:38 MSK. PENDING: runtime verify at that run.
|
||||
**Next action:** After 07-14 06:21 MSK run: check new importRun status=ok + counts.serviceGenerationRate={replaced:<сотни>,skipped:<~41k>}, serviceModificationRate={replaced:<сотни>,skipped:<~5k>}, duration < ~93 мин. If replaced still ~44k/6.7k → wrong image (but code-verify already GREEN). Rollback: docker tag 0.4.0 vehicles-loader:latest.
|
||||
**Status:** done
|
||||
**Where I stopped:** runtime verify GREEN per operator 2026-07-20 — 0.4.1 rate-diff confirmed on prod.
|
||||
**Next action:** (none — kept until merged)
|
||||
**Branch:** n/a
|
||||
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: victor/stostayer.new / 2026-07-13T14:08:16.228Z -->
|
||||
<!-- closed-by: OpeItcLoc03@DESKTOP-NSEF0UK / 2026-07-20T08:00:52.478Z / note: runtime verify GREEN per operator 2026-07-20 — 0.4.1 rate-diff confirmed on prod. -->
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -17,14 +17,18 @@
|
||||
- [ ] **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.
|
||||
⚪ ready (unblocked — [[snolla-local-admin-restore]] DONE). **Отложен в след. сессию.** Branch: master.
|
||||
|
||||
## Depends on / blocks
|
||||
- Blocked by: [[snolla-local-admin-restore]] (админ для контент-инспекции).
|
||||
- ~~Blocked by: [[snolla-local-admin-restore]]~~ — DONE (локальный админ жив, 6 `/admin` URL).
|
||||
|
||||
## Decisions (locked 2026-07-20)
|
||||
- **Repo:** `victor/on.snolla.com` (на git.kzntsv.site), структура-калька `victor/tandemmebel.ru`.
|
||||
- **Admin-креды:** в БД `MoreThenCms.dbo.Accounts` (читать SQL-user'ом `snolla` / SA `pass mssql-vds/sa-password`). Логин-форма `/admin/account/login`.
|
||||
- **Контент-инспекция:** hosts→127.0.0.1 активен (Task A), `http://on.snolla.com/` рендерит локальный IIS из той же MoreThenCms DB → контент == прод; `/admin` — контент-дерево.
|
||||
|
||||
## Open Q
|
||||
- Имя репо (`victor/on-snolla`? `victor/on.snolla.com`?).
|
||||
- Сложность посадочной (объём шаблонов) — узнается при реконструкции.
|
||||
- Сложность посадочной (объём шаблонов) — узнается при реконструкции (Title="Internal Site", culture `en` — вероятно простой лендинг).
|
||||
|
||||
## Rollback
|
||||
Образ предыдущего тега в registry / revert DNS reg.ru→80.64.31.36 (RUVDS IIS жив пока DNS не флипнут).
|
||||
@@ -11,24 +11,29 @@ Catch-all `*:80` + `hosts`-override → `127.0.0.1 <alias>.snolla.com`. Один
|
||||
- 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-цикл.
|
||||
- [x] **0. Verify source (read-only SSH RUVDS)** — plink `-hostkey` (fingerprint `SHA256:r/vSKU5WzH4B8T7RiXyXlg0D8XZ9hlBxzmdrPzuPWzE`, креды `pass show ruvds-iis/full-env`). `C:\sites\snolla\` есть, IIS site `snolla` Started, catch-all `*:80` + SNI `*.snolla.com`/real-domains. **Web.config уже → `mssql.kzntsv.site,1433;Catalog=MoreThenCms;User Id=snolla;Password=...` (тот же snolla SQL-user что stostayer.old).** MinIO drop-in применён: assets/galleries/images/scripts/stylesheets/watermarks → `FileStorage.S3.*`, endpoint `minio.kzntsv.site`, **ключи реальные** (placeholder_count=0, accessKey=20/secretKey=40). Кэши Local.
|
||||
- [x] **1. Копировать `C:\sites\snolla\`** RUVDS→локально — **selective tar-over-SSH ~100MB** (НЕ 8.76GB): `bin`(53MB, вкл S3 DLLs)+`Admin`(6MB)+`Areas`+`Views`+`Web.config`+`App_Data/{maxMind,searchIndexes,contentCache}`, исключая stale `App_Data/{assets(215MB),galleries(5.5GB),themes(2.8GB),uploadCache(145MB)}` + `bin.old`. Команда: `plink ... "tar -C C:/sites/snolla -cf - --exclude=App_Data/assets --exclude=App_Data/galleries --exclude=App_Data/themes --exclude=App_Data/uploadCache --exclude=bin.old --exclude=App_Data/imageCache ." | tar -C /c/sites/snolla -xf -`.
|
||||
- [x] **2. Репойнт conn-string** — НЕ НУЖНО, RUVDS-Web.config уже на `mssql.kzntsv.site` (cutover 2026-05). DB-креды `snolla`/`fXkH4@8O%3pc` (plaintext в Web.config, тот же user работает для MoreThenCms+stostayer catalogs). Q2 закрыта.
|
||||
- [x] **3. MinIO-ключи** — уже реальные в скопированном Web.config (см. step 0). Pass-lookup не понадобился.
|
||||
- [x] **4. IIS-сайт `snolla`** — elevated `scripts/local-snolla-admin-restore/setup-local-snolla-admin.ps1` (ASCII-only, PS5.1 BOM-less-safe): AppPool `snolla` (.NET v4.0, AppPoolIdentity, recycling.memory 200MB), IIS site `*:80` catch-all, ACL `IIS AppPool\snolla:(OI)(CI)(M)`.
|
||||
- [x] **5. hosts-override** — `127.0.0.1 tandemmebel/labtools/labtoolspro/emspb/kupimknigi/on .snolla.com` в `hosts` (marker `# snolla-local-admin`, idempotent).
|
||||
- [x] **6. FW** — `New-NetFirewallRule block-inbound-80-snolla-local` (Action Block, loopback не фильтруется → local-only). URL Rewrite rule НЕ ставил (скопированный inert).
|
||||
- [x] **7. Smoke** — `curl --noproxy '*' -H "Host: <alias>.snolla.com" http://127.0.0.1/admin/account/login` → **200 для всех 6** (tandemmebel/labtools/labtoolspro/emspb/kupimknigi/on). HTML = реальная MoreThenCms-логинформа (`<title>SNOLLA</title>`, `<form action="/admin/login">`). hosts + IIS listening confirmed.
|
||||
|
||||
## Status
|
||||
⚪ ready (ждёт отмашки оператора на SSH RUVDS + креды). Branch: master.
|
||||
🟢 DONE (2026-07-20). Branch: master. Local .NET-админ поднят, 6 адресов `/admin` живые.
|
||||
|
||||
## Verify-факт
|
||||
- Catch-all routing: `appSettings` = `sitePath=C:\sites\snolla\`, `primaryDomain=snolla.com`, `primaryAlias=on` (default-site = on.snolla.com "Internal Site"); siteId резолвится из Host-header (нет siteId в appSettings, в отличие от per-site stostayer.old). `customErrors mode="Off"`.
|
||||
- bin/ несёт `MoreThenCms.FileStorage.S3.dll` + `AWSSDK.Core.dll` + `AWSSDK.S3.dll` (drop-in).
|
||||
|
||||
## 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-список.
|
||||
- ~~MoreThenCms DB app-аккаунт~~ — ЗАКРЫТА: `snolla` SQL-user уже в Web.config (plaintext), работает для MoreThenCms catalog.
|
||||
- Включать все ~60 сайтов или только тираж(5)+on.snolla.com — пока 6 в hosts; catch-all даёт все, расширить = дописать `<alias>.snolla.com` в hosts.
|
||||
- **MinIO upload-acceptance** (не автотест): оператор логинится в админку, заливает тест-ассет → проверяет объект в MinIO `minio.kzntsv.site` (bucket assets). S3-провайдер был admin-self-test green на RUVDS, Web.config скопирован 1:1 → должен работать.
|
||||
|
||||
## Rollback
|
||||
Удалить IIS-сайт `snolla` + `C:\sites\snolla\` + откатать hosts. Прод-RUVDS не тронут.
|
||||
Удалить IIS-сайт `snolla` + `C:\sites\snolla\` + откатать hosts (снести marker `# snolla-local-admin`). FW-block-rule можно оставить. Прод-RUVDS не тронут.
|
||||
96
.wiki/concepts/on-snolla-vds-deploy-runbook.md
Normal file
96
.wiki/concepts/on-snolla-vds-deploy-runbook.md
Normal file
@@ -0,0 +1,96 @@
|
||||
---
|
||||
title: on.snolla.com snolla-app — VDS deploy runbook (cutover 2026-07-20)
|
||||
type: concept
|
||||
tags: [on-snolla, snolla, vds, deploy, docker, portainer, traefik, runbook, migration, landing]
|
||||
related: [[../entities/vds-kzntsv], [../entities/ruvds-iis-host], [tandemmebel-vds-deploy-runbook], [snolla-live-prod-inplace-image-bump], [portainer-stack-management-vds], [snolla-local-admin-and-on-snolla-migration-design]]
|
||||
updated: 2026-07-20
|
||||
---
|
||||
|
||||
# on.snolla.com → VDS deploy runbook
|
||||
|
||||
Вынос посадочной `on.snolla.com` (snolla-app, `@snollajs/snolla` **0.42.1**, server-side Liquid) с
|
||||
[[../entities/ruvds-iis-host]] (catch-all CMS, 80.64.31.36) в docker-контейнер на [[../entities/vds-kzntsv]]
|
||||
(89.253.255.94), за traefik. Паттерн = [[tandemmebel-vds-deploy-runbook]]. Отличие: **лендинг** (1 Page `/`
|
||||
+ 2 StaticPages), БЕЗ блога/каталога/e-commerce → reconstruction = layout.liquid byte-identical prod-HTML.
|
||||
Culture `en`. Спека: [[snolla-local-admin-and-on-snolla-migration-design]] §Task B.
|
||||
|
||||
## Артефакты
|
||||
- **Код:** `victor/on.snolla.com` @ `473923e494db` (apps/web, snolla 0.42.1). Структура-калька tandemmebel.ru.
|
||||
`deploy/Dockerfile` (multi-stage node:22-slim, `yarn install --immutable`, non-root, healthcheck `/robots.txt`).
|
||||
- **Образ:** `registry.kzntsv.site/on-snolla:473923e494db` (+`:latest`). Имя **`on-snolla`** (= стек/контейнер).
|
||||
Собран НА VDS (обход traefik-499).
|
||||
- **Стек Portainer:** `on-snolla` (**Id 22**, endpoint 1). Source-of-truth compose: `admin/host-stacks/vds-kzntsv/on-snolla.compose.yml`.
|
||||
- **siteId:** `B9ECDB50-2B93-4CE5-B238-A9918B3F9CF7` (non-secret, в `production.json`).
|
||||
- **siteUrl:** `https://on.snolla.com` (в `production.json`).
|
||||
- **Runtime env (8 секретов):** `DB_USER DB_PASSWORD IMGPROXY_KEY IMGPROXY_SALT S3_ACCESS_KEY_ID S3_SECRET_ACCESS_KEY SMTP_USER SMTP_PASSWORD`
|
||||
— Portainer stack env (переиспользованы verbatim из tandemmebel стека 20 — общая snolla-инфра). НЕ в образе, НЕ в git.
|
||||
- **mem_limit:** `512m`.
|
||||
|
||||
## Site model (MoreThenCms DB, siteId B9ECDB50)
|
||||
- 1 Page `/` (template `content_page`, `customDefaultLayout=layout`). **Content-поля пустые** → весь
|
||||
bootstraptor-лендинг baked в `views/layout.liquid` (byte-identical prod). `{{ item.content }}` (пуст) wired.
|
||||
- Form "Join us" (Path `/`, FormTemplate `join_us`: first_name/last_name/email/website/description/captcha)
|
||||
baked в `layout.liquid`; POST `/` → snolla `forms` middleware → `form_ajax_response.liquid` (AJAX replace).
|
||||
Legacy reCAPTCHA v1 в разметке мертва (Google shut down v1) — parity с продом, НЕ чиним.
|
||||
- StaticPages: `/yandex_7a510ac1f8311fca.html` (verification, IncludeInSitemap=true), `/4a052808276c.html` (not in sitemap).
|
||||
- `/c` → **404** (stale dead-link в .NET sitemap; snolla-app sitemap тоже его несёт → parity `/`+`/c`+`/yandex`).
|
||||
- Theme assets `/themes/c406a987ebe14244b0eefe7b8f959a6f/{css,js,images}/*` — из MinIO bucket `themes` (snolla
|
||||
`themeFiles` middleware; пути literal в `layout.liquid`).
|
||||
- `/admin` — **публичного `on.snolla.com/admin` не существует** (никогда не было: RUVDS catch-all IIS не
|
||||
маршрутизировал /admin на публичном on.snolla.com — cert на 80.64.31.36:443 SNI on.snolla.com = чужой
|
||||
`CN=kupimknigi.spb.ru`, /admin → 404). Админка — только **локальный catch-all IIS `snolla`** (Task A,
|
||||
воркстейшн). Site alias переименован `on`→`internal` (2026-07-20), доступ = `http://internal.snolla.com/admin`
|
||||
через hosts override → 127.0.0.1 → 302→login. **Web.config `primaryAlias`** тоже обновлён `on`→`internal`
|
||||
(default-site resolution; иначе catch-all NRE-500 на ВСЕХ запросах — primaryAlias ссылается на алиас,
|
||||
переименование сайта без обновления primaryAlias ломает весь catch-all). НЕ часть snolla-app.
|
||||
|
||||
## Cutover 2026-07-20 (первый вынос на VDS — DNS-gated)
|
||||
1. **Build на VDS** (archive `473923e494db` → `~/build/on-snolla` → `docker build -f deploy/Dockerfile
|
||||
--build-arg VERDACCIO_TOKEN -t .../on-snolla:473923e494db -t .../on-snolla:latest . && push`). Guard:
|
||||
`config/default.json` ABSENT в архиве (.dockerignore), пин snolla = 0.42.1.
|
||||
2. **Throwaway-staging :5077** из собранного env (8 секретов inline, т.к. нового live-контейнера ещё нет —
|
||||
секреты общие с тиражом). `docker run -d --name on-snolla-staging --env-file .staging.env -p 127.0.0.1:5077:5000`.
|
||||
Healthy. robots/`/`/sitemap 200.
|
||||
3. **Completeness-gate С VDS** — sitemapindex разворот. **NEW==PROD locs: 3 = 3 IDENTICAL** (`/`, `/c`, `/yandex_…`).
|
||||
Self-consistency: `/`→200, `/yandex`→200, `/c`→404 (dead-link, parity с прод-оракулом — prod /c тоже 404).
|
||||
**Byte-parity:** homepage + /yandex **byte-identical** staging vs prod (RUVDS, via `--resolve :443:80.64.31.36`).
|
||||
GREEN = 0 регрессий.
|
||||
4. **Portainer стек 22** создан со **staging-Host** `on-snolla.vds.kzntsv.site` (wildcard → VDS), LE=default cert.
|
||||
Healthy за traefik. (`create-stack.mjs` node-скрипт, Portainer JWT auth, env array 8/8, `mem_limit 512m`.)
|
||||
5. **DNS flip** — operator: reg.ru `on.snolla.com` A `80.64.31.36` → `89.253.255.94`.
|
||||
6. **Verify авторит. NS** — `nslookup on.snolla.com ns1/ns2.reg.ru` = `89.253.255.94` (BEFORE traefik rule swap —
|
||||
memory `operator-dns-flip-verify-domain-before-cutover`: wrong domain burns LE rate-limit). Public resolvers propagated.
|
||||
7. **PUT стека 22** — rule `Host(on-snolla.vds.kzntsv.site)` → `Host(on.snolla.com)`, env-preserving (8/8),
|
||||
`prune:false, pullImage:false`. node `cutover-put.mjs` (Portainer JWT; **re-auth right before PUT** —
|
||||
jwt из GET-фазы успел протухнуть к моменту PUT, первый PUT дал 401). PUT 200.
|
||||
8. **Poll** — контейнер healthy, **LE-серт issued on first hit**: CN=on.snolla.com, issuer YR1, until 2026-10-18.
|
||||
9. **Live-smoke С VDS + external** — `https://on.snolla.com/{robots.txt,/,/sitemap.xml,/yandex_…}` = 200,
|
||||
`/c` = 404 parity. TLS verify `ssl_verify_result=0` (trusted LE chain). Homepage **byte-identical** prod-HTML.
|
||||
|
||||
## Гочи (специфичные)
|
||||
- **snolla `robotsTxt` middleware падает на undefined `app.locals.domain`** — on.snolla.com НЕ имеет row в
|
||||
MoreThenCms `Domains` (served by primaryDomain без per-domain row). `robotsTxt.js` читает
|
||||
`res.app.locals.domain.robotsTxt` без null-guard → GET /robots.txt (и Dockerfile healthcheck) крашится 500.
|
||||
**Фикс в `apps/web/index.js`**: после `initApp`, если `!app.locals.domain`, synthesized `{robotsTxt: site.robotsTxt}`
|
||||
(only robotsTxt.js reads locals.domain; theme resolution uses site.activeThemeId — safe). Без мутации shared DB.
|
||||
**Альтернатива** (не применена): добавить Domains row (Name=on.snolla.com, SiteId=B9ECDB50, Public=1, ThemeId=null)
|
||||
— но это мутация shared prod MoreThenCms; предпочтён app-code fallback.
|
||||
- **Form "Join us" не имеет Liquid form-tag** — snolla не предоставляет form-rendering tag. Форма HTML baked в
|
||||
`layout.liquid` (поля по FormTemplate `join_us`); POST обрабатывает `forms` middleware (мэтч по Path `/`).
|
||||
`form_ajax_response.liquid` — AJAX-ответ (`$form.replaceWith(response)`).
|
||||
- **`/c` в sitemap — dead-link** — snolla SitemapService эмбитит `/c` из sections-source, но страница 404.
|
||||
Prod-оракул идентичен (404) → benign parity, не регрессия.
|
||||
- **hosts override на воркстейшне** — Task A оставил `127.0.0.1 on.snolla.com` в hosts (локальный админ catch-all).
|
||||
External verify прод-on.snolla.com с воркстейшна = только через `curl --resolve on.snolla.com:443:89.253.255.94`
|
||||
(иначе попадёшь в локальный IIS). См. memory `workstation-lan-dns-serves-local-cms-copy`.
|
||||
- **Portainer JWT short-lived** — GET stack + GET file + PUT в одном скрипте: jwt из GET-фазы может протухнуть
|
||||
к PUT. Re-auth (`POST /api/auth`) прямо перед PUT. API-key `ptr_*` даёт 401 (см. [[portainer-stack-management-vds]]).
|
||||
- **Образных rollback-тегов пока нет** — первый deploy, `473923e494db` = `:latest`. ~~Rollback = revert DNS (RUVDS жив).~~ RUVDS DECOMM 2026-07-21 — rollback только образ-тегом.
|
||||
|
||||
## Rollback
|
||||
- ~~**DNS (предпочт, мгновенный):** revert reg.ru `on.snolla.com` A → `80.64.31.36` (RUVDS IIS жив, не тронут).~~ **НЕАКТУАЛЬНО с 2026-07-21** — [[../entities/ruvds-iis-host]] DECOMM (погашен у провайдера). RUVDS более не rollback-target.
|
||||
- **Образный (рабочий):** PUT стека 22 назад на предыдущий тег (rollback-теги в registry). `473923e494db` = `:latest` — первый deploy, предыдущего тега нет; с этого дня ведём rollback-теги на каждый bump.
|
||||
|
||||
## Связанное
|
||||
- on.snolla.com admin (`/admin`) остаётся на RUVDS .NET — catch-all IIS `snolla` (см. [[snolla-local-admin-and-on-snolla-migration-design]] §Task A).
|
||||
- Тираж snolla на VDS: labtools.ru(17), emspb(18), labtools.pro(19), tandemmebel(20), kupimknigi(21), **on-snolla(22)**.
|
||||
@@ -1,15 +1,36 @@
|
||||
---
|
||||
title: RUVDS IIS Host (Windows Server 2025 Core) — 80.64.31.36
|
||||
title: RUVDS IIS Host (Windows Server 2025 Core) — 80.64.31.36 — DECOMM 2026-07-21
|
||||
type: entity
|
||||
tags: [hardware, vds, ruvds, windows, iis, cms, snolla, kupimknigi]
|
||||
tags: [hardware, vds, ruvds, windows, iis, cms, snolla, kupimknigi, decommissioned]
|
||||
sources: [../sources/iis-migration-to-ruvds-2026-05-23.md, ../sources/ruvds-backup-daily-kreknin-2026-05-24.md]
|
||||
updated: 2026-06-11
|
||||
updated: 2026-07-21
|
||||
---
|
||||
|
||||
# RUVDS IIS Host
|
||||
# RUVDS IIS Host — ⛔ DECOMM 2026-07-21
|
||||
|
||||
> **Декоммишнен 2026-07-21.** Погашен у провайдера, забыт. Деньги экономим. Финальный offsite-снимок на kreknin верифицирован (см. § Decommission ниже). Rollback-target для всех мигрированных snolla-сайтов **более недоступен** — откат только образ-тегом в registry / DNS уже на VDS.
|
||||
>
|
||||
> Что ниже — историческая запись живого хоста (куплен 2026-05-23, DECOMM 2026-07-21, срок жизни ~2 месяца). Креды/доступ сохранены в `pass` ретроспективно, хост выключен.
|
||||
|
||||
Облачный Windows-VDS у [RUVDS](https://ruvds.com), DC Королёв. Куплен 2026-05-23 как destination для миграции IIS-хостинга с [[windows-recovery-host]] — closing SPOF домашней машины для prod CMS сайтов (snolla CMS multi-tenant). Это **отдельный VDS** от [[vds-kzntsv]] (Rusonyx Linux, инфра-стек): RUVDS = только IIS catch-all для CMS hostnames, Rusonyx VDS = gitea/verdaccio/registry/DB park.
|
||||
|
||||
## Decommission (2026-07-21)
|
||||
|
||||
Сессия 2026-07-21: аудит «что осталось на RUVDS перед отказом от провайдера».
|
||||
|
||||
**Живого публично не осталось** — всё snolla-тираж уехало на VDS:
|
||||
- Публичный DNS → RUVDS (`80.64.31.36`): **только `rimiz.ru`/`www.rimiz.ru`** — и тот труп (HTTP 404 на RUVDS; сломан с 2026-05-19 iis-migration cleanup, не чинен, не мигрирован).
|
||||
- Всё остальное → VDS `89.253.255.94`: `on.snolla.com`, `snolla.com` apex, `kupimknigi.spb.ru`, `tandemmebel.ru`/www, `labtools.ru`/www, `labtools.pro`/www, `emspb.ru`/www, `pilorama98.ru`/www, `maljarka.tandemmebel.ru`, `ics-artmaterials`/`pilorama98`/`sestech`/`artmone`/`rimiz` `.snolla.com`. Smoke VDS 2026-07-21: 200 (кроме `snolla.com` apex — 404 TRAEFIK DEFAULT CERT, нет Host-правила; мёртв везде, отдельная мелочь, НЕ блокировала DECOMM).
|
||||
- VDS snolla-стеки Portainer: labtools(17)/emspb(18)/labtools-pro(19)/tandemmebel(20)/kupimknigi(21)/on-snolla(22).
|
||||
- Локальный .NET-админ (catch-all IIS `snolla` на воркстейшне, [[snolla-local-admin-and-on-snolla-migration-design]] §Task A) от RUVDS НЕ зависит — читает `mssql.kzntsv.site` + `minio.kzntsv.site` (оба на vds-kzntsv).
|
||||
|
||||
**Финальный offsite-снимок верифицирован 2026-07-21:**
|
||||
- `RUVDS-Backup-Daily` последний прогон 2026-07-21 04:30:01, `LastTaskResult=0`, 0 missed. DONE 72 мин (лог `C:\ProgramData\backup\logs\2026-07-21.log`): IIS-config snapshot + 13 certs exported (non-exportable pvt-key warning benign) + rclone sync snolla/applicationHost/iis-backup/certs/ssh-config + retention keep 7.
|
||||
- kreknin `/volume1/NetBackup/ruvds-iis/2026-07-21/` = **8.8G**, создан 05:37, полный (`sites/`+`iis-config/`+`iis-backup-webconfiguration/`+`certs/`+`ssh-config/`). 7 снимков в retention (2026-07-15…07-21).
|
||||
- Динамика (.NET-админ не несёт) — MSSQL+MinIO на vds-kzntsv, бэкапятся отдельно (см. [[backup-inventory-2026-06]]). Сам .NET-админ = статичные бинарники MoreThenCms + S3 drop-in, восстанавливаемо из source + локальная копия на воркстейшне.
|
||||
|
||||
**Loose end — RESOLVED 2026-07-21:** `rimiz.ru`/`www.rimiz.ru` A-запись переправлена оператором на `89.253.255.94`. Авторит. NS ns1/ns2.reg.ru = `89.253.255.94` (verified); public resolvers ещё держат stale `80.64.31.36` по TTL 86400 — сбросится в сутки. На RUVDS больше НИ ОДИН публичный домен не смотрит.
|
||||
|
||||
## Hardware / tariff
|
||||
|
||||
- **Vendor:** RUVDS (https://ruvds.com)
|
||||
|
||||
61
host-stacks/vds-kzntsv/on-snolla.compose.yml
Normal file
61
host-stacks/vds-kzntsv/on-snolla.compose.yml
Normal file
@@ -0,0 +1,61 @@
|
||||
# on-snolla — посадочная on.snolla.com (snolla-app, server-side Liquid, node) на vds-kzntsv (89.253.255.94).
|
||||
#
|
||||
# STAGING-FIRST. Source-of-truth этого compose — admin-репо; применяется через Portainer API/UI
|
||||
# (VDS-rule: стеки через Portainer, не ssh+compose).
|
||||
#
|
||||
# Модель: монолит @snollajs/snolla (0.42.1) / core / liquid / data — читает БД-контент MoreThenCms
|
||||
# (mssql.kzntsv.site) + server-side Liquid render. Ассеты из MinIO (minio.kzntsv.site). In-process sharp,
|
||||
# delivery=serve-bytes, cache=local-variant. imgproxy в путях нет (как tandemmebel — сырой /imgproxy -> 404 норма).
|
||||
# node-config: NODE_ENV=production -> default(dev,gitignored)+production.json+ENV-override.
|
||||
# ЛЕНДИНГ (1 Page / + 2 StaticPages), БЕЗ блога/каталога/e-commerce.
|
||||
#
|
||||
# Образ собирается АДМИНОМ на VDS из victor/on.snolla.com/deploy/Dockerfile (build-arg VERDACCIO_TOKEN,
|
||||
# @snollajs/* из verdaccio.kzntsv.site). Тег = git-sha репо on.snolla.com (текущий 473923e494db).
|
||||
# Homepage render byte-identical прод-HTML (verified direct diff + completeness-gate 3/3 loc parity 2026-07-20).
|
||||
#
|
||||
# Домен: LIVE — on.snolla.com (cert LE HTTP-01, CN=on.snolla.com, issued 2026-07-20, until 2026-10-18).
|
||||
# Cutover завершён 2026-07-20: DNS reg.ru on.snolla.com A 80.64.31.36 -> 89.253.255.94 (operator flip,
|
||||
# авторит. NS ns1/ns2.reg.ru verified -> VDS), traefik rule staging->боевой (LE-порядок соблюдён),
|
||||
# LE-серт issued on first hit. Live-smoke GREEN, homepage byte-identical прод-HTML, sitemap 3/3 parity.
|
||||
# Предыстория: жил на RUVDS IIS (80.64.31.36) до 2026-07-20. RUVDS IIS не тронут (rollback = revert DNS).
|
||||
# План отката = revert DNS reg.ru -> 80.64.31.36 (RUVDS IIS жив) ИЛИ PUT стека 22 назад на тег (пока
|
||||
# единственный тег 473923e494db = :latest — первый deploy; образных rollback-тегов пока нет).
|
||||
#
|
||||
# Runtime egress: mssql.kzntsv.site:1433, minio.kzntsv.site:443 (оригиналы + variant-cache), smtp.yandex.ru:465.
|
||||
#
|
||||
# Секреты — env на VDS (Portainer stack env), НЕ в образ, НЕ в git. Значения ${...} инжектит Portainer
|
||||
# из stack-переменных (переиспользованы verbatim из tandemmebel стека 20 — общая snolla-инфра). Контракт:
|
||||
# DB_USER DB_PASSWORD IMGPROXY_KEY IMGPROXY_SALT S3_ACCESS_KEY_ID S3_SECRET_ACCESS_KEY SMTP_USER SMTP_PASSWORD
|
||||
# siteId=B9ECDB50-2B93-4CE5-B238-A9918B3F9CF7 — non-secret, в production.json (не env). Culture en. siteUrl=https://on.snolla.com
|
||||
|
||||
services:
|
||||
on-snolla:
|
||||
container_name: on-snolla
|
||||
image: registry.kzntsv.site/on-snolla:473923e494db # git-sha victor/on.snolla.com master 473923e494db (snolla 0.42.1). rollback-теги в registry: 473923e494db (:latest он же — первый deploy, отката пока нет, revert DNS -> RUVDS).
|
||||
restart: unless-stopped
|
||||
mem_limit: 512m # guardrail: snolla baseline ~100-200M; OOM -> restart. standalone-compose -> mem_limit (НЕ deploy.resources, swarm-only).
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
TZ: Europe/Moscow
|
||||
# --- runtime-секреты (значения из Portainer stack env; НЕ хранить тут) ---
|
||||
DB_USER: ${DB_USER}
|
||||
DB_PASSWORD: ${DB_PASSWORD}
|
||||
IMGPROXY_KEY: ${IMGPROXY_KEY}
|
||||
IMGPROXY_SALT: ${IMGPROXY_SALT}
|
||||
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID}
|
||||
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY}
|
||||
SMTP_USER: ${SMTP_USER}
|
||||
SMTP_PASSWORD: ${SMTP_PASSWORD}
|
||||
networks:
|
||||
- proxy
|
||||
labels:
|
||||
traefik.enable: "true"
|
||||
traefik.http.routers.on-snolla.entrypoints: websecure
|
||||
# LIVE (cutover 2026-07-20). Rollback = Host(`on-snolla.vds.kzntsv.site`) + revert DNS -> 80.64.31.36.
|
||||
traefik.http.routers.on-snolla.rule: Host(`on.snolla.com`)
|
||||
traefik.http.routers.on-snolla.tls.certresolver: letsEncrypt
|
||||
traefik.http.services.on-snolla.loadbalancer.server.port: "5000"
|
||||
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
19
scripts/local-snolla-admin-restore/ruvds-verify.ps1
Normal file
19
scripts/local-snolla-admin-restore/ruvds-verify.ps1
Normal file
@@ -0,0 +1,19 @@
|
||||
$ErrorActionPreference='SilentlyContinue'
|
||||
Write-Output "=== IIS sites ==="
|
||||
Import-Module WebAdministration
|
||||
Get-Website | ForEach-Object {
|
||||
$b = (Get-WebBinding -Name $_.Name).bindingInformation -join ' ; '
|
||||
"{0} | {1} | {2} | {3}" -f $_.Name, $_.State, $_.PhysicalPath, $b
|
||||
}
|
||||
Write-Output "=== C:\sites\snolla ==="
|
||||
if (Test-Path 'C:\sites\snolla') {
|
||||
$f = Get-ChildItem 'C:\sites\snolla' -File
|
||||
"exists; top-files=" + $f.Count
|
||||
$wc = 'C:\sites\snolla\Web.config'
|
||||
if (Test-Path $wc) {
|
||||
"Web.config size=" + (Get-Item $wc).Length
|
||||
Write-Output "=== Web.config storageType / minio lines ==="
|
||||
Select-String -Path $wc -Pattern 'storageType|minio\.kzntsv|FileStorage\.S3|Initial Catalog|Data Source' | ForEach-Object { $_.Line.Trim() }
|
||||
} else { "Web.config MISSING" }
|
||||
} else { "C:\sites\snolla MISSING" }
|
||||
Write-Output "=== DONE ==="
|
||||
@@ -0,0 +1,75 @@
|
||||
# setup-local-snolla-admin.ps1 - restore local catch-all IIS site 'snolla' (admin for tirazh + on.snolla.com)
|
||||
# RUN FROM elevated PowerShell: Set-ExecutionPolicy -Scope Process Bypass; & 'C:\Users\vitya\projects\.admin\scripts\local-snolla-admin-restore\setup-local-snolla-admin.ps1'
|
||||
# Source: C:\sites\snolla\ already copied from RUVDS (selective ~100MB, Web.config -> mssql.kzntsv.site + MinIO S3).
|
||||
|
||||
$logPath = 'C:\Users\vitya\projects\.admin\.tmp\setup-log.txt'
|
||||
Start-Transcript -Path $logPath -Force | Out-Null
|
||||
$ErrorActionPreference = 'Stop'
|
||||
try {
|
||||
Import-Module WebAdministration
|
||||
|
||||
$siteName = 'snolla'
|
||||
$poolName = 'snolla'
|
||||
$physPath = 'C:\sites\snolla'
|
||||
$aliases = @('tandemmebel.snolla.com','labtools.snolla.com','labtoolspro.snolla.com','emspb.snolla.com','kupimknigi.snolla.com','internal.snolla.com')
|
||||
|
||||
Write-Host "== 1. AppPool $poolName =="
|
||||
if (Test-Path "IIS:\AppPools\$poolName") {
|
||||
Write-Host " exists, ensuring config"
|
||||
} else {
|
||||
New-WebAppPool -Name $poolName | Out-Null
|
||||
}
|
||||
Set-ItemProperty "IIS:\AppPools\$poolName" -Name managedRuntimeVersion -Value 'v4.0'
|
||||
Set-ItemProperty "IIS:\AppPools\$poolName" -Name processModel.identityType -Value 'ApplicationPoolIdentity'
|
||||
Set-ItemProperty "IIS:\AppPools\$poolName" -Name recycling.periodicRestart.memory -Value 200
|
||||
|
||||
Write-Host "== 2. IIS site $siteName (catch-all *:80) =="
|
||||
if (Test-Path "IIS:\Sites\$siteName") {
|
||||
Write-Host " exists - removing to recreate cleanly"
|
||||
Remove-Website -Name $siteName
|
||||
}
|
||||
# catch-all HTTP on *:80 (no HostHeader = matches any Host header)
|
||||
New-Website -Name $siteName -PhysicalPath $physPath -ApplicationPool $poolName -Port 80 -Force | Out-Null
|
||||
Set-ItemProperty "IIS:\Sites\$siteName" -Name physicalPath -Value $physPath
|
||||
|
||||
Write-Host "== 3. ACL: IIS AppPool\$poolName (OI)(CI)(M) on $physPath =="
|
||||
icacls $physPath /grant "IIS AppPool\${poolName}:(OI)(CI)(M)" /T /C | Out-Null
|
||||
|
||||
Write-Host "== 4. hosts-override (127.0.0.1 aliases) =="
|
||||
$hostsFile = "$env:windir\System32\drivers\etc\hosts"
|
||||
$hostsContent = Get-Content $hostsFile -Raw -ErrorAction SilentlyContinue
|
||||
$marker = '# snolla-local-admin'
|
||||
if ($hostsContent -notmatch [regex]::Escape($marker)) {
|
||||
$line = "`r`n$marker`r`n127.0.0.1 $($aliases -join ' ')`r`n"
|
||||
Add-Content -Path $hostsFile -Value $line -Encoding ASCII
|
||||
Write-Host " added hosts entries"
|
||||
} else {
|
||||
Write-Host " hosts entries already present (marker found)"
|
||||
}
|
||||
|
||||
Write-Host "== 5. FW: block inbound TCP 80 (local-only guard; loopback not filtered) =="
|
||||
$fwName = 'block-inbound-80-snolla-local'
|
||||
if (-not (Get-NetFirewallRule -DisplayName $fwName -ErrorAction SilentlyContinue)) {
|
||||
New-NetFirewallRule -DisplayName $fwName -Direction Inbound -Protocol TCP -LocalPort 80 -Action Block -Profile Any | Out-Null
|
||||
Write-Host " block rule added"
|
||||
} else { Write-Host " block rule already present" }
|
||||
|
||||
Write-Host "== 6. Start =="
|
||||
Start-WebAppPool $poolName
|
||||
Start-Website $siteName
|
||||
Start-Sleep -Seconds 3
|
||||
Write-Host " pool state: $((Get-WebAppPoolState $poolName).Text)"
|
||||
Write-Host " site state: $((Get-WebsiteState $siteName).Text)"
|
||||
|
||||
Write-Host "== 7. Smoke (curl --noproxy bypasses VPN-proxy localhost swallow) =="
|
||||
foreach ($a in $aliases) {
|
||||
$code = & curl.exe --noproxy '*' -s -o NUL -w "%{http_code}" -H "Host: $a" "http://127.0.0.1/admin/account/login" 2>$null
|
||||
Write-Host " http://$a/admin/account/login -> $code"
|
||||
}
|
||||
Write-Host "== DONE - open http://tandemmebel.snolla.com/admin in browser =="
|
||||
Write-Host "(if login form not 200 - check C:\Logs\snolla\log*.txt and eventvwr IIS)"
|
||||
} catch {
|
||||
Write-Host "FATAL: $_"
|
||||
Write-Host $_.ScriptStackTrace
|
||||
}
|
||||
Stop-Transcript | Out-Null
|
||||
Reference in New Issue
Block a user