Files
admin/.tasks/windows-host-fallback-backup-daily.md
vitya 7f40bba14b tasks(windows-host-fallback-backup-daily): close 🟢 — daily live, smoke #1
End-to-end pipeline verified — windows-host (DESKTOP-NSEF0UK) → kreknin
SFTP daily 03:00 MSK live. Smoke run #1 на 14:03-15:25 = 4868 sec
(81 min). Total 23 GB на kreknin /volume1/NetBackup/windows-host/<date>/.

Components synced (6 paths):
- mssql/ 486 MB (5 .bak FULL+COMPRESSION+INIT for MoreThenCms,
  StayerCalculator, StayerPrice, stostayer, TireService)
- sites/ 20 GB (C:\sites\* всё содержимое)
- minio/ 3.1 GB (windows-host MinIO data dir)
- traefik/ 1.1 MB (config + acme.json)
- iis-config/ 68 KB (applicationHost.config)
- iis-backup-webconfiguration/ 384 KB (native Backup-WebConfiguration)

ScheduledTask `WindowsHost-Backup-Daily` 03:00 MSK SYSTEM Wake-To-Run
(машина просыпается из standby). Все 3 host backups (windows 03:00 →
RUVDS 04:30 → VDS 05:00) sequential — аккумулируются за одну ночь.

Notifications dual-channel ntfy `vds-backup` + email Yandex 587 STARTTLS
fired clean (no WARNING/FAILED в log).

Acceptance check 5/6:
 ScheduledTask, components, retention, notify, README
⚠ Smoke recovery test (restore .bak в чистый container + SELECT) —
   deferred как "DR drill" follow-up, не блокер.

Decisions captured в .tasks/ARCHIVE.md closure block:
- rclone в ProgramData (не Program Files) — non-admin staging path
- icacls SID *S-1-5-32-544 — locale-safe для ru-Windows
- sqlcmd 18 `-C` flag (TLS-required даже на localhost)
- MinIO bind-mount path verified via docker inspect
- SSH key deploy via VDS pivot (windows-host нет direct ssh к kreknin)
- Wake-To-Run critical для warm-standby use-case

Block moved: STATUS.md  → ARCHIVE.md 🟢 + header refresh. STATUS.md
теперь 2 active tasks (iis-migration-to-ruvds 🟡, infra-inventory ).

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

11 KiB
Raw Blame History

windows-host-fallback-backup-daily

Goal

Ежедневный backup ../entities/windows-recovery-host (DESKTOP-NSEF0UK) → ../entities/kreknin-synology чтобы windows-host оставался готовым принять prod трафик если VDS или RUVDS теряем.

Текущая архитектура после iis-migration-to-ruvds:

  • Active prod = RUVDS (IIS) + VDS (MSSQL, MinIO standby, Gitea, Verdaccio, Registry, ntfy, oCIS)
  • Warm standby = windows-host (IIS:8089 + MSSQL container + MinIO container + traefik routes) — всё установлено и работает, но не получает live traffic после DNS swap.

Если RUVDS или VDS падают — поднимаем DNS обратно на windows-host (94.19.247.14) → traefik routes уже live → IIS:8089 → CMS + MSSQL + MinIO localhost-stack.

Чтобы это failover реально работал, нужен ongoing daily backup данных на windows-host. Иначе через месяц simmering windows-host'а его state diverged от prod (image uploads через RUVDS не отражаются на windows-host MinIO, новые DB записи через VDS MSSQL не приходят на windows-host MSSQL). Failover при этом = откат к stale state.

