Files
admin/.tasks/STATUS.md
vitya 73ad6dd06a scripts(backup-notifications): unify push + email format across VDS/RUVDS/windows-host
3 host-pipelines (VDS bash, RUVDS+windows-host ps1) had drifted formats:
ntfy title `VDS backup OK $D` vs `RUVDS backup OK ($D)`, tags
`white_check_mark` vs `green_circle`, email subject `[VDS] backup OK` vs
`RUVDS backup -- SUCCESS`. Phone-side фильтрация и desktop reading
ломались за счёт inconsistency.

Unified to:
- ntfy push: title `<HOST> backup OK <date>`, body
  `<duration_human>, size=<>, snapshots=<>, dest=kreknin:<>`,
  tags `green_circle` (OK) / `red_circle` (FAILED).
- email: subject `[<HOST>] backup <STATUS> <date>` (STATUS=OK|FAILED),
  body — structured Date/Duration/Size/Snapshots/Source/Dest/Components/Log.
  Failure body extends with `Tail (last 40 lines)`.

Also imports VDS `run.sh` into repo as `scripts/vds-backup-rsync-kreknin/`
— closes drift из общего `scripts/<slug>/` pattern (RUVDS+windows-host
уже жили там; VDS жил только на /opt/stacks/backup/scripts/).

Deploy status:
- VDS: deployed via scp + sudo install, sha256=27b09ca272bb, smoke ntfy+email ✓
- RUVDS: deployed via scp + Move-Item, sha256=f3bb57a86af5, smoke ntfy+email ✓
- windows-host: deploy.ps1 + smoke-notify.ps1 готовы в scripts/, **pending
  elevated PS у user'а** (ACL=SYSTEM+Administrators, не пишется без UAC).

Spec + decisions + completed: .tasks/unify-backup-notifications.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 07:19:15 +03:00

17 KiB
Raw Blame History

Admin Task Board

