Files
admin/.wiki/concepts/on-snolla-vds-deploy-runbook.md
vitya 50e263860d ops(on-snolla): rename site alias on->internal (admin at internal.snolla.com/admin)
- Sites.Alias+LoweredAlias on->internal (siteId B9ECDB50; PrimaryDomain on.snolla.com kept).
- Web.config primaryAlias on->internal (catch-all default-site; without it the whole
  catch-all NRE-500s on every request — primaryAlias references the renamed alias).
- hosts: on.snolla.com->internal.snolla.com under # snolla-local-admin marker.
- setup-local-snolla-admin.ps1 aliases array updated.
- runbook + NEXT_SESSION + memory updated.

VDS prod on.snolla.com unaffected (snolla-app uses config.siteId, not alias) — verified
byte-identical + smoke GREEN after rename. Incident: elevated hosts edit emptied hosts
to 0B (Get-Content -Raw returned null in RunAs context) — restored from Windows default
header + snolla-local-admin block. Memory snolla-catch-all-primaryalias-depends-on-alias.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-20 13:33:09 +03:00

9.3 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.

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

  • 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 жив).

Rollback

  • DNS (предпочт, мгновенный): revert reg.ru on.snolla.com A → 80.64.31.36 (RUVDS IIS жив, не тронут).
  • Образный (будущие bump'ы): PUT стека 22 назад на предыдущий тег (rollback-теги в registry).

Связанное

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