#requires -Version 5.1 #requires -RunAsAdministrator <# .SYNOPSIS One-time setup для RUVDS daily backup → kreknin. Run on RUVDS as Administrator. Idempotent. .DESCRIPTION 1. Generate ed25519 SSH key (`C:\ProgramData\backup\kreknin-key`). 2. Install rclone v1.74+ to `C:\Program Files\rclone\rclone.exe`. 3. Write rclone.conf (SFTP remote `kreknin` без host-key validation — see Decisions log). 4. Write config.env с ntfy creds (chmod-equiv via icacls SYSTEM+Administrators). 5. Deploy run.ps1 (companion file в this folder). 6. Register ScheduledTask `RUVDS-Backup-Daily` daily @ 04:30 MSK as SYSTEM. User action required between steps 1 и 6: add `kreknin-key.pub` to `/volume1/homes/vitya/.ssh/authorized_keys` on kreknin Synology. #> [CmdletBinding()] param( [string]$NtfyUser = 'vitya', [string]$NtfyPass = 'Pryakhin9', [string]$NtfyUrl = 'https://ntfy.vds.kzntsv.site', [string]$NtfyTopic = 'vds-backup', [string]$SmtpHost = 'smtp.yandex.ru', [int]$SmtpPort = 587, [string]$SmtpFrom = 'noreply@snolla.com', [string]$SmtpUser = 'noreply@snolla.com', [string]$SmtpPass = 'JP44ajqZ3K#W', [string]$OpsNotifyEmail = 'vitya.kuznetsov@gmail.com', [string]$ScheduleAt = '04:30' ) $ErrorActionPreference = 'Stop' $base = 'C:\ProgramData\backup' New-Item -ItemType Directory -Path $base -Force | Out-Null # 1. SSH key $keyPath = "$base\kreknin-key" if (-not (Test-Path $keyPath)) { ssh-keygen -t ed25519 -f $keyPath -N '""' -C 'ruvds-backup' -q & cmd.exe /c "icacls `"$keyPath`" /inheritance:r /grant `"SYSTEM:(F)`" /grant `"BUILTIN\Administrators:(F)`"" | Out-Null Write-Host "[OK] SSH key generated: $keyPath" Write-Host "ADD TO KREKNIN authorized_keys:" Get-Content "$keyPath.pub" Read-Host "Press Enter when pubkey added to kreknin" } else { Write-Host "[SKIP] SSH key exists" } # 2. rclone $rcloneExe = 'C:\Program Files\rclone\rclone.exe' if (-not (Test-Path $rcloneExe)) { $ver = (Invoke-RestMethod 'https://downloads.rclone.org/version.txt' -UseBasicParsing).Trim() -replace '^rclone\s+v|^v','' $url = "https://downloads.rclone.org/v$ver/rclone-v$ver-windows-amd64.zip" $tmp = "$env:TEMP\rclone.zip" Invoke-WebRequest $url -OutFile $tmp -UseBasicParsing if (Test-Path "$env:TEMP\rclone") { Remove-Item "$env:TEMP\rclone" -Recurse -Force } 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" $rcloneExe -Force Write-Host "[OK] rclone installed: v$ver" } else { Write-Host "[SKIP] rclone installed: $(& $rcloneExe --version | Select-Object -First 1)" } # 3. rclone.conf — no known_hosts_file (rclone go-sftp lib чувствителен к формату; ssh-key auth = trust enough) @" [kreknin] type = sftp host = 195.19.90.188 user = vitya key_file = $keyPath disable_hashcheck = true "@ | Set-Content "$base\rclone.conf" -Encoding ASCII -Force & cmd.exe /c "icacls `"$base\rclone.conf`" /inheritance:r /grant `"SYSTEM:(F)`" /grant `"BUILTIN\Administrators:(F)`"" | Out-Null Write-Host "[OK] rclone.conf written" # 4. config.env (ntfy + SMTP creds) @" NTFY_URL=$NtfyUrl NTFY_TOPIC=$NtfyTopic NTFY_USER=$NtfyUser NTFY_PASS=$NtfyPass SMTP_HOST=$SmtpHost SMTP_PORT=$SmtpPort SMTP_FROM=$SmtpFrom SMTP_USER=$SmtpUser SMTP_PASS=$SmtpPass OPS_NOTIFY_EMAIL=$OpsNotifyEmail "@ | Set-Content "$base\config.env" -Encoding ASCII -Force & cmd.exe /c "icacls `"$base\config.env`" /inheritance:r /grant `"SYSTEM:(F)`" /grant `"BUILTIN\Administrators:(F)`"" | Out-Null Write-Host "[OK] config.env written" # 5. Deploy run.ps1 (assumed alongside this setup.ps1) $srcRun = Join-Path $PSScriptRoot 'run.ps1' if (-not (Test-Path $srcRun)) { throw "run.ps1 not found alongside setup.ps1 ($srcRun)" } Copy-Item $srcRun "$base\run.ps1" -Force & cmd.exe /c "icacls `"$base\run.ps1`" /inheritance:r /grant `"SYSTEM:(F)`" /grant `"BUILTIN\Administrators:(F)`"" | Out-Null Write-Host "[OK] run.ps1 deployed" # 6. Scheduled Task $taskName = 'RUVDS-Backup-Daily' if (Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue) { Unregister-ScheduledTask -TaskName $taskName -Confirm:$false } $action = New-ScheduledTaskAction -Execute 'powershell.exe' ` -Argument "-NoProfile -ExecutionPolicy Bypass -File $base\run.ps1" $trigger = New-ScheduledTaskTrigger -Daily -At $ScheduleAt $principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest $settings = New-ScheduledTaskSettingsSet ` -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries ` -StartWhenAvailable -MultipleInstances IgnoreNew ` -ExecutionTimeLimit (New-TimeSpan -Hours 2) Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force | Out-Null Write-Host "[OK] ScheduledTask '$taskName' registered ($ScheduleAt daily, SYSTEM, 2h max)" Write-Host "" Write-Host "=== Setup complete. Test with: Start-ScheduledTask -TaskName '$taskName' ===" Write-Host "Log: $base\logs\.log"