Files
admin/.tasks/ruvds-backup-daily-kreknin.md
vitya df5878cdad tasks: + [ruvds-backup-daily-kreknin] ready — параллель к VDS backup
Создаю задачу пока [iis-migration-to-ruvds] в soak window. Закрывает
Open-question "Backup strategy для RUVDS IIS" из migration task.

Pattern параллель [vds-backup-rsync-kreknin] 🟢 — daily backup → kreknin
synology, 7 daily snapshots retention, ntfy на vds-backup topic.

Differences vs VDS:
- Win Server 2025 Core → rclone single-binary, не rsync (no cygwin/WSL)
- Task Scheduler SYSTEM-account, не cron-root
- 04:30 MSK (за 30 мин до VDS backup чтобы не пересекать uplink)
- Backup scope: C:\sites\snolla + applicationHost.config + IIS native
  Backup-WebConfiguration + cert store PFX export + sshd config

Decisions log в task file: tool=rclone (rejected restic encrypted-dedupe
как overkill для transitional setup, robocopy-over-SMB fragile);
SYSTEM-principal mirrors VDS root-cron pattern; PFX export pass=temp
'pfximport' (TODO: pass-equivalent на Windows когда найдём).

Open questions для решения user'а: when to start (recommend сейчас, не
ждать full cutover), kreknin SSH ACL add pubkey to authorized_keys
(требует user action).

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