Updated: 2026-05-25 (unify-backup-notifications 🟡 paused — 3 scripts edited под единый push+email format; VDS+RUVDS deployed + smoke notify ✓; windows-host deploy pending elevated PS у user'а. VDS run.sh импортирован в repo как canonical source. Pre-existing: books-ssh-audit-shared-vds 🟢, windows-host-fallback-backup-daily 🟢, все 3 daily backups live на kreknin.)

🟡 [unify-backup-notifications] — единый формат push + email для всех 3 backup-pipelines (VDS / RUVDS / windows-host)

Status: paused (pending windows-host elevated deploy) Where I stopped: 2026-05-25 — 3 scripts edited + parser-check ✓. VDS + RUVDS deployed + smoke notify ✓ (ntfy_ok + email_ok с TEST-prefix). windows-host pending elevated deployscripts/windows-host-fallback-backup-daily/deploy.ps1 готов, user запустит из elevated PS позже. Smoke на windows-host skipped по user-decision (доверяем parser-проверке). Next action:

  1. User: open elevated PowerShell, cd C:\Users\vitya\projects\.admin, & .\scripts\windows-host-fallback-backup-daily\deploy.ps1.
  2. (Optional) & .\scripts\windows-host-fallback-backup-daily\smoke-notify.ps1 — отправит TEST ntfy + email, verify format.
  3. Verify первой ночью (2026-05-25 03:00 MSK windows-host → 04:30 RUVDS → 05:00 VDS) что push'и + email'ы пришли с единым форматом, нет regression.
  4. Закрыть task. Branch: master

🟡 [iis-migration-to-ruvds] — RUVDS IIS live для 2 prod hostnames (kupimknigi + emspb flipped); 22 в очереди. tandemmebel.ru остаётся на windows-IIS отдельно. Source held для rollback.

Status: in_progress (DNS partial cutover — soak window 2026-05-24) Where I stopped: 2026-05-24 — kupimknigi.spb.ru + emspb.ru (+ www.emspb.ru) DNS A flipped на 80.64.31.36, authoritative ns1.reg.ru правильный, public resolver caches expire'ятся (8.8.8.8=~6h, 1.1.1.1=~24h max). RUVDS state: snolla site (8.66 GB / 44725 files) transferred + IIS recreated + 25 HTTPS SNI bindings c LE certs (R13, valid до 2026-07-22), 7 prod hostnames live-smoke через VDS (третья сеть) → 200 OK / correct content. Source IIS:8089 + traefik routes ALIVE — rollback ready. Findings зафиксированы в iis-migration-to-ruvds.md Decisions log: (1) outbound 445 блокирует home ISP, не RUVDS-FW → SSH/scp = canonical transfer-метод; (2) home network HTTP-middlebox mangles Host header for direct external HTTP — real end-users не пострадают, тестировать через VDS; (3) traefik acme.json → IIS PFX recipe работает (extract + openssl pkcs12 -export + Import-PfxCertificate + AddSslCertificate by thumbprint); (4) IIS 10 HTTP/2 default; (5) maljarka.tandemmebel.ru + 3 rimiz hostnames → 502/404 — pre-existing CMS-tenant config gap, не migration defect.

Scope exception (2026-05-24 user decision): tandemmebel.ru + www.tandemmebel.ru ОСТАЮТСЯ на windows-IIS на неопределённый срок (отдельное решение user'а — site не готов к cutover ровно сейчас). DNS НЕ свапать. Cert на RUVDS уже импортирован, binding existing — может оставаться idle, traffic не пойдёт.

Next action:

  1. Снизить DNS TTL в reg.ru на оставшиеся 22 hostnames до 300s — pilorama98.ru, labtools.{ru,pro}, snolla.com + 11 snolla subdomains + rimiz.{ru,snolla.com} + maljarka.tandemmebel.ru (но не tandemmebel.ru — см. Scope exception). Сократит cache-tail с 24h до 5 мин.
  2. 24h soak kupimknigi + emspb — verify через cache-clean resolver (потом curl без --resolve).
  3. Bulk DNS swap оставшихся 22 hostnames на 80.64.31.36 (single sitting). tandemmebel.ru / www.tandemmebel.ru — пропустить.
  4. 1-week prod soak с RUVDS как live source для migrated hostnames.
  5. Decommission source IIS:8089 только для migrated hostnames (snolla catch-all site нельзя decommission'ить пока tandemmebel.ru на нём же). Решение defer до tandemmebel migration.
  6. LE renewal pipeline — win-acme + HTTP-01 на RUVDS после full cutover (LE certs expire 2026-07-22, soak window до ~07-15).
  7. Cleanup migration-temp: Remove-NetFirewallRule 'smb-from-source','ssh-from-source' на RUVDS, удалить ~/.ssh/ruvds-iis-migration* на source, очистить C:\ProgramData\ssh\administrators_authorized_keys на RUVDS.

Полный план + Completed + Open questions + Remaining steps — в iis-migration-to-ruvds.md. Branch: master

Branch: master


[infra-inventory] — two-tier инвентаризация: public-карта в global wiki + admin-detailed runbook локально

Status: ready Where I stopped: (not started — создана 2026-05-22 из инцидента gitea. vs git. + перепутанный source/dest IP в traefik access-логах; scope расширена в тот же день — single-page → two-tier per user «у все общее представление, у админа полное») Next action: см. полный план в infra-inventory.md. Шаги: (1) probing-фаза одна для обоих — nslookup известных subdomain'ов + vds-ops/synology-ops ops_docker_ps/inspect + knowledge_search по существующим bootstrap-concept'ам + rg "kzntsv.site" по ~/projects/. (2) Write A — light public в projects-wiki/concepts/infrastructure-inventory.md (машины, canonical hostnames, anti-aliases) → knowledge_ingest. (3) Write B — heavy admin в .admin/.wiki/concepts/infrastructure-stack.md (per-stack: версии, internal IPs, volumes, depends-on, backup paths, DR pointers) → commit + push. (4) Cross-refs A↔B + pointer в .admin/.wiki/CLAUDE.md Domain conventions. Branch: n/a


🔵 [books-vds-bookva-bootstrap] — Ops-таска для Фазы 4 дизайна tenant-split из victor/books (см. mcp__projects-meta__knowledge_get slug=concepts/tenant-split). Поднять новый VDS для Bookva — billing на юрлицо Bookva (учредители развелись, каждое юрлицо платит инфру напрямую провайдеру).

Контекст dev-source: дизайн в victor/books .wiki/concepts/tenant-split.md; brainstorm trace ~/projects/.workshop/.archive/2026-05-24-books-tenant-split.md.

Direction: Slovo остаётся на текущем VDS, Bookva переезжает на новый.

Acceptance:

  • Новый VDS у провайдера (Rusonyx или другой по предпочтению Bookva), billing-account оформлен на юрлицо Bookva.
  • Docker + traefik + certbot развёрнуты.
  • DNS *.bookva.<tld> готов резолвиться на новый IP (фактический switch — в books-dns-cutover-bookva).
  • SSH-ключи: только инженерные (core-разраб + админ Bookva, если есть). Аналитики Bookva — НЕ имеют SSH к новому VDS.

Status: blocked Where I stopped: (not started) Next action: Pre-step: прочитать concepts/tenant-split.md § «Фаза 4» в victor/books (через mcp__projects-meta__knowledge_get slug=concepts/tenant-split или git clone victor/books → .wiki/concepts/tenant-split.md).

  1. Согласовать с учредителем Bookva: provider, configuration (CPU/RAM/disk), регистрация billing'а на юрлицо Bookva.
  2. Provision VDS, базовая настройка (firewall, fail2ban, SSH ключи).
  3. Установить Docker + docker-compose.
  4. Развернуть traefik + certbot из overlay-репо victor/books-bookva/deploy/traefik.compose.yml.
  5. Подготовить DNS-зону bookva.<tld> (создать A-records, TTL=300 для возможности быстрого switch'а).
  6. Smoke: curl https://placeholder.bookva.<tld> → 200 от nginx-placeholder или из traefik.
  7. Документировать в victor/books-bookva/README.md: hostname, IP, как ssh, runbook smoke-теста.
  8. Закрыть с note: «VDS поднят, IP=<...>, готов к stack deploy». Blocker: victor/books tenant-split-pointers + overlay-repos-bootstrap-bookva-slovo + compose-second-mariadb-instance + per-tenant-backup-and-observability (стек уже работает на текущем VDS логически — пора готовить физический переезд). Branch: n/a

🔵 [books-dns-cutover-bookva] — Ops-таска для Фазы 4, шаг 5 дизайна tenant-split из victor/books. DNS switch *.bookva.<tld> → новый VDS IP, с parallel-run старого bookva-стека на shared VDS 7 дней без публичного hostname.

Контекст dev-source: дизайн в victor/books .wiki/concepts/tenant-split.md § «Фаза 4».

Acceptance:

  • DNS *.bookva.<tld> (или конкретный hostname Bookva — определяется учредителем) указывает на новый VDS IP.
  • Старый bookva-стек на shared VDS остаётся запущенным, без публичного hostname (traefik labels убраны или disabled), доступен только по docker-сети для возможного отката.
  • Smoke с двух разных сетей (mobile + офисный wifi) — https://<bookva-hostname> отвечает с нового VDS.
  • Per-VDS backup'ы на новом VDS подтверждены — есть snapshot спустя 24ч после DNS-switch'а.
  • Через 7 дней parallel-run без откатов — decommission старого bookva-стека (см. Фаза 4, шаг 7 в spec).

Status: blocked Where I stopped: (not started) Next action: Pre-step: прочитать concepts/tenant-split.md § «Фаза 4, шаги 47» в victor/books.

  1. Maintenance window 12ч (объявить за 7 дней).
  2. Финальная синхронизация: mysqldump mariadb-bookva на текущем VDS → mysql на новом VDS (если schema/data разошлись с момента Фазы 2).
  3. Smoke на новом VDS до DNS-switch'а: hosts-файл override → проверить login + base flow.
  4. DNS-switch: меняем A-record(s) для bookva-hostname на new IP. TTL=300 уже стоял (Phase 4 step 1).
  5. Через 1ч (TTL expiry + propagation): smoke с двух сетей.
  6. На старом VDS — отключить traefik labels для bookva-стека (контейнеры продолжают работать, но не доступны снаружи).
  7. Parallel-run 7 дней. Каждый день — smoke. Per-VDS backup на новом VDS — проверить хотя бы 1 успешный snapshot.
  8. Если за 7 дней проблем нет → закрыть с note «cutover stable». Если есть — DNS rollback на старый IP, follow-up debug task в victor/books.
  9. Decommission старого bookva-стека на shared VDS (отдельный шаг, не в этой таске — финальный backup в архив + docker compose down + volume drop). Blocker: books-vds-bookva-bootstrap + victor/books pwa-redirect-handoff (SW bump выкачен в shared API за 12 недели до этой таски). Branch: n/a

[books-bookva-user-whitelist-gathering] — Процессная ops-таска для Фазы 3, шаг 1 дизайна tenant-split из victor/books. Получить от учредителя Bookva письменный список пользователей, которые допущены к Bookva-инсталляции. Без этого списка cutover не возможен — иначе утечка доступа: либо лишние юзеры получат доступ к Bookva (через копирование «всех users»), либо легитимные юзеры заблокированы (через пустой whitelist).

Direction: Bookva — новая инсталляция, начинается с whitelist'а (закрытый список). Slovo — остаётся на текущем стеке, получает копию всех текущих users (статус-кво).

Контекст dev-source: дизайн в victor/books .wiki/concepts/tenant-split.md § «Двухуровневая изоляция пользователей → App-level» и § «Фаза 3, шаг 1».

Не блокируется ничем — можно начинать gathering сразу, лаг до cutover'а может быть значительным.

Acceptance:

  • Письменный список от учредителя Bookva (email или подписанный документ): ФИО + role (если знают).
  • Список зафиксирован в OpeItcLoc03/admin/.wiki/concepts/books-bookva-whitelist.md или в отдельной таблице.
  • Для каждой строки списка сверка с текущей users-таблицей shared БД: user существует / роль соответствует / email актуален.
  • Любые расхождения (запрошенный user не существует в shared / роль другая) — обработаны: создать новый user в Bookva-БД post-cutover ИЛИ скорректировать список с учредителем.

Status: ready Where I stopped: (not started) Next action: 1. Отправить учредителю Bookva формальный запрос (email/мессенджер): «Для tenant-split нужен список пользователей, которые останутся в Bookva после разделения. Формат: ФИО + роль + email/login. Список будет применён на cutover'е как whitelist». 2. Дождаться ответа (это может занять дни/недели — нормально). 3. Получив список — сверить с users-таблицей shared БД:

SELECT id, login, email, role FROM users WHERE email IN (<list>) AND deleted_at IS NULL;
  1. Разобрать расхождения с учредителем (missing / role mismatch / inactive).
  2. Зафиксировать финальный список в OpeItcLoc03/admin/.wiki/concepts/books-bookva-whitelist.md (или в local-only encrypted file если NDA-чувствительно).
  3. Финальный список становится input'ом для Фазы 3, шаг 1: при настройке Bookva-БД в неё попадают только эти users.
  4. Закрыть с note: «whitelist (N users) подтверждён учредителем, готов к применению на cutover'е». Branch: n/a