Files
vitya bb7dd40436 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>
2026-05-24 12:35:25 +03:00

88 lines
5.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 to `C:\ProgramData\backup\run.ps1` by setup.ps1).
## Initial install (rebuilding RUVDS from scratch)
```powershell
# На 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>)`, 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
- **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-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.
## Smoke run (manual)
```powershell
Start-ScheduledTask -TaskName 'RUVDS-Backup-Daily'
# Watch:
Get-Content C:\ProgramData\backup\logs\(Get-Date -Format yyyy-MM-dd).log -Wait
```
Verify on kreknin:
```powershell
ssh vitya@195.19.90.188 'du -sh /volume1/NetBackup/ruvds-iis/*/sites/snolla/'
```
## Atomic revert (uninstall)
```powershell
# 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).
```