215 lines
12 KiB
Markdown
Raw 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
## Goal
Ежедневный backup с RUVDS (`80.64.31.36` / Win Server 2025 Core) → [[../entities/kreknin-synology]] (`195.19.90.188 / kreknin.site`) в **04:30 MSK** (за 30 мин до `[vds-backup-rsync-kreknin]` 05:00, чтобы не пересекать uplink). После каждого прохода — ntfy push на topic `vds-backup` (тот же что VDS backup пушит — общий agg-канал).
Параллель `[vds-backup-rsync-kreknin]` 🟢 (VDS Ubuntu → kreknin via rsync `--link-dest`), но source = Windows Server Core, поэтому:
- Cron нет → Windows Task Scheduler
- rsync нативного нет → **rclone** sync over SFTP (см. Decisions ниже)
- root-cron-as-uid недоступен → SYSTEM scheduled task
## Scope (what to backup)
Минимум для disaster-recovery RUVDS state:
| Path on RUVDS | Reason | Approx size |
|---|---|---|
| `C:\sites\snolla\` | CMS site content + Web.config + media | 8.66 GB (grows slowly) |
| `C:\Windows\System32\inetsrv\config\applicationHost.config` | IIS site/binding/apppool config | <1 MB |
| Backup-WebConfiguration export | IIS native config snapshot (`Backup-WebConfiguration -Name ...`) → `%SystemRoot%\System32\inetsrv\backup\` | <5 MB |
| `C:\ProgramData\ssh\` (sshd_config + administrators_authorized_keys) | SSH access state | <50 KB |
| LE certs export (`Get-ChildItem Cert:\LocalMachine\My` → Export-PfxCertificate с временным пасс'ом + git-tracked) | для restore без re-extract из traefik acme.json | <1 MB |
**Не бэкапить:**
- `C:\Windows\` system files — RUVDS rebuild = fresh install (~5 мин через RUVDS panel).
- `C:\Program Files\` — installed software re-installable from scripts (bootstrap.ps1).
- IIS logs (`C:\inetpub\logs\LogFiles\`) — диагностические, не recovery-critical. Optional.
## Open questions
- [ ] **Tool:** rclone sync over SFTP (см. Decisions ниже — recommended). Alternative — restic (encrypted dedupe) — defer как для VDS; RUVDS↔kreknin link через public internet, но обе стороны ours, single-hop. Add encryption если threat model changes.
- [ ] **Retention:** 7 daily snapshots — следуем VDS-pattern. Per-day dirs (`/volume1/NetBackup/ruvds-iis/2026-05-25/`) — без hardlink dedup, 8.66 GB × 7 = ~60 GB на kreknin (5.7T free, easy).
- [ ] **Auth — RUVDS→kreknin SSH key:** генерировать новый ed25519 на RUVDS (`ssh-keygen` ships with OpenSSH client/server caps), pubkey добавить в `/volume1/homes/vitya/.ssh/authorized_keys` на kreknin через user. Private key хранится в `C:\ProgramData\backup\ssh_key` (ACL: SYSTEM + Administrators only).
- [ ] **Notification:** ntfy `vds-backup` topic — reuse (общий backup-канал, удобно для phone alerts). Title включает source-host чтобы отличать VDS-backup от RUVDS-backup.
- [ ] **Encryption-at-rest на kreknin:** none (как для VDS). RUVDS data = sites content (public web pages anyway) + config files. Не sensitive enough для encryption overhead в transitional setup.
## Implementation sketch
### 1. rclone install + config
```powershell
# Install rclone (one-time)
$ver = (Invoke-RestMethod 'https://downloads.rclone.org/version.txt').Trim('v').Trim()
$url = "https://downloads.rclone.org/v$ver/rclone-v$ver-windows-amd64.zip"
$tmp = "$env:TEMP\rclone.zip"
Invoke-WebRequest $url -OutFile $tmp -UseBasicParsing
Expand-Archive $tmp -DestinationPath "$env:TEMP\rclone" -Force
New-Item -ItemType Directory 'C:\Program Files\rclone' -Force | Out-Null
Copy-Item "$env:TEMP\rclone\rclone-*-windows-amd64\rclone.exe" 'C:\Program Files\rclone\' -Force
[Environment]::SetEnvironmentVariable('Path', "$env:Path;C:\Program Files\rclone", 'Machine')
# Generate SSH key для kreknin auth (one-time)
ssh-keygen -t ed25519 -f C:\ProgramData\backup\kreknin-key -N '""' -C 'ruvds-backup'
icacls C:\ProgramData\backup\kreknin-key /inheritance:r /grant 'SYSTEM:(F)' /grant 'Administrators:(F)'
# Затем user добавляет .pub в kreknin /volume1/homes/vitya/.ssh/authorized_keys
# rclone config — SFTP remote
@'
[kreknin]
type = sftp
host = 195.19.90.188
user = vitya
key_file = C:\ProgramData\backup\kreknin-key
disable_hashcheck = true
'@ | Set-Content C:\ProgramData\backup\rclone.conf -Encoding ASCII
```
### 2. Backup script `C:\ProgramData\backup\run.ps1`
```powershell
$ErrorActionPreference = 'Stop'
$today = Get-Date -Format 'yyyy-MM-dd'
$start = Get-Date
$logFile = "C:\ProgramData\backup\logs\$today.log"
New-Item -ItemType Directory (Split-Path $logFile) -Force | Out-Null
Start-Transcript -Path $logFile -Append -Force | Out-Null
try {
# 1. IIS config snapshot
Backup-WebConfiguration -Name "daily-$today" -Force | Out-Null
$iisBackupDir = "$env:SystemRoot\System32\inetsrv\backup\daily-$today"
# 2. Export cert store (LocalMachine\My) to PFX with timestamp passphrase
$pfxPass = ConvertTo-SecureString 'pfximport' -AsPlainText -Force # TODO move to pass-equivalent
$certDir = "C:\ProgramData\backup\certs-$today"
New-Item -ItemType Directory $certDir -Force | Out-Null
Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.HasPrivateKey } | ForEach-Object {
$name = ($_.Subject -replace '[^A-Za-z0-9.-]','_').Substring(0, [math]::Min(40, $_.Subject.Length))
try {
Export-PfxCertificate -Cert $_ -FilePath "$certDir\$name.pfx" -Password $pfxPass -ErrorAction SilentlyContinue | Out-Null
} catch {}
}
# 3. rclone sync — push to dated dir on kreknin
& 'C:\Program Files\rclone\rclone.exe' sync `
--config C:\ProgramData\backup\rclone.conf `
--log-file $logFile --log-level INFO `
--transfers 4 --checkers 8 `
C:\sites\snolla `
"kreknin:/volume1/NetBackup/ruvds-iis/$today/sites/snolla/"
if ($LASTEXITCODE -ne 0) { throw "rclone snolla failed" }
& 'C:\Program Files\rclone\rclone.exe' copy `
--config C:\ProgramData\backup\rclone.conf `
C:\Windows\System32\inetsrv\config\applicationHost.config `
"kreknin:/volume1/NetBackup/ruvds-iis/$today/iis-config/"
& 'C:\Program Files\rclone\rclone.exe' sync `
--config C:\ProgramData\backup\rclone.conf `
$iisBackupDir `
"kreknin:/volume1/NetBackup/ruvds-iis/$today/iis-backup-$today/"
& 'C:\Program Files\rclone\rclone.exe' sync `
--config C:\ProgramData\backup\rclone.conf `
$certDir `
"kreknin:/volume1/NetBackup/ruvds-iis/$today/certs/"
& 'C:\Program Files\rclone\rclone.exe' sync `
--config C:\ProgramData\backup\rclone.conf `
C:\ProgramData\ssh `
"kreknin:/volume1/NetBackup/ruvds-iis/$today/ssh-config/"
# 4. Retention prune — keep last 7 daily snapshots
& 'C:\Program Files\rclone\rclone.exe' lsd `
--config C:\ProgramData\backup\rclone.conf `
'kreknin:/volume1/NetBackup/ruvds-iis/' |
Where-Object { $_ -match '\d{4}-\d{2}-\d{2}' } |
ForEach-Object { ($_ -split '\s+')[-1] } |
Sort-Object | Select-Object -SkipLast 7 |
ForEach-Object {
& 'C:\Program Files\rclone\rclone.exe' purge `
--config C:\ProgramData\backup\rclone.conf `
"kreknin:/volume1/NetBackup/ruvds-iis/$_"
}
# 5. Cleanup local temp
Remove-Item $certDir -Recurse -Force
Remove-Item $iisBackupDir -Recurse -Force -ErrorAction SilentlyContinue
# 6. Notification — ntfy success
$duration = (New-TimeSpan -Start $start -End (Get-Date)).TotalSeconds
$msg = "RUVDS backup $today OK | $([math]::Round($duration,0))s"
$ntfyToken = (Get-Content C:\ProgramData\backup\ntfy-token.txt)
Invoke-RestMethod -Uri 'https://ntfy.vds.kzntsv.site/vds-backup' `
-Method POST `
-Headers @{ Authorization = "Bearer $ntfyToken"; Title = "RUVDS backup success"; Priority = 'default'; Tags = 'green_circle' } `
-Body $msg
} catch {
# Notification — ntfy failure
$msg = "RUVDS backup $today FAILED: $($_.Exception.Message)"
$ntfyToken = (Get-Content C:\ProgramData\backup\ntfy-token.txt -ErrorAction SilentlyContinue)
if ($ntfyToken) {
Invoke-RestMethod -Uri 'https://ntfy.vds.kzntsv.site/vds-backup' `
-Method POST `
-Headers @{ Authorization = "Bearer $ntfyToken"; Title = "RUVDS backup FAILED"; Priority = 'high'; Tags = 'red_circle' } `
-Body $msg
}
throw
} finally {
Stop-Transcript | Out-Null
}
```
### 3. Schedule via Windows Task Scheduler
```powershell
$action = New-ScheduledTaskAction -Execute 'powershell.exe' `
-Argument '-NoProfile -ExecutionPolicy Bypass -File C:\ProgramData\backup\run.ps1'
$trigger = New-ScheduledTaskTrigger -Daily -At '04:30'
$principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -MultipleInstances IgnoreNew
Register-ScheduledTask -TaskName 'RUVDS-Backup-Daily' `
-Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force
```
## Decisions log
- **2026-05-24 (task creation):** Tool = **rclone**, not robocopy-over-SMB and not restic. Reasoning:
- rsync на Win Server Core отсутствует (no cygwin/WSL on Core). Установка cygwin/MSYS — лишний пакет, security surface.
- robocopy + SMB-mount kreknin требует Synology SMB включён + Windows credentials cached + UNC reliability over WAN — fragile.
- rclone — single .exe (~50 MB), SFTP backend native, reliable, well-supported on Server Core, log-friendly.
- restic — encrypted+dedupe — overkill пока link trusted; defer like VDS.
- **2026-05-24:** **Run as SYSTEM**, не пользовательский account. SYSTEM имеет full доступ к `C:\sites\` + `C:\Windows\System32\inetsrv\` + cert store, не требует stored-password в Task Scheduler. Pattern matches `[vds-backup-rsync-kreknin]` root-cron decision.
- **2026-05-24:** **PFX export `pfximport` password** — temporary, will move to pass-equivalent on RUVDS (или derived из машинной creds). Open question: how to handle pass-on-Windows-Core analog. Defer пока migration не cutover'нется полностью.
## Open questions (additional)
- [ ] **Когда стартовать:** сейчас (parallel с soak window `[iis-migration-to-ruvds]`) или после full cutover? Recommendation: **сейчас** — даже до full cutover, backup snolla content на RUVDS даёт rollback-evidence если RUVDS state corrupt'нется. Lateral risk minimal — backup идёт через ssh-key auth, кroil-кroil traffic.
- [ ] **kreknin SSH ACL on `/volume1/homes/vitya/`** — текущий ACL разрешает `vitya` user. RUVDS пушит как `vitya@kreknin` через SFTP — нужна добавка pubkey в authorized_keys. Без user action не сработает.
- [ ] **Backup `C:\sites\snolla` size growth** — CMS file uploads через админку могут вырасти со временем. Monitor disk usage на kreknin через quarterly check.
## Completed steps
(none yet)
## Notes
- **Триггер:** task создан 2026-05-24, можно стартовать paralleltno с soak'ом RUVDS. Не блокировать full DNS swap (если backup pipeline ломается — rollback на source IIS:8089 всегда возможен).
- **Integration:** ntfy topic `vds-backup` — общий с VDS backup. Title differentiator чтобы phone-side фильтровать.
- **Атомарный revert (откат всей задачи):**
```powershell
# На RUVDS:
Unregister-ScheduledTask -TaskName 'RUVDS-Backup-Daily' -Confirm:$false
Remove-Item C:\ProgramData\backup -Recurse -Force
# На kreknin: (через SSH)
ssh vitya@195.19.90.188 'rm -rf /volume1/NetBackup/ruvds-iis'
```
- **Relation to [iis-migration-to-ruvds]:** этот backup закрывает "Backup strategy для RUVDS IIS" open-question из migration task. Когда migration переходит в 🟢, эту задачу нужно явно отметить как dependency-closer.
- **Future evolution:** когда snolla-on-node будет ready и IIS станет obsolete (long-term goal per migration task notes) — этот backup можно retire вместе с RUVDS.
<!-- created-by: vitya / 2026-05-24 / trigger: post-iis-migration-partial-cutover, while-soak-window-open -->