ruvds-backup: add email-notify (Yandex SMTP 587 STARTTLS) + fix size calc
Add dual-channel notifications — ntfy (already there) + email via Send-MailMessage / Yandex SMTP, mirroring VDS msmtp pipeline. Email: noreply@snolla.com -> vitya.kuznetsov@gmail.com. Verified delivered (DKIM pass, SPF pass) via run #2 + manual smoke. Settings sourced from C:\sites\snolla\Web.config <mailSettings> (Yandex SMTP), cross-checked against pass-store snolla-smtp/full-env. Same creds, same account as VDS backup msmtp uses. SMTP port: 587 STARTTLS, NOT 465 implicit-TLS: .NET SmtpClient / Send-MailMessage support only STARTTLS. Yandex accepts both; we use 587 for native PS tooling. VDS msmtp uses 465 implicit-TLS — both work, different tools. Size in email: switched from `rclone size --json | ConvertFrom-Json` (parses fail when rclone NOTICE stderr leaks into stdout) to local Get-ChildItem on C:\sites\snolla. Instant, no JSON dance. setup.ps1: ned params for SMTP creds + OPS_NOTIFY_EMAIL; config.env template extended. README.md: notifications section split into ntfy + email subsections, new SMTP-port + size-calc decisions in Decisions log. Run #2 (12:30:03) and run #3 (12:33) both produced email delivery receipts in user inbox. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -35,9 +35,19 @@ Retention: **7 daily snapshots**. Older — pruned by `rclone purge` in step 4.
|
||||
|
||||
## Notifications
|
||||
|
||||
ntfy topic `vds-backup` (shared with VDS backup) — phone push:
|
||||
- Success: title `RUVDS backup OK (<date>)`, tag `green_circle`, priority `default`
|
||||
- Fail: title `RUVDS backup FAILED (<date>)`, tag `red_circle`, priority `high`
|
||||
**Dual-channel** (oба отправляются после каждого run):
|
||||
|
||||
- **ntfy topic `vds-backup`** (shared с VDS backup) — phone push через ntfy mobile app:
|
||||
- Success: title `RUVDS backup OK (<date>)`, tag `green_circle`, priority `default`
|
||||
- Fail: title `RUVDS backup FAILED (<date>)`, tag `red_circle`, priority `high`
|
||||
|
||||
- **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)
|
||||
|
||||
Если email или ntfy fail — backup itself **не fail'ит** (notify-функции wrapped в try/catch, warning в лог).
|
||||
|
||||
## Decisions log
|
||||
|
||||
@@ -45,6 +55,8 @@ ntfy topic `vds-backup` (shared with VDS backup) — phone push:
|
||||
- **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-Rclone` wrapper** — `$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 + plain `Backup-WebConfiguration`.
|
||||
- **SMTP port 587 STARTTLS, не 465 implicit-TLS** — .NET `SmtpClient` (и Powershell's `Send-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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user