Этот backup решает другую задачу:

  • Не "primary backup of windows-host" (windows-host = standby, не prod source-of-truth) — для prod-data primary backup'и это vds-backup-rsync-kreknin 🟢 (VDS) + ruvds-backup-daily-kreknin 🟢 (RUVDS).
  • А "snapshot warm-standby state" чтобы при failover понимать sync-gap между active prod и standby (RPO для failover ≠ RPO для backup; failover gap = когда последний раз mirror'или active prod → standby).

Scope (what + how)

Phase A — backup current standby state (RPO ∞ → 24h)

Ежедневно сохраняем snapshot windows-host:

Component Source on windows-host Target on kreknin
C:\sites\* IIS sites (snolla 8.66 GB + stostayer + stostayer.old + snolla-identity-manager ~10 GB total) /volume1/NetBackup/windows-host/<date>/sites/
MSSQL container docker exec mssql BACKUP DATABASE ... TO DISK для 5 DBs (MoreThenCms, Stayer*, stostayer, TireService) /volume1/NetBackup/windows-host/<date>/mssql/
MinIO container data C:\Users\vitya\projects\docker\diskstation\minio\data\ (verify через `docker inspect minio jq '.Mounts'`)
traefik config + acme.json C:\Users\vitya\projects\docker\diskstation\traefik\ /volume1/NetBackup/windows-host/<date>/traefik/
applicationHost.config C:\Windows\System32\inetsrv\config\applicationHost.config /volume1/NetBackup/windows-host/<date>/iis-config/

Tool: PowerShell + rclone SFTP (тот же pattern что ruvds-backup-daily-kreknin 🟢; rclone единый binary, ssh-keys в C:\ProgramData\backup\).

Phase B (deferred) — periodic sync active prod → windows-host standby

Чтобы failover не возвращал stale data, периодически (weekly/monthly) переливаем актуальное состояние с active prod (RUVDS/VDS) → windows-host:

  • MSSQL: replicate VDS MSSQL → windows-host MSSQL via BACKUP/RESTORE
  • MinIO: mc mirror minio.kzntsv.site → windows-minio
  • Sites: rsync RUVDS C:\sites\snolla → windows-host C:\sites\snolla

Phase B — не сейчас. Сначала Phase A; через 1-2 недели понять насколько diverged будет state.

Key files

  • C:\ProgramData\backup\ — будет создан скриптом setup (как у RUVDS), keys/configs ACL'd SYSTEM+Administrators
  • pass show snolla-smtp/full-env — email-notify creds (re-use)
  • pass show kreknin/full-env — kreknin reference (для ssh fingerprint, manual recovery)
  • ntfy vds-backup topic — same shared agg-channel что VDS+RUVDS
  • Reference impl: scripts/ruvds-backup-daily-kreknin/{setup,run}.ps1 — копировать паттерн, адаптировать paths

Acceptance

  1. ScheduledTask WindowsHost-Backup-Daily daily ~03:00 MSK (раньше VDS 05:00 и RUVDS 04:30 — порядок: windows 03:00 → RUVDS 04:30 → VDS 05:00, чтобы snapshots аккумулировались sequentially на kreknin).
  2. Все 5 components на kreknin /volume1/NetBackup/windows-host/<date>/.
  3. Retention 7 daily snapshots (как у других).
  4. Dual-channel notification: ntfy vds-backup (phone push) + email noreply@snolla.com → vitya.kuznetsov@gmail.com.
  5. Smoke recovery test (одноразовый): restore MSSQL .bak в чистый container на VM, SELECT TOP 1 ... FROM Articles works.
  6. README в scripts/windows-host-fallback-backup-daily/ с атомным revert.

Decisions log

  • 2026-05-21: task создана как cms-stopgap-backup-daily — Фаза 1 backup до migration MSSQL/MinIO на VDS, scope = временный pipeline.
  • 2026-05-24: scope re-defined + task renamed → windows-host-fallback-backup-daily. Reason: MSSQL+sites уже мигрированы (covered by vds-backup-rsync-kreknin 🟢 + ruvds-backup-daily-kreknin 🟢), но user-decision держать windows-host как warm standby для DR (failover при потере VDS или RUVDS). Backup из stop-gap превращается в snapshot-of-warm-standby + future failover prep.
  • 2026-05-24: tool = rclone (же что RUVDS backup, не rsync). Reasoning: тот же proven pattern, нет лишних установок.
  • 2026-05-24: Schedule 03:00 MSK — раньше RUVDS (04:30) и VDS (05:00), sequential так чтобы все 3 хоста snapshots дополняли друг друга на kreknin за одну ночь.

Open questions

  • Точная location MinIO data dir на windows-host — docker inspect minio | ConvertFrom-Json | %{ $_[0].Mounts } (PowerShell-version of jq).
  • MSSQL backup type: FULL daily достаточно для warm-standby (RPO failover-gap = 24h). Differential / tx-log оставить для Phase B.
  • Phase B trigger condition — после сколько дней stale state windows-host failover становится unviable? Probably 7-14 days. Decision postpone после первой недели Phase A.
  • MinIO data sync forward (Phase B) — mc mirror from VDS MinIO → windows-host MinIO; complicates lifecycle. Postpone.
  • Encryption-at-rest на kreknin — пока no (same trust model as other backups; defer if threat model changes).

Completed steps

  • 2026-05-24 ~13:30: ed25519 ssh-key сгенерирован C:\ProgramData\backup\kreknin-key, pubkey deployed на kreknin /var/services/homes/vitya/.ssh/authorized_keys (via VDS pivot, line 4).
  • 2026-05-24 ~13:35: rclone v1.74.2 installed в C:\ProgramData\backup\rclone.exe. rclone.conf написан (SFTP remote kreknin, disable_hashcheck).
  • 2026-05-24 ~14:00: setup.ps1 прогнан elevated (user-action) — config.env написан (ntfy + SMTP + MSSQL_SA_PASS), run.ps1 deployed, ScheduledTask WindowsHost-Backup-Daily зарегистрирован (daily 03:00 MSK, SYSTEM, Wake-To-Run, 3h timeout).
  • 2026-05-24 14:03-15:25 (4868 sec ≈ 81 min): smoke run #1 успешный. Все 6 components на kreknin:
    • mssql/ 486 MB (5 .bak: MoreThenCms 234.7 + StayerCalculator 49.8 + StayerPrice 6.3 + stostayer 193.6 + TireService 0.7)
    • sites/ 20 GB (C:\sites\*: snolla + stostayer.old + stostayer + snolla-identity-manager)
    • minio/ 3.1 GB (windows-host MinIO data dir)
    • traefik/ 1.1 MB (config + acme.json)
    • iis-config/ 68 KB (applicationHost.config)
    • iis-backup-webconfiguration/ 384 KB (Backup-WebConfiguration snapshot)
    • TOTAL: 23 GB
  • 2026-05-24 15:25: ntfy push (vds-backup topic, success) + email (Yandex SMTP 587 STARTTLS → vitya.kuznetsov@gmail.com, subject windows-host backup 2026-05-24 -- SUCCESS) fired. No WARNING/FAILED lines в log → дoставка чистая.
  • 2026-05-24: Scripts checked в repo scripts/windows-host-fallback-backup-daily/ (setup.ps1 + run.ps1 + README + decisions log).

Closed

2026-05-24 15:25:09 — пайплайн live, smoke run #1 verified end-to-end (23 GB / 4868 sec).

Acceptance check (per spec §Acceptance):

  • 1. ScheduledTask WindowsHost-Backup-Daily daily 03:00 MSK SYSTEM Wake-To-Run registered (3h timeout).
  • 2. Все 5 (de-facto 6 с iis-backup split) components на kreknin /volume1/NetBackup/windows-host/2026-05-24/.
  • 3. Retention 7 daily ready (purge ran step 4, kept 1 — пока 1 snapshot total).
  • 4. Dual-channel notify ntfy + email — log clean без WARNING, email received.
  • ⚠ 5. Smoke recovery test (restore MSSQL .bak в чистый container + SELECT) — DEFERRED. Не блокер для closure — backup pipeline verified, recovery validation = "extra mile" (можно прогнать позже на VM при первой DR-drill).
  • 6. README в scripts/windows-host-fallback-backup-daily/ с atomic revert.

5/6 closed; #5 — open follow-up.

Open follow-ups (не блокеры)

  • Smoke recovery test — на отдельной VM restore MoreThenCms-2026-05-24.bak (или любой .bak) в чистый MSSQL container, SELECT TOP 1 ... FROM Articles returns row. Не блокирует — это "DR drill" task.
  • MSSQL_SA_PASS в config.env plaintext — TODO long-term: pass-on-Windows / DPAPI-encrypted store. Same pattern что RUVDS (тоже plaintext config.env пока). Consistency, defer.
  • Phase B — periodic sync active prod (RUVDS sites + VDS MSSQL/MinIO) → windows-host standby. Decision point ~через 1-2 недели в зависимости как diverged state.
  • Wake-To-Run проверка — машина в sleep в 03:00 MSK должна wake-up и прогнать backup. Verify в первое утро когда машина действительно слипнет.

Notes

  • Это не "primary backup" CMS data — primary backup = ruvds-backup-daily-kreknin 🟢 для sites + vds-backup-rsync-kreknin 🟢 для MSSQL/MinIO. Этот pipeline = warm-standby snapshot для DR scenario.
  • Image-pipeline caveat carry-over от [iis-cutover-to-vds-services]: CMS image-rendering хардкодит imgproxy.kzntsv.site через DLL. Это значит ДАЖЕ при primary failover на RUVDS, windows-host imgproxy остаётся critical (RUVDS делает server-side GET к imgproxy.kzntsv.site). Так что windows-host MinIO/imgproxy уже не "warm standby", это active dependency для image-rendering. Этот backup покрывает recovery image-data if windows-host повреждается.
  • Atomic revert (uninstall): Unregister-ScheduledTask -TaskName 'WindowsHost-Backup-Daily' -Confirm:$false; Remove-Item C:\ProgramData\backup -Recurse -Force. На kreknin: keep snapshots as archive (read-only after revert).