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>
ruvds-backup-daily-kreknin — scripts
Ежедневный backup RUVDS (80.64.31.36 Win Server 2025 Core) → kreknin Synology (195.19.90.188:/volume1/NetBackup/ruvds-iis/<date>/) via rclone SFTP.
Live since 2026-05-24. Schedule: daily 04:30 MSK. Task name: RUVDS-Backup-Daily.
Files
setup.ps1— one-time install: SSH key, rclone, configs, ScheduledTask.run.ps1— backup logic (synced toC:\ProgramData\backup\run.ps1by setup.ps1).
Initial install (rebuilding RUVDS from scratch)
# На RUVDS, PowerShell as Administrator
mkdir C:\backup-scripts -Force
# Копируем оба файла из source repo:
Copy-Item \\tsclient\C\Users\vitya\projects\.admin\scripts\ruvds-backup-daily-kreknin\*.ps1 C:\backup-scripts\
C:\backup-scripts\setup.ps1
Setup паузится после генерации SSH key — нужно добавить kreknin-key.pub в /volume1/homes/vitya/.ssh/authorized_keys на kreknin (через SSH/DSM File Station), потом Enter.
What's backed up (5 components)
| Component | Source | Remote path on kreknin |
|---|---|---|
| snolla site content | C:\sites\snolla\ (~8.7 GB) |
NetBackup/ruvds-iis/<date>/sites/snolla/ |
| applicationHost.config | C:\Windows\System32\inetsrv\config\applicationHost.config |
NetBackup/ruvds-iis/<date>/iis-config/ |
| IIS native config backup | Backup-WebConfiguration -Name daily-<date> |
NetBackup/ruvds-iis/<date>/iis-backup-webconfiguration/ |
| LE certs (PFX export) | Cert:\LocalMachine\My private-key certs (14 PFX, pass ruvds-backup-pfx) |
NetBackup/ruvds-iis/<date>/certs/ |
| SSH state | C:\ProgramData\ssh\ (sshd_config + administrators_authorized_keys) |
NetBackup/ruvds-iis/<date>/ssh-config/ |
Retention: 7 daily snapshots. Older — pruned by rclone purge in step 4.
Notifications
Dual-channel (oба отправляются после каждого run):
-
ntfy topic
vds-backup(shared с VDS backup) — phone push через ntfy mobile app:- Success: title
RUVDS backup OK (<date>), taggreen_circle, prioritydefault - Fail: title
RUVDS backup FAILED (<date>), tagred_circle, priorityhigh
- Success: title
-
Email via Yandex SMTP (
noreply@snolla.com→vitya.kuznetsov@gmail.com):- Port 587 STARTTLS (.NET
SmtpClientне дружит с implicit-TLS port 465; 587 STARTTLS работает сSend-MailMessage -UseSsl) - Subject:
RUVDS backup <date> -- SUCCESS / FAILED - Body: duration, size, certs count, component list, log path
- SMTP creds в
config.env(re-used изpass show snolla-smtp/full-env, тот же account что VDS msmtp)
- Port 587 STARTTLS (.NET
Если email или ntfy fail — backup itself не fail'ит (notify-функции wrapped в try/catch, warning в лог).
Decisions log
- rclone, not rsync — Win Server Core нет cygwin/WSL, rsync.exe = пакет, security surface. rclone single .exe.
- SFTP без host-key validation — rclone go-sftp library не parsит SSH known_hosts с keyscan format корректно (key mismatch error даже на fresh keyscan). Path RUVDS↔kreknin через public internet, но key auth достаточно для нашего threat model. Если threat model меняется — populate known_hosts file from
ssh-keyscanв правильном format. Invoke-Rclonewrapper —$ErrorActionPreference = 'Stop'+ rclone NOTICE на stderr = native command terminating-error в PS. Wrapper temporarily switches к Continue для rclone calls, restores after. Без этого2>$nullне помогает (PS видит non-empty stderr stream как error).Backup-WebConfiguration -Force— параметра нет в этой версии WebAdministration module. ИспользуемGet-WebConfigurationBackup + Remove-WebConfigurationBackupесли exist + plainBackup-WebConfiguration.- SMTP port 587 STARTTLS, не 465 implicit-TLS — .NET
SmtpClient(и Powershell'sSend-MailMessage) не поддерживает implicit-TLS на 465 (только STARTTLS). Yandex принимает обоих, выбрали 587 STARTTLS для compat с native PS tooling. VDS msmtp использует 465 implicit — оба валидны, разные tooling. - Local Get-ChildItem для size в email, не
rclone size --json—Invoke-Rclone size --jsonобъединяет stdout JSON со stderr NOTICE,ConvertFrom-Jsonпадает на mixed output.Get-ChildItem C:\sites\snolla -Recurse | Measure -Sum Length— local-disk-cost, instant. - Cert PFX export pass =
ruvds-backup-pfx— temporary. TODO: pass-equivalent на Windows (gpg4win + pass-bash) или derived от machine-creds. - SYSTEM principal, не user account — Task Scheduler SYSTEM имеет full access к C:\sites, Cert:\LocalMachine\My, %SystemRoot%\System32\inetsrv, не требует stored-password. Pattern matches VDS root-cron decision.
Smoke run (manual)
Start-ScheduledTask -TaskName 'RUVDS-Backup-Daily'
# Watch:
Get-Content C:\ProgramData\backup\logs\(Get-Date -Format yyyy-MM-dd).log -Wait
Verify on kreknin:
ssh vitya@195.19.90.188 'du -sh /volume1/NetBackup/ruvds-iis/*/sites/snolla/'
Atomic revert (uninstall)
# On RUVDS:
Unregister-ScheduledTask -TaskName 'RUVDS-Backup-Daily' -Confirm:$false
Remove-Item C:\ProgramData\backup -Recurse -Force
# Optionally: Remove-Item 'C:\Program Files\rclone' -Recurse -Force
# On kreknin (via SSH):
ssh vitya@195.19.90.188 'rm -rf /volume1/NetBackup/ruvds-iis'
# Remove the RUVDS pubkey line from authorized_keys (one line with 'ruvds-backup' comment).