3rd site of v3 тираж (after on-snolla + kupimknigi, 3/6 GREEN). Bump 0dc0b4e: apps/web snolla→0.43.2 + resolutions (root). Endpoint fix 4f3314f (minio.vds.kzntsv.site) was in master but not in running v2 image 566d41c — v3 cutover also moved S3-direct read to vds minio. Staging :5080 parity-gate GREEN (home/theme byte-identical, sitemap 38 locs == live, order-parity). Portainer PUT stack 17 env-preserving 8/8, mem_limit 512m, prune:false pullImage:true. Live smoke GREEN, TLS untouched. Rollback = 566d41c (v2, in registry). Compose source-of-truth 566d41c→0dc0b4e. Runbook + handoff updated. Co-Authored-By: Claude <noreply@anthropic.com>
11 KiB
labtools.ru → VDS deploy runbook
Вынос labtools.ru (snolla-приложение, @snollajs/snolla, server-side Liquid) с ../entities/ruvds-iis-host
(catch-all CMS) в отдельный docker-контейнер на ../entities/vds-kzntsv (89.253.255.94), за traefik.
Модель — snolla-app (НЕ pilorama98.ru/Nuxt-contentApi): читает БД-контент MoreThenCms (mssql.kzntsv.site)
- ассеты из MinIO (
minio.kzntsv.site) через imgproxy.
Артефакты
- Код:
victor/labtools.ru@43e28ba(apps/web, parity ре-ревью №2 PASS).deploy/Dockerfile(multi-stage node:22-slim). - Образ:
registry.kzntsv.site/labtools:43e28ba(+:latest). Собран НА VDS (обход traefik-499), 114 MB content. - Стек Portainer:
labtools(Id 17, endpoint 1). Source-of-truth compose:admin/host-stacks/vds-kzntsv/labtools.compose.yml.
Сборка образа (на VDS)
# чистый git-archive (только tracked → без config/default.json и node_modules) на VDS
git -C ~/projects/labtools.ru archive --format=tar 43e28ba \
| ssh vitya@89.253.255.94 'rm -rf ~/build/labtools && mkdir -p ~/build/labtools && tar -x -C ~/build/labtools'
# build с build-arg VERDACCIO_TOKEN (pass vds-kzntsv/full-env VERDACCIO_CI_TOKEN), push из VDS
ssh vitya@89.253.255.94 'cd ~/build/labtools && docker build -f deploy/Dockerfile \
--build-arg VERDACCIO_TOKEN=<token> -t registry.kzntsv.site/labtools:43e28ba -t registry.kzntsv.site/labtools:latest . \
&& docker push registry.kzntsv.site/labtools:43e28ba && docker push registry.kzntsv.site/labtools:latest'
- VERDACCIO_TOKEN — build-time only (discarded build-стейдж; в финальный образ не попадает; docker linter warn-only).
config/default.json(dev-секреты) исключён.dockerignore— в образе толькоproduction.json+custom-environment-variables.json.
Runtime env-контракт (8 секретов — Portainer stack-env, НЕ в образ/git)
Маппинг env→config: apps/web/config/custom-environment-variables.json. Non-secret (host/siteId/endpoints) — в production.json.
| ENV | Значение | Источник |
|---|---|---|
DB_USER |
snolla |
web.config боя MoreThenCmsEntities |
DB_PASSWORD |
⟨секрет⟩ | web.config боя MoreThenCmsEntities (User Id=snolla) |
IMGPROXY_KEY |
⟨128hex⟩ | pass minio-vds/full-env (== сервер imgproxy books-vds — HMAC должен совпадать) |
IMGPROXY_SALT |
⟨128hex⟩ | pass minio-vds/full-env |
S3_ACCESS_KEY_ID |
⟨секрет⟩ | pass minio-vds/full-env (MINIO_ROOT_USER) |
S3_SECRET_ACCESS_KEY |
⟨секрет⟩ | pass minio-vds/full-env (MINIO_ROOT_PASSWORD) |
SMTP_USER |
noreply@snolla.com |
pass snolla-smtp/full-env |
SMTP_PASSWORD |
⟨секрет⟩ | pass snolla-smtp/full-env (SMTP_PASS; default.json имел dev-значение — НЕ брать оттуда) |
PORT — не переопределять (образ дефолтит 5000; EXPOSE 5000; healthcheck /robots.txt на $PORT). traefik service-port = 5000.
Runtime egress (наружу из proxy-сети)
mssql.kzntsv.site:1433 (БД-контент, обязателен) · minio.kzntsv.site:443 (ассеты) · imgproxy.kzntsv.site:443 · smtp.yandex.ru:465 (формы).
Staging smoke (2026-07-01, GREEN) — labtools.vds.kzntsv.site vs бой www.labtools.ru
- Все страницы меню (home/about/clients/contacts/cookie/privacy/6×products) — 200/200, дельта размера стабильна (длина хоста в canonical/og).
- Редиректы:
.php→301→/,/about/→301 (trailing-slash),/Products/Press-Forms→301→lowercase — 1:1 с боем. theme.cssиз MinIO — байт-в-байт (12248),Cache-Control: max-age=86400, public, must-revalidate./assets/<ownerId>/*.webpиз MinIO — байт-в-байт с боем (44444, 24354); content-typeapplication/octet-stream— как на бою.- Контейнер healthy (MSSQL+S3 подключены).
Cutover (live DNS) — ✅ ВЫПОЛНЕН 2026-07-02
⚠️ DNS зоны labtools.ru — на Yandex DNS (dns1/dns2.yandex.net), НЕ reg.ru (в отличие от labtools.pro/reg.ru). Порядок был:
- (оператор) Yandex DNS: A-записи
labtools.ru+www.labtools.ru→89.253.255.94(с RUVDS80.64.31.36). - (ops) verify перед traefik — критично: флип шёл неравномерно, dns1 и dns2 расходились (dns2 обновился первым, dns1 отставал). Гейт cutover = ОБА авторитетных NS согласованно отдают VDS по apex+www (иначе LE мог попасть на dns1→RUVDS→сжечь rate-limit). Публичные резолверы кэшировали до 6ч (TTL 21600) — для LE не критично (резолвит по авторитетному). Cм. memory [operator-dns-flip-verify-domain-before-cutover].
- (ops) после подтверждения обоих NS: стек
labtools(Id 17) traefik-rule →Host(\labtools.ru`) || Host(`www.labtools.ru`)` (Portainer PUT, env 8/8 сохранён, pullImage=false). LE-cert выпущен (~t+20s; первые хиты ловили self-signed в окне issuance, потом ssl_verify=0). - Live-smoke GREEN: оба хоста 200 (nav + каталог-секции + продукты); редиректы (
/about/→trailing,/Contacts→lowercase,/index.php→/) parity; sitemap = index (host=labtools.ru, non-www — siteUrl этого тенанта без www, в отличие от .pro/R3); theme-ассеты из MinIO byte-identical бою (RUVDS отдаёт 301 apex→www, поэтому прямой md5 «DIFF» — артефакт; с-LMD5-OK). staging-хостlabtools.vds.kzntsv.siteубран (→404). Внешняя проверка с RUVDS-хоста:labtools.ru→VDS 200;wwwещё на кэше RUVDS (200, идентичный контент) — split-brain окно, тухнет по TTL. labtools.pro— закрыт отдельно (labtools.pro-vds-deploy-runbook, LIVE 2026-07-02).
Rollback
- DNS: вернуть A-записи
labtools.ru/www→80.64.31.36(RUVDS IIS живой, нетронут). Откат = смена DNS. - Стек: Portainer → stack
labtools→ remove (или откат тега образа). Образ в registry остаётся. - RUVDS IIS labtools не выводить из эксплуатации до явного решения оператора (директива 2026-07-01).
0.42.1 in-place bump — ✅ ВЫПОЛНЕН 2026-07-05
Тираж snolla 0.42.1. labtools.ru обновлён на живом стеке 17 in-place (домен уже на VDS, DNS не трогали). Рецепт — snolla-live-prod-inplace-image-bump (общий для labtools.ru/emspb/labtools.pro). Оператор дал отмашку на боевой apply.
- Образ:
registry.kzntsv.site/labtools:566d41c(snolla 0.28.2→0.42.1, digestea0649a…). Собран на VDS. - Acceptance С VDS (throwaway-staging из env стека 17): новый sitemap = 38 page-locs (7 pages+1 static+6 sections+24 продукта) — 37×200 + 1×301(
/products/laboratory-ball-mills→/lshm-750, идентично проду). content-not-lost 11/11 (0 потерь). Order-фикс 0.42.1 (liquid 0.10.2): presses =plg-20,plg-12,plg-25,pgr-10== прод. - Находка: старый 0.28.2 sitemap был дефицитным (sections=1, catalog=2 продукта) — 0.42.1 отдаёт полную корректную структуру. Ещё: sitemap листит 301-секцию как
<loc>(прод идентичен, engine-intended; heads-up прогу→снолле). - Swap: Portainer PUT стека 17 (env 8/8 сохранён, pullImage=true) → healthy → live-smoke GREEN, TLS CN=labtools.ru не тронут (без LE-churn).
- Rollback: тег
labtools:43e28ba(0.28.2, в registry) / стек 17 PUT назад / DNS→RUVDS. - Compose обновлён на
566d41c. Таска[labtools-ru-deploy-snolla-0-42-1]🟢. Notify=victor/labtools.ru.
0.43.2 v3 bump (aws-sdk v2→v3) — ✅ ВЫПОЛНЕН 2026-07-30
Тираж v3 (MinIO split Track B3-v3, 3-й сайт после on-snolla + kupimknigi). Домен на VDS, DNS не трогали. Рецепт — snolla-live-prod-inplace-image-bump + minio-split-cutover-runbook §B3-v3.
- Bump:
@snollajs/snolla 0.42.1→0.43.2вapps/web/package.json+resolutions-блок в rootpackage.json(commit0dc0b4e, pushed victor/labtools.ru master). yarn install: single@smithy/signature-v4@5.3.11(deduped). Endpoint fix4f3314f(s3.endpoint→minio.vds.kzntsv.site) был в master с 2026-07-29, но в бегущем образе566d41c(v2) его не было — v3 cutover заодно перевёл S3-direct read на vds minio. - Build на VDS:
git archive 0dc0b4e→~/build/labtools→docker build -f deploy/Dockerfile --build-arg VERDACCIO_TOKEN→registry.kzntsv.site/labtools:0dc0b4e(+latest), EXIT=0. - Throwaway staging :5080 parity-gate GREEN (из env живого стека 17, 8 секретов):
/byte-identical с real Host (18594B), theme assetlato.css200 9239B byte-identical (v3 aws-sdk v3 S3-direct read из vds MinIO 2025), robots 200/200, sitemap = index 38 page-locs == live (identical set, 0 diff), self-consistency 0 bad (все 200/3xx), catalog section/products/accessoriesbyte-identical (order-parity ✅). - Portainer PUT stack 17 LIVE: node in-memory
put-stack(НЕ PS), env 8/8 preserved,mem_limit 512mуже в compose,prune:false pullImage:true. PUT 200. Контейнер0dc0b4ehealthy сразу. Source-of-truth compose синхронно закоммичен (admin). - Live smoke GREEN:
/200, www 200, robots/sitemap 200, menu pages (about/clients/contacts/cookie/privacy) 200,/products/press-forms+/products/accessories+/products/laboratory-ball-mills200, themelato.css200 9239B (v3 S3-direct). TLS CN=labtools.ru не тронут (LE до Sep 30)./products(bare) +/products/presses→ 404 = ожидаемо (не в sitemap, не real pages; real section =/products/press-forms). Rollback =566d41c(v2 0.42.1, жив в registry).