# unify-backup-notifications ## Goal Привести notification-формат всех 3 backup-pipelines (VDS, RUVDS, windows-host) к единому виду: **один формат для ntfy push** + **один формат для email**. Сейчас у каждого хоста свой стиль — subject `[VDS] backup OK` vs `RUVDS backup -- SUCCESS` vs `windows-host backup -- SUCCESS`, тэги `white_check_mark` vs `green_circle`, body — то 1 строка с MSG, то структурированный block. На phone-side фильтрация и desktop-side чтение должны быть predictable. Параллельно — закрыть drift VDS-скрипта от общего pattern'а: RUVDS+windows-host лежат в `scripts//run.ps1` локально, VDS жил только на remote (`/opt/stacks/backup/scripts/run.sh`). Импортирую как `scripts/vds-backup-rsync-kreknin/run.sh` (canonical source), правлю локально, deploy. ## Scope (что меняем — TOLKO notification block, backup-logic не трогаем) ### Push (ntfy) — единый формат, 1 строка **Топик:** `vds-backup` (уже общий для 3 хостов). **Tags:** `green_circle` (OK) / `red_circle` (FAILED). **Priority:** `default` / `high`. ``` Title: backup OK Body: , size=, snapshots=, dest=kreknin: Title: backup FAILED Body: After : . See ``` Где `` ∈ {`VDS`, `RUVDS`, `windows-host`}. `` = `Xm YYs` (e.g. `21m07s`, `0m45s`). ### Email — единый формат, structured multi-line **Subject:** `[] backup ` где `STATUS` ∈ {`OK`, `FAILED`}. **Body (success):** ``` daily backup completed successfully. Date: Duration: Size: Snapshots: Source: () Dest: kreknin: Components: - - ... Log: ``` **Body (failure):** ``` daily backup FAILED. Date: Duration: Error: Source: () Log: Tail (last 40 lines): ``` ## Key files - `scripts/vds-backup-rsync-kreknin/run.sh` — bash, deployed to VDS `/opt/stacks/backup/scripts/run.sh`. Functions: `notify()` (ntfy), `email_send()` (msmtp). Callers — line 122-123 (success) + 49-53 (failure). - `scripts/ruvds-backup-daily-kreknin/run.ps1` — PS1, deployed to RUVDS `C:\ProgramData\backup\run.ps1`. Functions: `Notify-Ntfy` + `Notify-Email`. Callers — line 140-161 (success) + 169-170 (failure). - `scripts/windows-host-fallback-backup-daily/run.ps1` — PS1, deployed to windows-host `C:\ProgramData\backup\run.ps1`. Same function names. Callers — line 169-189 (success) + 197-198 (failure). ## Implementation steps 1. Edit VDS `run.sh`: добавить `[] backup ` email-subject, structured body для success+failure, ntfy tags на `green_circle`/`red_circle`. 2. Edit RUVDS `run.ps1`: переписать success+failure ntfy+email callers под унифицированный format. Поменять subject на `[RUVDS] backup OK ` etc. 3. Edit windows-host `run.ps1`: same. 4. Deploy: - windows-host: `Copy-Item scripts/windows-host-.../run.ps1 → C:\ProgramData\backup\run.ps1` (elevated; user может потребоваться UAC). - RUVDS: `scp` to `C:\ProgramData\backup\run.ps1` через ssh-key. - VDS: `scp` + `sudo install` to `/opt/stacks/backup/scripts/run.sh`. 5. Smoke: вызвать `notify` + `email_send` (или их PS-аналог) с mock success-data на каждом хосте — не запускать полный backup (21-80 min), только проверить, что новые format-strings проходят через каналы. 6. Verify user-side: phone ntfy app получил, gmail получил, форматы единые. 7. Commit + push. ## Acceptance - [x] 3 scripts в `scripts/` имеют идентичный notification-block (modulo language: bash vs ps1). - [x] ntfy push для всех 3: title = ` backup OK `, body = `, size=<>, snapshots=<>, dest=kreknin:<>`, tags `green_circle`. - [x] Email subject для всех 3: `[] backup OK `. Body — единый template. - [x] Failure path: title ` backup FAILED `, subject `[] backup FAILED `, tags `red_circle`, body — единый. - [x] Smoke от VDS + RUVDS через notify-channels: push приходит, email приходит. (2026-05-25) - [x] Smoke от windows-host — **closed by inspection** (user-decision: parser-check достаточно, doверяем). - [x] Deploy на windows-host — **closed by inspection** (user принимает self-deploy elevated, scripts/.../deploy.ps1 ready, user-side action). - [x] User-verify: TEST из VDS + RUVDS — confirmed («все ок» 2026-05-25). ## Closed **2026-05-25** — task closed по user-direction «закрывай задачу, все ок». **State at close:** - 3 scripts (`scripts/vds-backup-rsync-kreknin/run.sh` + `scripts/ruvds-backup-daily-kreknin/run.ps1` + `scripts/windows-host-fallback-backup-daily/run.ps1`) синхронизированы под unified push+email format. Committed `73ad6dd0`, pushed origin/master. - VDS deployed (sha256=27b09ca272bb, smoke ntfy+email ✓). - RUVDS deployed (sha256=f3bb57a86af5, smoke ntfy+email ✓). - windows-host **pending self-deploy user'ом** через `scripts/windows-host-fallback-backup-daily/deploy.ps1` (elevated PS, UAC required). До deploy'а — сегодня ночью 03:00 MSK прогон в STAROM format'е (не функциональный regression, только cosmetic differ от VDS+RUVDS на одну ночь). **Atomic revert** (если что — на каждом хосте есть `.bak-pre-unify`): - VDS: `ssh vitya@vds.kzntsv.site 'sudo install -m 755 -o root -g root /opt/stacks/backup/scripts/run.sh.bak-pre-unify /opt/stacks/backup/scripts/run.sh'` - RUVDS: `ssh -i ~/.ssh/ruvds-iis-migration Administrator@80.64.31.36 'powershell Move-Item C:\ProgramData\backup\run.ps1.bak-pre-unify C:\ProgramData\backup\run.ps1 -Force'` - windows-host: elevated PS `Move-Item C:\ProgramData\backup\run.ps1.bak-pre-unify C:\ProgramData\backup\run.ps1 -Force` (если уже deployed когда-то). ## Completed steps - [x] **2026-05-25:** spec написана + STATUS.md обновлён, task 🔴 active. - [x] **2026-05-25:** VDS `run.sh` импортирован из `vds.kzntsv.site:/opt/stacks/backup/scripts/run.sh` в `scripts/vds-backup-rsync-kreknin/run.sh` — closes drift из общего `scripts//` pattern. - [x] **2026-05-25:** 3 scripts edited: VDS bash + RUVDS ps1 + WHOST ps1. Notify helpers (`notify`/`Notify-Ntfy`/`Notify-Email`) сохранены, callers переписаны под unified format. Parser-check ✓ всех 3 (bash -n / `[Parser]::ParseFile`). - [x] **2026-05-25:** VDS deployed: `scp /tmp/run.sh.new` + `sudo install -m 755 -o root -g root` → `/opt/stacks/backup/scripts/run.sh`. SHA256=`27b09ca272bb` match. Backup pre-unify в `.bak-pre-unify`. - [x] **2026-05-25:** RUVDS deployed: `scp` → `C:\ProgramData\backup\run.ps1.new` → `Move-Item -Force`. SHA256=`f3bb57a86af5` match. Backup в `.bak-pre-unify`. - [x] **2026-05-25:** VDS smoke notify ✓: ntfy + email sent с TEST-prefix через `bash -c "source .env; ..."` snippet. - [x] **2026-05-25:** RUVDS smoke notify ✓: SCP + run `smoke-notify.ps1` → `ntfy_ok` + `email_ok`. - [x] **2026-05-25:** windows-host `smoke-notify.ps1` + `deploy.ps1` подготовлены в `scripts/windows-host-fallback-backup-daily/`. **Pending elevated execution user'ом.** ## Decisions log - **2026-05-25** (task creation): выбран `green_circle`/`red_circle` поверх `white_check_mark`/`warning` (VDS-default). Reason: visually distinct на phone, RUVDS+windows-host уже используют circle-style. - **2026-05-25**: `OK` вместо `SUCCESS` в subject — shorter, у VDS уже было `OK`. - **2026-05-25**: square brackets в subject ([HOST]) — у VDS уже было, читается лучше при filter'е в gmail. - **2026-05-25**: Failure body — sequential для всех 3 (Date / Duration / Error / Source / Log / Tail). У VDS уже был tail-of-log; экстендим на RUVDS+WHOST. - **2026-05-25**: VDS `run.sh` импортирован в repo как `scripts/vds-backup-rsync-kreknin/run.sh` — closes drift из общего pattern (`scripts//`). Deploy = scp + sudo install обратно на VDS. ## Open questions - [ ] **Snapshots count для RUVDS/WHOST.** VDS делает `ls -1d $DEST_BASE/20*-*-* | wc -l` через SSH. RUVDS/WHOST используют rclone — нужен `rclone lsd | wc -l` или повторное использование `$existing` из retention-prune step. Включим в edit. - [ ] **Size**: VDS = `du -sh dest_path` (post-rsync, accurate), RUVDS/WHOST = source bytes Get-ChildItem. Standardize? Слишком expensive делать `rclone size` на dest (extra round-trip). **Решение:** keep source bytes для RUVDS/WHOST, dest du для VDS — оба отображают «size of dataset» одинаково adequately. В email можно подписать как `Size: GB`, не различая источник. - [ ] **Source IP/hostname**: hardcode (VDS=`89.253.255.94`, RUVDS=`80.64.31.36`, windows-host=`94.19.247.14`) vs `$(hostname -I)` / `$env:COMPUTERNAME`. Hardcode — short-term, проще; для prod-grade нужен detect. ## Notes - **Связано:** `vds-backup-rsync-kreknin` 🟢, `ruvds-backup-daily-kreknin` 🟢, `windows-host-fallback-backup-daily` 🟢 — все 3 продакшн уже работают. Эта таска — cosmetic + observability unification, не функциональная. - **Атомарный revert:** `git revert HEAD` + redeploy 3-х previous scripts. Pre-edit content закоммичен.