Files
admin/.wiki/concepts/on-snolla-vds-deploy-runbook.md
vitya f56eb2f800 feat(on-snolla): v3 cutover LIVE — snolla 0.43.2 (aws-sdk v2→v3) + runbook migration
v3 pilot on.snolla.com end-goal (user 2026-07-30): bump @snollajs/snolla
0.42.1→0.43.2 + @smithy resolutions (root package.json, on.snolla.com eb8c143).
Portainer PUT stack 22 → registry.kzntsv.site/on-snolla:eb8c143, env-preserving
8/8, mem_limit 512m. Live smoke GREEN: theme asset 200 97324 B (v3 aws-sdk v3
S3-direct read из vds MinIO 2025), sitemap+sub-sitemaps byte-identical, /c 404.
Rollback = 07db7e3 (v2, жив).

runbook migration (дисциплина): scripts/minio-split-cutover/runbook.md →
.wiki/concepts/minio-split-cutover-runbook.md (конвенция: runbook'и в .wiki/concepts/).
Creds normalized → pass show minio-vds/full-env (wiki-конвенция, не plaintext).
+ index.md, log.md, on-snolla-vds-deploy-runbook v3-секция.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-30 14:30:38 +03:00

12 KiB
Raw Blame History

title, type, tags, related, updated
title type tags related updated
on.snolla.com snolla-app — VDS deploy runbook (cutover 2026-07-20) concept
on-snolla
snolla
vds
deploy
docker
portainer
traefik
runbook
migration
landing
../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
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 /

Артефакты

  • Код: 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.comproduction.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).
  • /c404 (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 переименован oninternal (2026-07-20), доступ = http://internal.snolla.com/admin через hosts override → 127.0.0.1 → 302→login. Web.config primaryAlias тоже обновлён oninternal (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-snolladocker 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.3689.253.255.94.
  6. Verify авторит. NSnslookup 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 + externalhttps://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.

In-place bumps (после cutover)

  • 07db7e3 — MinIO split config-endpoint (v2, 2026-07-30). In-place bump стека 22 473923e494db→07db7e3 без правки package.json: только config/production.json s3.endpoint minio.kzntsv.site→minio.vds.kzntsv.site. snolla остался 0.42.1 (aws-sdk v2). Пилот S3-direct-path — theme asset 200 97324 B == live, v2 vs vds MinIO 2025 работает без @smithy pin. Rollback-тег 473923e494db. См. minio-split-cutover-runbook §B3 (Track B).
  • eb8c143 — v3 bump (aws-sdk v2→v3, 2026-07-30T11:28Z). End-goal (user). @snollajs/snolla 0.42.1→0.43.2 в apps/web/package.json + resolutions (@aws-sdk/client-s3 3.1005.0 exact + @smithy chain 5.3.11) в root package.json (optional determinism, single-instance — live verify доказал что 5.6.12 тоже работает, pin для version-stability). Commit eb8c143 pushed. Build на VDS (archive → ~/build/on-snolladocker build -f deploy/Dockerfile --build-arg VERDACCIO_TOKEN) → registry.kzntsv.site/on-snolla:eb8c143 (+:latest). Throwaway staging :5078 из env live-контейнера (8 секретов) → parity-gate GREEN (theme asset 200 97324 B byte-identical, sitemapindex+3 sub-sitemaps byte-identical, /c 404 parity). Portainer PUT stack 22 env-preserving (8/8, node in-memory put-stackНЕ PS Invoke-RestMethod), prune:false, pullImage:true, mem_limit 512m preserved. Live smoke GREEN: / 200, robots/sitemap/sub-sitemaps 200, /yandex 200, theme asset 200 97324 B (v3 aws-sdk v3 S3-direct read из vds MinIO 2025). TLS не тронут (LE до Oct 18). Back-compat шим s3ForcePathStyleforcePathStyle (v2-key ещё читается) — config-правки не требовались. Rollback = 07db7e3 (v2, жив в registry). См. minio-split-cutover-runbook §B3-v3 + snolla-live-prod-inplace-image-bump.

Гочи (специфичные)

  • 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).