From 22786e1865e06174b91dbcfc0cb8e7499532567d Mon Sep 17 00:00:00 2001 From: vitya Date: Sun, 24 May 2026 23:31:14 +0300 Subject: [PATCH] wiki(ingest): RUVDS IIS migration + daily backup pipeline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - entities/ruvds-iis-host (NEW) — 80.64.31.36, Win Server 2025 Core, 25 SNI HTTPS bindings, 2/24 hostnames DNS-flipped - sources/iis-migration-to-ruvds-2026-05-23 (NEW) — chronology, SSH/scp pivot после home-ISP outbound 445 block - sources/ruvds-backup-daily-kreknin-2026-05-24 (NEW) — rclone+SFTP SYSTEM task daily 04:30, ntfy общий канал - concepts/traefik-acme-json-to-iis-cert-import (NEW) — PFX + SNI recipe - concepts/windows-server-2025-core-bootstrap — SMB deprecate, HTTP middlebox warning, HTTP/2 note; backup/cert open-Qs закрыты - entities/windows-recovery-host — partial-cutover state, imgproxy SPOF carve-out, tandemmebel indefinitely здесь - overview / index / log — catalog refresh Co-Authored-By: Claude Opus 4.7 (1M context) --- .../traefik-acme-json-to-iis-cert-import.md | 124 ++++++++++++++++++ .../windows-server-2025-core-bootstrap.md | 65 ++++++++- .wiki/entities/ruvds-iis-host.md | 82 ++++++++++++ .wiki/entities/windows-recovery-host.md | 23 +++- .wiki/index.md | 4 + .wiki/log.md | 2 + .wiki/overview.md | 5 +- .../iis-migration-to-ruvds-2026-05-23.md | 114 ++++++++++++++++ .../ruvds-backup-daily-kreknin-2026-05-24.md | 81 ++++++++++++ 9 files changed, 492 insertions(+), 8 deletions(-) create mode 100644 .wiki/concepts/traefik-acme-json-to-iis-cert-import.md create mode 100644 .wiki/entities/ruvds-iis-host.md create mode 100644 .wiki/sources/iis-migration-to-ruvds-2026-05-23.md create mode 100644 .wiki/sources/ruvds-backup-daily-kreknin-2026-05-24.md diff --git a/.wiki/concepts/traefik-acme-json-to-iis-cert-import.md b/.wiki/concepts/traefik-acme-json-to-iis-cert-import.md new file mode 100644 index 0000000..58b8e8c --- /dev/null +++ b/.wiki/concepts/traefik-acme-json-to-iis-cert-import.md @@ -0,0 +1,124 @@ +--- +title: Экспорт LE certs из traefik acme.json в IIS (PFX + SNI bindings) +type: concept +tags: [traefik, iis, letsencrypt, certs, pfx, sni, windows] +sources: [../sources/iis-migration-to-ruvds-2026-05-23.md] +updated: 2026-05-24 +--- + +# traefik `acme.json` → IIS cert import + +Recipe для one-shot переноса Let's Encrypt certs из traefik `acme.json` (single-file ACME store) в IIS на Windows host с SNI multi-binding'ами. Использован при миграции [[../entities/ruvds-iis-host]] 2026-05-23 для 14 LE certs → 25 HTTPS hostnames bound via SNI. **Это не renewal pipeline**, а bootstrap-перенос — для long-term renewal recommend `win-acme` standalone на IIS host'е (см. footnote). + +## Когда применять + +- Migration: traefik-on-A → IIS-on-B, certs нужны до того как ACME-validation с нового host'а станет возможной (DNS ещё указывает на старый host, HTTP-01 challenge bounce'нется). +- Bootstrap пилотного IIS-сервера с готовыми certs для smoke testing **до** DNS swap'а. + +**Не применять для regular renewal** — каждый renewal цикл traefik будет генерировать новый cert, и manual re-export не масштабируется. После full DNS swap → `win-acme` HTTP-01 на IIS-side directly. + +## Входные данные + +- `acme.json` — обычно в `/letsencrypt/acme.json`. Содержит JSON с массивом `Certificates[].domain.main`, `.sans`, `.certificate` (base64 PEM bundle), `.key` (base64 PEM private key). +- Target IIS host с PowerShell + OpenSSL (для cert conversion) + access to `Cert:\LocalMachine\My` store. + +## Recipe (per cert) + +### 1. Распаковать пару PEM из acme.json + +```powershell +$acme = Get-Content C:\path\to\acme.json | ConvertFrom-Json +# Resolver key — обычно "letsencrypt" или имя из traefik.yml +$resolver = $acme.letsencrypt +foreach ($cert in $resolver.Certificates) { + $domain = $cert.domain.main + $sans = $cert.domain.sans # может быть $null + $safeName = $domain -replace '\*','wildcard' + + [System.Convert]::FromBase64String($cert.certificate) | Set-Content "C:\temp\$safeName.crt" -AsByteStream + [System.Convert]::FromBase64String($cert.key) | Set-Content "C:\temp\$safeName.key" -AsByteStream +} +``` + +### 2. Convert PEM pair → PFX (OpenSSL) + +```powershell +$pfxPass = 'pfximport' # temp passphrase, only for Import step +& openssl pkcs12 -export ` + -inkey "C:\temp\$safeName.key" ` + -in "C:\temp\$safeName.crt" ` + -out "C:\temp\$safeName.pfx" ` + -name $domain ` + -password "pass:$pfxPass" +``` + +### 3. Import PFX → `Cert:\LocalMachine\My` + +```powershell +$securePass = ConvertTo-SecureString $pfxPass -AsPlainText -Force +$imported = Import-PfxCertificate ` + -FilePath "C:\temp\$safeName.pfx" ` + -CertStoreLocation 'Cert:\LocalMachine\My' ` + -Password $securePass +# $imported.Thumbprint — нужен для следующего шага +``` + +### 4. SNI binding в IIS (per hostname) + +Один cert может покрывать несколько SANs — для каждого hostname создать **separate binding** с **SslFlags=1 (SNI)**: + +```powershell +$allHosts = @($domain) + @($sans | Where-Object { $_ }) +foreach ($hostname in $allHosts) { + # 4a. Create binding without cert + New-WebBinding -Name 'snolla' ` + -IPAddress '*' -Port 443 -Protocol 'https' ` + -HostHeader $hostname -SslFlags 1 # 1 = SNI + + # 4b. Attach cert via thumbprint (нужен netsh-стиль через IIS:\) + $binding = Get-WebBinding -Name 'snolla' -Port 443 -HostHeader $hostname + $binding.AddSslCertificate($imported.Thumbprint, 'My') +} +``` + +> **SslFlags=1 обязателен.** Без SNI один port 443 = один cert per IP — Windows откажется bind'ить второй cert на тот же `*:443`. С SNI можно навесить ~unlimited hostnames на один `*:443`. + +## Verification + +```powershell +# Список bindings: +Get-WebBinding -Port 443 | Format-Table protocol, bindingInformation, sslFlags + +# Сертификат за binding: +$binding.attributes['certificateHash'].Value # thumbprint +$binding.attributes['certificateStoreName'].Value # "My" + +# External smoke (с другого host'а — home middlebox может mangle Host header): +curl -k --resolve "$hostname:443:80.64.31.36" "https://$hostname/" -I +# Должен вернуть chain LE R13 + correct Subject CN +``` + +HTTP/2 negotiate'ится auto (IIS 10 + Windows Server 2019+ → ALPN supported из коробки). + +## Gotchas + +- **`acme.json` permission** на Linux: `chmod 600`, traefik не запустится с другим. На Windows copy-out для conversion'а — нужны Admin perms. +- **PEM bundle order** в acme.json: `certificate` поле содержит leaf + chain (Let's Encrypt R13 + ISRG Root X1). OpenSSL pkcs12 импортит весь bundle корректно — IIS отдаст полный chain. +- **PFX password** — только для transit между PEM и cert store, после import не используется. `pfximport` (или любой placeholder) — OK; не путать с pass для encrypted PFX-on-disk storage. +- **HostHeader case-sensitivity** в `New-WebBinding`: IIS lowercase'ит автоматически, но скрипт принимай canonical lowercase. +- **Wildcard SANs:** если cert `*.example.com` — нужно отдельный binding для каждого конкретного subdomain'а (Windows не делает wildcard matching на binding'ах автоматически). Либо использовать default-cert на listener'е (`netsh http add sslcert`) — но это break'нет multi-cert SNI scenario. +- **Cert duplicates:** повторный import того же cert'а создаёт duplicate в `Cert:\LocalMachine\My`. Idempotency — check thumbprint exists перед import'ом. +- **`netsh http show sslcert`** — для low-level audit что binding'и реально привязаны (PowerShell `Get-WebBinding` иногда показывает stale state после ручных правок IIS Manager'ом). + +## Limits / когда recipe мал + +- **>30 hostnames** — `Import-PfxCertificate` + `New-WebBinding` цикл становится медленным (~5 sec/cert). Batch'ить через `appcmd add binding /commit:apphost`. +- **TLS 1.3** — IIS 10 на Server 2022+ supports; на Server 2019 — Edge case. Не зависит от recipe — от Windows feature. +- **Renewal** — этот recipe **не покрывает**. Variant A (win-acme HTTP-01 standalone) предпочтительнее, см. [[../sources/iis-migration-to-ruvds-2026-05-23]] Outstanding (post-soak). + +## Cross-refs + +- Use case: [[../sources/iis-migration-to-ruvds-2026-05-23]] Phase 6 +- Source acme.json расположение: traefik-on-windows-host setup, см. [[traefik-on-windows-docker-desktop]] +- Long-term replacement: `win-acme` (wacs.exe) standalone — пока не documented as concept; reference https://www.win-acme.com/ +- Bootstrap-host где recipe был применён: [[../entities/ruvds-iis-host]] diff --git a/.wiki/concepts/windows-server-2025-core-bootstrap.md b/.wiki/concepts/windows-server-2025-core-bootstrap.md index ef1ba12..508f48c 100644 --- a/.wiki/concepts/windows-server-2025-core-bootstrap.md +++ b/.wiki/concepts/windows-server-2025-core-bootstrap.md @@ -9,6 +9,8 @@ related: [[iis-migration-2026-05-19-postmortem]], [[recovery-architecture-snapsh Из коробки на RUVDS (2GB RAM, 30GB HDD, Win Server 2025 Core, RDP-only) машина **не готова** ни принимать файлы по SMB, ни хостить IIS — стандартный сценарий «купил, RDP'нулся, robocopy'нул» не работает. Документ фиксирует дефолтное состояние, default-blockers, и матрицу transfer-методов для переноса content'а с windows-recovery-host. +> **Update 2026-05-24 (post-migration):** SMB transfer-метод **deprecated** — outbound TCP/445 блокирует residential RU ISP (стандартная анти-worm политика). Canonical transfer-метод = **SSH/scp** (см. §«Update 2026-05-24» ниже). HTTP smoke с home-network также unreliable — DPI/transparent proxy mangles Host header. + ## Дефолтное состояние fresh Win Server 2025 Core | Компонент | Дефолт | Нужно для IIS-host'инга | @@ -48,7 +50,7 @@ Test-NetConnection -ComputerName -Port 445 | **SFTP** (OpenSSH server feature) | `Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0` + start sshd + FW 22 | works с любого Linux/Mac source; ключи безопасно | extra service surface; sshd default config иногда permissive | | **HTTP PUT через временный traefik+webdav** | overkill для bootstrap | reusable для последующих deploy'ев | сначала нужен IIS/nginx running — но IIS ещё не deployed → chicken-and-egg | -**Recommendation для IIS migration:** SMB inbound с source-IP whitelist. Самый быстрый для 11 sites × ~1 GB; native robocopy /Z поддерживает interrupt-resume; FW rule убирается после migration cutover. +**~~Recommendation для IIS migration: SMB inbound с source-IP whitelist~~** — **deprecated 2026-05-24**, см. §«Update 2026-05-24» ниже. Текущий canonical — **SSH/scp**. ```powershell # На RUVDS (RDP-сессия, PowerShell): @@ -96,9 +98,68 @@ net use \\\sites /delete - **LE certs:** если IIS будет terminate'ить TLS напрямую — `win-acme` (wacs.exe) standalone-friendly на Core. Альтернатива — traefik-on-RUVDS перед IIS, но это лишняя layer для 11 sites. - **Backup strategy для RUVDS:** unsolved — RUVDS native snapshots = VDS-snapshot-level, не file-level. Daily rsync sites+IIS config → kreknin (расширить `vds-backup-rsync-kreknin` на источник RUVDS) — отдельная chore-task после успешного cutover. +## Update 2026-05-24 — SMB deprecate + HTTP middlebox + HTTP/2 + +### SMB deprecated — home-ISP блокирует outbound 445 + +После выполнения bootstrap-чеклиста выше (FW 445 + SMB share созданы на RUVDS) **TCP/445 всё равно не reachable с source**. Root cause — residential RU ISP блокируют outbound 445 (стандартная анти-worm политика). FW scoping на RUVDS-стороне корректен, проблема на source side и **не fixable** без VPN. + +> **Canonical transfer-метод теперь — SSH/scp.** Pivot zaprotokolirovan в [[../sources/iis-migration-to-ruvds-2026-05-23]] Phase 2-3. + +Setup (на RUVDS): + +```powershell +# OpenSSH server feature (если ещё не установлен): +Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 +Start-Service sshd +Set-Service -Name sshd -StartupType Automatic + +# FW 22 scoped к source IP (не глобально): +New-NetFirewallRule -DisplayName "ssh-from-source" -Direction Inbound ` + -Protocol TCP -LocalPort 22 -RemoteAddress -Action Allow + +# Deploy pubkey для administrators (правильный ACL обязателен): +$pub = "ssh-ed25519 AAAA... source-comment" +Set-Content C:\ProgramData\ssh\administrators_authorized_keys $pub +icacls C:\ProgramData\ssh\administrators_authorized_keys /inheritance:r ` + /grant 'SYSTEM:(F)' /grant 'BUILTIN\Administrators:(F)' +``` + +Source-side transfer: + +```powershell +scp -i ~/.ssh/ -r C:\sites\snolla ` + Administrator@:C:/sites/ +``` + +8.66 GB / 44725 files за ~25 мин на 5 MB/s home uplink. Не parallel, но resume через `scp -r` после прерывания не работает — нужен `rsync` (нет на Core) или restart с нуля. Для production cutover это OK; для multi-GB content с unreliable link — `rclone copy` (см. [[../sources/ruvds-backup-daily-kreknin-2026-05-24]]). + +После cutover — `Remove-NetFirewallRule -DisplayName 'ssh-from-source'`, `Remove-Item C:\ProgramData\ssh\administrators_authorized_keys`. + +### HTTP middlebox в home network mangles Host header + +Local smoke testing с home network через external IP `curl -H "Host: real-hostname.example" http:///` **возвращает default catch-all content**, не per-tenant. Inside RUVDS (loopback) — корректно. С другой сети (VDS, mobile uplink) — корректно. SSH tunnel `localhost:N → ruvds:80` — корректно. + +> **Conclusion:** home-ISP / OpenWRT DPI / transparent proxy mangles Host header для **direct external HTTP**. Real end-users из других сетей не affected. Для smoke testing — обязательно SSH tunnel либо smoke с VDS/mobile. + +### HTTP/2 auto-negotiates на IIS 10 + Server 2022/2025 + +ALPN supported из коробки; `curl --http2 https://...` → `HTTP/2 200`. Не требует config'а. + +### Backup pipeline — закрыт + +`Backup strategy для RUVDS` в исходном «Gotcha-fineprint» — **закрыт** 2026-05-24: rclone + SFTP → kreknin daily 04:30 MSK. См. [[../sources/ruvds-backup-daily-kreknin-2026-05-24]] для recipe + scripts. + +### Cert import recipe — закрыт + +Перенос LE certs из traefik `acme.json` → IIS PFX → SNI bindings вынесен в отдельный recipe-концепт: [[traefik-acme-json-to-iis-cert-import]]. + ## Cross-refs - Driver для миграции: [[future-resilient-architecture-goals]] §Workshop pass 1 → IIS-track «вынести IIS с windows-recovery-host чтобы убрать SPOF домашней машины». - Vendor selection: `.tasks/windows-hosting-vendor-research.md` (🟢 closed 2026-05-22 — RUVDS выбран). -- Mid-impl task: `.tasks/iis-migration-to-ruvds.md` (🟡 paused 2026-05-23 — этот концепт зафиксирован после failed-robocopy инцидента). +- Live RUVDS host: [[../entities/ruvds-iis-host]]. +- Migration chronology: [[../sources/iis-migration-to-ruvds-2026-05-23]]. +- Backup chronology: [[../sources/ruvds-backup-daily-kreknin-2026-05-24]]. +- Cert import recipe: [[traefik-acme-json-to-iis-cert-import]]. - Source-host postmortem: [[iis-migration-2026-05-19-postmortem]] — что было при первой миграции снолла-recovery → нативный IIS. diff --git a/.wiki/entities/ruvds-iis-host.md b/.wiki/entities/ruvds-iis-host.md new file mode 100644 index 0000000..0131457 --- /dev/null +++ b/.wiki/entities/ruvds-iis-host.md @@ -0,0 +1,82 @@ +--- +title: RUVDS IIS Host (Windows Server 2025 Core) — 80.64.31.36 +type: entity +tags: [hardware, vds, ruvds, windows, iis, cms, snolla, kupimknigi] +sources: [../sources/iis-migration-to-ruvds-2026-05-23.md, ../sources/ruvds-backup-daily-kreknin-2026-05-24.md] +updated: 2026-05-24 +--- + +# RUVDS IIS Host + +Облачный Windows-VDS у [RUVDS](https://ruvds.com), DC Королёв. Куплен 2026-05-23 как destination для миграции IIS-хостинга с [[windows-recovery-host]] — closing SPOF домашней машины для prod CMS сайтов (snolla CMS multi-tenant). Это **отдельный VDS** от [[vds-kzntsv]] (Rusonyx Linux, инфра-стек): RUVDS = только IIS catch-all для CMS hostnames, Rusonyx VDS = gitea/verdaccio/registry/DB park. + +## Hardware / tariff + +- **Vendor:** RUVDS (https://ruvds.com) +- **Tariff:** Windows Server 2025 Core, 2 GB RAM, 30 GB HDD, 1 IPv4 (DC Королёв) +- **OS:** Windows Server 2025 Core (GUI-less, RDP-only management) +- **IPv4:** `80.64.31.36` +- **Activated:** 2026-05-23 + +## Доступ + +- **RDP:** `mstsc /admin` → `80.64.31.36:3389` (открыт из коробки) +- **SSH:** `ssh -i Administrator@80.64.31.36` (OpenSSH.Server enabled; FW 22 был scoped к source IP на время migration, после cutover — cleanup pending) +- **Креды:** `pass show ruvds-iis/full-env` (canonical secret store; раньше лежали plaintext в `.secrets/ruvds-iis.env` — вынесены ретроспективно, см. [[../sources/iis-migration-to-ruvds-2026-05-23]] Decisions log 2026-05-23 09:37) + +## Установленный стек + +- **IIS 10** (`Web-Server` + sub-features + management tools) +- **.NET Framework 4.8** (verified ≥ 528040) +- **URL Rewrite Module 2.1** (msiexec offline) +- **OpenSSH.Server** (Windows capability; sshd running; FW 22 source-scoped) +- **rclone v1.74.2** (`C:\Program Files\rclone\rclone.exe`) — backup pipeline +- **Defender FW:** inbound 80/443 (Any), 22 (source-IP), 3389 (Any); 445 закрыт (SMB transfer-метод deprecated, см. [[../concepts/windows-server-2025-core-bootstrap]]) + +## Что хостит + +| Site | physicalPath | Bindings | Notes | +|---|---|---|---| +| `snolla` (AppPool `snolla`, .NET v4.0 Integrated, ApplicationPoolIdentity) | `C:\sites\snolla\` (8.66 GB / 44725 files, copied 2026-05-23 via SSH/scp) | `*:80:` catch-all HTTP + 25× `*:443:` HTTPS SNI | catch-all для всех CMS hostnames через multi-tenant routing в самом CMS | + +**25 HTTPS hostnames bound via SNI** (LE certs imported from traefik `acme.json`, valid до 2026-07-22, R13): +- ✅ `emspb.ru` / `www.emspb.ru` — DNS flipped 2026-05-24 ~12:00 +- ✅ `kupimknigi.spb.ru` — DNS flipped 2026-05-24 ~00:00 (pilot) +- ⏳ 22 more in queue (`pilorama98.ru`/www, `labtools.ru`/www, `labtools.pro`/www, 12× `*.snolla.com`, `rimiz.ru`/www, `maljarka.tandemmebel.ru`, etc.) — pending DNS TTL drop в reg.ru (TTL=86400 пока) +- ⛔ `tandemmebel.ru` / `www.tandemmebel.ru` — scope-narrowed 2026-05-24, остаются на windows-IIS на неопределённый срок + +**Degraded (CMS-side, не migration defect):** `maljarka.tandemmebel.ru`, `rimiz.ru`/www, `rimiz.snolla.com` — возвращают 502/404 (pre-existing dead-routes от [[../sources/iis-host-migration-2026-05-19]] cleanup; на source IIS:8089 тоже не работают). + +## Ключевые папки + +- `C:\sites\snolla\` — IIS site content (8.66 GB) +- `C:\Windows\System32\inetsrv\config\applicationHost.config` — IIS config +- `C:\ProgramData\backup\` — backup pipeline (rclone.conf, kreknin-key, run.ps1, ntfy-token.txt) — ACL: SYSTEM + Administrators only +- `C:\ProgramData\ssh\administrators_authorized_keys` — temp pubkey для migration scp; **cleanup pending** post full cutover +- `scripts/iis-migration-to-ruvds/01-ruvds-bootstrap.ps1` (в admin repo) — idempotent bootstrap скрипт + +## Backup + +Daily 04:30 MSK → [[kreknin-synology]] via rclone+SFTP. Снимаются: `C:\sites\snolla\`, `applicationHost.config`, `Backup-WebConfiguration` snapshot, exported PFX certs, `C:\ProgramData\ssh\`. Retention 7 daily. ntfy `vds-backup` topic (общий с VDS backup). Smoke run #1 (2026-05-24 11:46:51) — green. См. [[../sources/ruvds-backup-daily-kreknin-2026-05-24]]. + +## Известные риски / SPOF + +- **Image-pipeline SPOF:** RUVDS IIS вызывает `imgproxy.kzntsv.site` который **всё ещё** на [[windows-recovery-host]] — если домашняя машина гаснет, картинки rendering падает (HTML отдаётся OK с RUVDS). Verified post-migration `Test-NetConnection imgproxy.kzntsv.site -Port 443` = OK. Не closing полный SPOF — defer (Option B local nginx-relay / Option D decompile DLL, см. [[../concepts/iis-cutover-to-vds-services]]). +- **2 GB RAM tight:** w3wp ~330 MB cold start. Monitor under prod load — возможно потребуется `RecyclingPeriodicRestartMemory 200MB` per pool. +- **LE renewal pipeline отсутствует:** certs истекают 2026-07-22 (~60 дней window). Pending — `win-acme` standalone с HTTP-01 после full DNS swap (см. [[../sources/iis-migration-to-ruvds-2026-05-23]] Open questions). +- **Home-network HTTP middlebox** (DPI/transparent proxy в OpenWRT/ISP) — mangles Host header для direct external HTTP smoke testing. Real end-users из других сетей не affected. См. [[../concepts/windows-server-2025-core-bootstrap]] Update 2026-05-24. + +## Vendor onboarding + +В отличие от [[../concepts/rusonyx-vps-onboarding-quirks]] (VNC console, dpkg prompts) — RUVDS Windows из коробки RDP-ready, VPN/VNC quirks не зафиксировано. Bootstrap-recipe в [[../concepts/windows-server-2025-core-bootstrap]]. + +## Cross-refs + +- Source-host (где IIS был раньше): [[windows-recovery-host]] +- VDS со shared DBs / MSSQL backend для IIS: [[vds-kzntsv]] +- Backup target: [[kreknin-synology]] +- Migration chronology: [[../sources/iis-migration-to-ruvds-2026-05-23]] +- Backup chronology: [[../sources/ruvds-backup-daily-kreknin-2026-05-24]] +- Bootstrap recipe: [[../concepts/windows-server-2025-core-bootstrap]] +- Cert import recipe: [[../concepts/traefik-acme-json-to-iis-cert-import]] +- Driver / SPOF rationale: [[../concepts/future-resilient-architecture-goals]] diff --git a/.wiki/entities/windows-recovery-host.md b/.wiki/entities/windows-recovery-host.md index a591b65..b9e2b59 100644 --- a/.wiki/entities/windows-recovery-host.md +++ b/.wiki/entities/windows-recovery-host.md @@ -1,9 +1,9 @@ --- title: Windows Recovery Host (рабочий PC пользователя) type: entity -tags: [hardware, windows, docker, virtualbox, iis, recovery] -sources: [../sources/nas-recovery-session-2026-05-18.md] -updated: 2026-05-19 +tags: [hardware, windows, docker, virtualbox, iis, recovery, imgproxy] +sources: [../sources/nas-recovery-session-2026-05-18.md, ../sources/iis-migration-to-ruvds-2026-05-23.md] +updated: 2026-05-24 --- # Windows Recovery Host @@ -88,4 +88,19 @@ updated: 2026-05-19 ## Что должно случиться, если этот PC погаснет -- **Всё** — все сайты лягут. **Single point of failure** — главное замечание для [[future-resilient-architecture-goals]]. +- **Image-pipeline (imgproxy) ляжет для всех сайтов** — RUVDS IIS rendering'ит HTML самостоятельно, но картинки идут через `imgproxy.kzntsv.site` который **всё ещё** на этой машине. Partial SPOF после миграции IIS. +- **`tandemmebel.ru` + www** — лежат полностью (scope-narrowed 2026-05-24, остаются здесь indefinitely). +- **Остальные ~24 CMS hostnames** — degrade gracefully после full DNS swap на RUVDS (HTML работает, картинки нет). Pre-swap — DNS всё ещё указывает сюда → полный outage до swap'а. +- **MSSQL / MinIO** — уже мигрированы на [[vds-kzntsv]] (2026-05-22), здесь только containers running в idle (могут быть decommission'ed). +- Long-term goal — closing image-pipeline SPOF (Option B local nginx-relay / Option D decompile DLL), см. [[future-resilient-architecture-goals]] + [[../concepts/iis-cutover-to-vds-services]]. + +## IIS partial-cutover на RUVDS (2026-05-24) + +IIS site `snolla` **частично мигрирован** на [[ruvds-iis-host]] (`80.64.31.36`). State 2026-05-24: + +- ✅ DNS flipped: `kupimknigi.spb.ru` (~00:00), `emspb.ru` + `www.emspb.ru` (~12:00). Public resolver cache держит старое до TTL=86400 expiry. +- ⏳ В очереди (pending TTL drop до 300s в reg.ru): 22 hostnames — pilorama98/www, labtools.ru/www, labtools.pro/www, 12× *.snolla.com, rimiz.ru/www, maljarka.tandemmebel.ru, etc. +- ⛔ Останутся здесь indefinitely: `tandemmebel.ru` + `www.tandemmebel.ru` (scope narrow). +- ⚠ Source IIS:8089 + traefik routes для CMS-hostnames **всё ещё running** — rollback path на ~1 неделю soak. После — decommission (но не traefik сам, много других routes). + +Подробная chronology — [[../sources/iis-migration-to-ruvds-2026-05-23]]. Driver: [[future-resilient-architecture-goals]]. diff --git a/.wiki/index.md b/.wiki/index.md index 1c4fc91..ef49fc7 100644 --- a/.wiki/index.md +++ b/.wiki/index.md @@ -11,6 +11,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever - [dead-synology-diskstation](entities/dead-synology-diskstation.md) — мёртвая Synology DiskStation (source NAS) - [kreknin-synology](entities/kreknin-synology.md) — Kreknin Synology (backup target + DDNS) - [openwrt-router](entities/openwrt-router.md) — OpenWRT Router (192.168.1.1) +- [ruvds-iis-host](entities/ruvds-iis-host.md) — RUVDS IIS Host (Win Server 2025 Core, 80.64.31.36) — CMS catch-all destination - [snolla-recovery-vm](entities/snolla-recovery-vm.md) — Snolla Recovery VM (VirtualBox, savestate'нута 2026-05-21 после 36h soak) - [vds-kzntsv](entities/vds-kzntsv.md) — VDS kzntsv (Rusonyx 160 NVMe cloud server) - [windows-recovery-host](entities/windows-recovery-host.md) — Windows Recovery Host (рабочий PC пользователя) @@ -34,6 +35,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever - [recovery-architecture-snapshot](concepts/recovery-architecture-snapshot.md) — текущая recovery architecture (2026-05-19/21, attempt 2) - [registry-gc-mount-and-modify-flag](concepts/registry-gc-mount-and-modify-flag.md) — Docker Registry GC mount layout + `-m` flag - [rusonyx-vps-onboarding-quirks](concepts/rusonyx-vps-onboarding-quirks.md) — Rusonyx VPS onboarding quirks (Astra Облако / myvm.rusonyx.ru) +- [traefik-acme-json-to-iis-cert-import](concepts/traefik-acme-json-to-iis-cert-import.md) — Экспорт LE certs из traefik acme.json в IIS (PFX + SNI bindings) - [traefik-file-watch-wsl2-broken](concepts/traefik-file-watch-wsl2-broken.md) — Traefik file-watch broken под Docker Desktop Windows (WSL2 9p mount) - [traefik-on-windows-docker-desktop](concepts/traefik-on-windows-docker-desktop.md) — Traefik на Windows Docker Desktop — нюансы - [traefik-tcp-passthrough-vs-starttls](concepts/traefik-tcp-passthrough-vs-starttls.md) — Traefik TCP passthrough vs STARTTLS-protocols @@ -49,5 +51,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever ## Sources - [iis-host-migration-2026-05-19](sources/iis-host-migration-2026-05-19.md) — IIS Host Migration Session 2026-05-19 chronology +- [iis-migration-to-ruvds-2026-05-23](sources/iis-migration-to-ruvds-2026-05-23.md) — IIS migration to RUVDS — session 2026-05-23/24 (SSH/scp pivot, 25 SNI bindings, partial DNS cutover) - [nas-recovery-session-2026-05-18](sources/nas-recovery-session-2026-05-18.md) — NAS Recovery Session 2026-05-18/19 chronology +- [ruvds-backup-daily-kreknin-2026-05-24](sources/ruvds-backup-daily-kreknin-2026-05-24.md) — RUVDS daily backup → kreknin pipeline standup 2026-05-24 (rclone+SFTP, SYSTEM task) - [vds-kzntsv-bootstrap-2026-05-20](sources/vds-kzntsv-bootstrap-2026-05-20.md) — VDS bootstrap session 2026-05-20 chronology diff --git a/.wiki/log.md b/.wiki/log.md index b7e239b..0e16044 100644 --- a/.wiki/log.md +++ b/.wiki/log.md @@ -21,3 +21,5 @@ Append-only log of wiki operations (ingests, promotions, lints, migrations). ## [2026-05-23] ingest | concepts/windows-server-2025-core-bootstrap — default-blockers (SMB closed, IIS/URL-Rewrite/.NET unverified) + transfer-методов матрица (RDP-redirect / SMB / WinRM / SFTP); recommendation = SMB inbound с source-IP whitelist на время migration. Source: failed-robocopy инцидент 2026-05-23 18:08 (.tasks/iis-migration-to-ruvds.md Decisions log). ## [2026-05-24] ingest | concepts/books-ssh-access — SSH access audit на shared VDS pre-cutover Фазы 3 tenant-split. Retained keys table (1 key, vitya core dev), removed cosmetic dead root key, sshd hardening verified via `sshd -T` (not raw config), fail2ban active 2670 failed/37 banned, only vitya@94.19.247.14 в access log last 7 days. Source: .tasks/books-ssh-audit-shared-vds.md. + +## [2026-05-24] ingest | RUVDS IIS migration + backup pipeline — entities/ruvds-iis-host (NEW, 80.64.31.36 Win Server 2025 Core, 25 SNI bindings, 2/24 hostnames DNS-flipped) + sources/iis-migration-to-ruvds-2026-05-23 (NEW, SSH/scp pivot после SMB-block by home-ISP) + sources/ruvds-backup-daily-kreknin-2026-05-24 (NEW, rclone+SFTP SYSTEM task daily 04:30) + concepts/traefik-acme-json-to-iis-cert-import (NEW, PFX+SNI recipe) + UPDATE concepts/windows-server-2025-core-bootstrap (SMB deprecate, HTTP middlebox warning, HTTP/2 note, backup-strategy + cert-import закрыты) + UPDATE entities/windows-recovery-host (IIS partial-cutover state, imgproxy SPOF carve-out) + UPDATE overview (RUVDS line). Sources: .tasks/iis-migration-to-ruvds.md, .tasks/ruvds-backup-daily-kreknin.md. diff --git a/.wiki/overview.md b/.wiki/overview.md index 1413601..6adb013 100644 --- a/.wiki/overview.md +++ b/.wiki/overview.md @@ -3,9 +3,10 @@ Operational + roadmap workspace for personal-and-client infrastructure stack: - **VDS** (`vds.kzntsv.site`, Rusonyx) — gitea, verdaccio, registry, shared DB park, ntfy, traefik+portainer +- **RUVDS IIS host** (`80.64.31.36`, Win Server 2025 Core) — CMS multi-tenant IIS site `snolla` (catch-all для 24+ hostnames), partial-cutover idёт 2026-05-24 - **NAS** (`kreknin`, Synology DSM) — backup target, Hyper Backup repo, secondary services -- **Windows recovery host** — current CMS prod host (IIS + traefik + docker), to be replaced as part of fault-tolerance roadmap -- **OpenWRT router** — NAT 80/443 → traefik +- **Windows recovery host** — раньше CMS prod IIS (мигрирует на RUVDS), всё ещё хостит imgproxy + `tandemmebel.ru` + parallel running docker/traefik как rollback +- **OpenWRT router** — NAT 80/443 → traefik (на windows-recovery-host) ## Current state diff --git a/.wiki/sources/iis-migration-to-ruvds-2026-05-23.md b/.wiki/sources/iis-migration-to-ruvds-2026-05-23.md new file mode 100644 index 0000000..e9f075b --- /dev/null +++ b/.wiki/sources/iis-migration-to-ruvds-2026-05-23.md @@ -0,0 +1,114 @@ +--- +title: IIS migration to RUVDS — session 2026-05-23/24 +type: source +tags: [iis, ruvds, migration, snolla, cms, ssh, scp, smb, dns, le-certs, sni] +ingested: 2026-05-24 +raw_path: ../../.tasks/iis-migration-to-ruvds.md +updated: 2026-05-24 +--- + +# IIS migration to RUVDS — 2026-05-23/24 + +Перенос IIS-хостинга CMS-сайтов с [[../entities/windows-recovery-host]] (DESKTOP-NSEF0UK, дом, SPOF) на [[../entities/ruvds-iis-host]] (Win Server 2025 Core, RUVDS, 80.64.31.36). Pre-req: MSSQL+MinIO уже мигрированы на [[../entities/vds-kzntsv]] (см. [[../concepts/mssql-on-vds]], [[../concepts/minio-imgproxy-on-vds]]). + +Источник истины — `.tasks/iis-migration-to-ruvds.md`. Live state RUVDS-хоста — [[../entities/ruvds-iis-host]]. + +## Scope finalize (2026-05-24) + +Только 1 IIS site `snolla` (catch-all для ~26 hostnames через CMS multi-tenant routing) — 8.66 GB. `stostayer` уже на external MSSQL (не наш scope), `stostayer.old` local-only (defer), `snolla-identity-manager` dead conn-string (defer). `tandemmebel.ru` + www — **остаются на windows-IIS** на неопределённый срок (scope-narrow 2026-05-24). Из 25 HTTPS bindings — 2 хоста уже DNS-flipped, 22 в очереди после снижения TTL. + +## Хронология + +### Phase 0 — vendor selection (2026-05-22) + +Закрыт research-task `windows-hosting-vendor-research` 🟢 — RUVDS выбран. Сравнение: Rusonyx (Linux only для нужного формата), Selectel, FirstVDS, Beget. Critical constraints: RDP-доступ, .NET Framework 4.8 native, IIS 10, external MSSQL/MinIO connectivity (на VDS после Фазы 2). + +### Phase 1 — purchase + secrets discipline (2026-05-23 09:37) + +RUVDS активирован, RDP creds сохранены изначально plaintext в `.secrets/ruvds-iis.env` в repo tree → нарушение etap-2 secrets-discipline. **Ретроспективно вынесены** в `pass show ruvds-iis/full-env`, `.secrets/` + `*.env` + `*-log.txt` + `*-size.txt` добавлены в `.gitignore`. + +### Phase 2 — failed-robocopy → SMB-block discovery (2026-05-23 18:08 → 22:30) + +**18:08:** Попытка robocopy через UNC `\\80.64.31.36\sites\snolla\` упала exit 16. Initial diagnostics: SMB share не создан + FW 445 не открыт. Создан concept [[../concepts/windows-server-2025-core-bootstrap]] с default-blockers + transfer-методов матрицей. + +**22:30 (session-recovery):** После выполнения bootstrap'а (FW+share созданы) SMB **всё равно** не reachable — TCP/445 не выходит **с home-ISP**. **Real root cause: outbound 445 блокирует ISP** (стандартная анти-worm политика residential провайдеров RU). FW scoping на RUVDS корректен. + +> **Решение:** SMB recommendation в bootstrap-концепте **deprecated**. SSH/scp = canonical transfer-метод. Концепт обновлён, см. [[../concepts/windows-server-2025-core-bootstrap]] Update 2026-05-24. + +### Phase 3 — SSH/scp transfer (2026-05-23 22:35 → 23:13) + +OpenSSH.Server на RUVDS уже был установлен ранее (admin'ом), sshd running. Открыт FW 22 scoped к source IP, deployed ed25519 pubkey в `C:\ProgramData\ssh\administrators_authorized_keys` (правильный ACL — SYSTEM + Administrators only). + +`scp -r C:\sites\snolla → C:/sites/` — **~25 мин** (8.66 GB / 5 MB/s home uplink), exit 0, count+size MATCH (44725 files / 9 302 398 880 bytes). + +### Phase 4 — IIS recreate (2026-05-23 23:18) + +Default Web Site удалён. AppPool `snolla` (.NET v4.0, Integrated, ApplicationPoolIdentity), Website `snolla` с physicalPath `C:\sites\snolla` + catch-all binding `*:80:`. ACL — `IIS APPPOOL\snolla` + `IIS_IUSRS` Read на 46150 file entries. Local smoke (loopback + `Host: kupimknigi.spb.ru`) — 200 OK с правильным title. + +### Phase 5 — HTTP middlebox surprise (2026-05-23 23:25) + +External smoke через home network: все 8 hostnames вернули **`"SNOLLA | Cloud CMS" default`** (28 406 bytes), не per-tenant content. Внутри RUVDS (loopback) — корректно. SSH tunnel localhost:8888→RUVDS:80 → correct. Тест из VDS (другая сеть) → correct. + +> **Conclusion: home-side outbound HTTP mutation** — DPI/transparent proxy в OpenWRT/ISP path mangles Host header. Real end-users из других сетей не пострадают. Affected — только local smoke testing. + +Зафиксировано в [[../concepts/windows-server-2025-core-bootstrap]] Update 2026-05-24. + +### Phase 6 — HTTPS SNI bindings (2026-05-23 23:30) + +Извлечены 14 LE certs из traefik `acme.json` (`C:\Users\vitya\projects\docker\diskstation\traefik\letsencrypt\acme.json`): + +``` +acme.json → openssl pkcs12 -export → PFX → Import-PfxCertificate (RUVDS) → + New-WebBinding *:443: SslFlags=1 (SNI) → AddSslCertificate by thumbprint +``` + +→ **25 HTTPS bindings live**. Cert chain valid (LE R13, до 2026-07-22). HTTP/2 auto-negotiated. Recipe вынесен в [[../concepts/traefik-acme-json-to-iis-cert-import]]. + +### Phase 7 — live smoke from VDS (2026-05-23 23:35) + +7 prod hostnames → 200 OK + correct content; canonical bare→www 301s (CMS-side). 4 hostnames (`maljarka.tandemmebel.ru`, `rimiz.ru`/www, `rimiz.snolla.com`) → 502/404 — **CMS-internal tenant mismatch** (на source IIS:8089 они возвращают 200 default = тоже degraded pre-existing). Не блокирует cutover. + +### Phase 8 — DNS partial-cutover (2026-05-24) + +- **~00:00:** user flipped A `kupimknigi.spb.ru` в reg.ru. Сначала ошибочно на `89.253.255.94` (VDS Linux), потом исправлено на `80.64.31.36` (RUVDS). Authoritative `ns1.reg.ru` отдаёт правильное; public resolver-cache (8.8.8.8=6h, 1.1.1.1=24h, Yandex=2h) держат старое до TTL expiry. +- **~12:00:** `emspb.ru` + `www.emspb.ru` flipped (1.1.1.1 + Yandex + reg.ru уже отдают новое, 8.8.8.8 кешировал старое). Smoke `--resolve` + partially-cached real DNS → 200 OK + correct content. + +> **TTL=86400 — слишком много.** Lower до 300s в reg.ru для всех hostnames ДО полного DNS swap'а. + +### Phase 9 — scope narrow (2026-05-24) + +User-decision: `tandemmebel.ru` + `www.tandemmebel.ru` ОСТАЮТСЯ на windows-IIS на неопределённый срок. Cert на RUVDS уже импортирован, HTTPS binding existing — но DNS не свапаем. Source IIS `snolla` site нельзя decommission'ить пока tandemmebel на нём же (catch-all binding). Migration делится: 24 hostnames мигрируют, 2 остаются. + +## Decisions log (summary) + +- **SMB → SSH/scp pivot** (22:30) — home-ISP блокирует outbound 445, deprecate SMB-метод глобально в bootstrap-концепте. +- **Tariff 2GB / 30GB** — minimum-viable для IIS+1 site catch-all; w3wp ~330 MB cold. Под load monitor. +- **Secrets canonical store** — `pass show ruvds-iis/full-env` после ретроактивной cleanup'а .gitignore. +- **CMS-side degraded** (4 hostnames 502/404) — accept, pre-existing on source, не блокер. +- **TTL не снижен заранее** — ошибка процесса, fix recommendation сделан в pre-swap list. + +## Outstanding (post-soak) + +- DNS TTL drop до 300s в reg.ru для 22 hostnames. +- Full DNS swap остальных 22 hostnames. +- 1-неделя soak с RUVDS как live prod. +- LE renewal pipeline (recommend: `win-acme` standalone + HTTP-01 после full cutover, ~95 days margin). +- Decommission source IIS:8089 + traefik routes (но не traefik сам). +- Cleanup: temp FW rules `ssh-from-source` + `smb-from-source` + удалить `~/.ssh/ruvds-iis-migration*` keys + `C:\ProgramData\ssh\administrators_authorized_keys`. +- Source-info commit — image-pipeline SPOF осталось (imgproxy на windows-host). + +## MinIO/imgproxy caveat (carry-over) + +RUVDS IIS coupled к windows-host imgproxy через DNS `imgproxy.kzntsv.site` — SPOF home machine **сохраняется** для image-rendering. HTML rendering работает с RUVDS independent. Verified post-migration: `Test-NetConnection imgproxy.kzntsv.site -Port 443` с RUVDS = OK. См. [[../concepts/iis-cutover-to-vds-services]] для long-term resolution. + +## Cross-refs + +- Live state: [[../entities/ruvds-iis-host]] +- Source-host (pre-migration): [[../entities/windows-recovery-host]] +- Vendor research: `.tasks/windows-hosting-vendor-research.md` (🟢 closed 2026-05-22) +- Pre-req migrations: [[../concepts/mssql-on-vds]] + [[../concepts/minio-imgproxy-on-vds]] +- Bootstrap recipe (updated 2026-05-24): [[../concepts/windows-server-2025-core-bootstrap]] +- Cert-import recipe: [[../concepts/traefik-acme-json-to-iis-cert-import]] +- Backup pipeline: [[ruvds-backup-daily-kreknin-2026-05-24]] +- Driver (SPOF rationale): [[../concepts/future-resilient-architecture-goals]] +- Pre-existing degraded routes: [[../concepts/iis-migration-2026-05-19-postmortem]] + [[iis-host-migration-2026-05-19]] diff --git a/.wiki/sources/ruvds-backup-daily-kreknin-2026-05-24.md b/.wiki/sources/ruvds-backup-daily-kreknin-2026-05-24.md new file mode 100644 index 0000000..bad032e --- /dev/null +++ b/.wiki/sources/ruvds-backup-daily-kreknin-2026-05-24.md @@ -0,0 +1,81 @@ +--- +title: RUVDS daily backup → kreknin — pipeline standup 2026-05-24 +type: source +tags: [backup, ruvds, kreknin, rclone, sftp, ntfy, schedtask] +ingested: 2026-05-24 +raw_path: ../../.tasks/ruvds-backup-daily-kreknin.md +updated: 2026-05-24 +--- + +# RUVDS daily backup → kreknin + +Поднят ежедневный backup pipeline с [[../entities/ruvds-iis-host]] (`80.64.31.36`, Win Server 2025 Core) → [[../entities/kreknin-synology]] (`195.19.90.188 / kreknin.site`) в **04:30 MSK** (за 30 мин до VDS backup'а в 05:00, чтобы не пересекать uplink). После каждого прохода — ntfy push на общий topic `vds-backup` (одно phone-channel для всех backup events). Параллель [[vds-kzntsv-bootstrap-2026-05-20]] §backup, но source = Windows Core → cron нет (Task Scheduler), rsync нет (rclone), root-cron нет (SYSTEM scheduled task). + +Источник истины — `.tasks/ruvds-backup-daily-kreknin.md`. + +## Scope + +| Path on RUVDS | Reason | Size | +|---|---|---| +| `C:\sites\snolla\` | CMS site content + Web.config + media | 8.66 GB | +| `C:\Windows\System32\inetsrv\config\applicationHost.config` | IIS site/binding/apppool config | <1 MB | +| `Backup-WebConfiguration` snapshot → `%SystemRoot%\System32\inetsrv\backup\` | IIS native config snapshot | <5 MB | +| `C:\ProgramData\ssh\` | sshd_config + authorized_keys | <50 KB | +| Exported PFX из `Cert:\LocalMachine\My` | LE certs для restore без re-extract из traefik | <1 MB | + +Не бэкапятся: `C:\Windows\`, `C:\Program Files\`, IIS logs. + +## Decisions log + +- **Tool = rclone (SFTP)**. Не robocopy-over-SMB (SMB через home-ISP блокируется, см. [[iis-migration-to-ruvds-2026-05-23]] Phase 2), не rsync (нет cygwin/WSL на Core, лишний security surface), не restic (encrypted dedupe overkill пока link trusted; defer like VDS). +- **Run as SYSTEM**, не user account — full доступ к `C:\sites\` + `inetsrv\` + cert store, не требует stored-password в Task Scheduler. Pattern matches VDS root-cron decision. +- **PFX export pass = `pfximport` plaintext в run.ps1** — temporary, migrate to pass-equivalent на Windows (DPAPI или gpg4win+bash-pass) когда migration cutover'нется полностью. +- **Retention 7 daily snapshots, без hardlink dedup** — 8.66 GB × 7 = ~60 GB на kreknin (5.7T free). Per-day dirs `/volume1/NetBackup/ruvds-iis/YYYY-MM-DD/`. +- **ntfy topic `vds-backup`** — reuse общего канала, Title включает source-host чтобы phone-side отличать VDS-backup от RUVDS-backup. + +## Хронология standup'а (2026-05-24) + +- **~10:18:** rclone v1.74.2 installed на RUVDS (`C:\Program Files\rclone\rclone.exe`). +- **~10:18:** ed25519 SSH key `C:\ProgramData\backup\kreknin-key` сгенерирован, pubkey deployed в kreknin `/var/services/homes/vitya/.ssh/authorized_keys` **через VDS pivot** (source machine не имеет direct SSH к kreknin). +- **~10:19:** Deployed `rclone.conf` (SFTP remote `kreknin`, `disable_hashcheck=true`), `config.env` (ntfy creds), `run.ps1`. ACL = SYSTEM + Administrators. +- **10:19:47:** Зарегистрирован ScheduledTask `RUVDS-Backup-Daily` (daily 04:30 MSK, SYSTEM, 2h timeout). +- **10:21:13 — 11:42:57:** Initial full sync 8.66 GB snolla + 4 small components → kreknin. **~82 мин** из-за home-uplink throttling (production cron не affected — RUVDS uplink direct). +- **11:46:51:** Run #1 incremental smoke ✓ **20 sec** — все 5 components OK, retention prune OK (1 snapshot kept, ничего пока удалять), ntfy success sent. +- Scripts checked-in: `scripts/ruvds-backup-daily-kreknin/` (setup.ps1 + run.ps1 + README). + +## Bugs fixed during smoke + +- `Backup-WebConfiguration -Force` параметра нет на этом IIS — используем `Get-WebConfigurationBackup + Remove-WebConfigurationBackup` если exists + plain `Backup-WebConfiguration`. +- rclone `--log-file` указывал на тот же путь что и `Start-Transcript` → file lock. Убран `--log-file`, transcript captures всё. +- rclone NOTICE на stderr + `$ErrorActionPreference='Stop'` = PS terminating error даже c `2>$null`. Wrapper `Invoke-Rclone` temporarily switches к `ErrorActionPreference='Continue'`. +- ssh-keyscan'енный `known_hosts` не проходит rclone go-sftp library (key mismatch). Убран `known_hosts_file` из rclone.conf, key-auth достаточно. + +## Pipeline state + +- **Live**: ScheduledTask `RUVDS-Backup-Daily`, daily 04:30 MSK, SYSTEM. +- **Verified**: run #1 end-to-end (20 sec incremental, ntfy push received). +- **Retention day-8 verify**: pending — retention prune не triggered'илась (только 1 snapshot < 7). +- **Phone-side ntfy verify**: pending — user должен подтвердить что push с title `RUVDS backup OK` приходит на ntfy app (common channel с VDS backup). + +## Open follow-ups (не блокер) + +- PFX export passphrase в plaintext — migrate to DPAPI/pass-equivalent. +- Backup `C:\sites\snolla` size growth (CMS uploads через админку) — quarterly disk-usage check на kreknin. + +## Атомарный 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' +``` + +## Cross-refs + +- Source host: [[../entities/ruvds-iis-host]] +- Backup target: [[../entities/kreknin-synology]] +- Driver: open question "Backup strategy для RUVDS" из [[iis-migration-to-ruvds-2026-05-23]] — closed by этой задачей. +- Parallel pipeline: VDS Ubuntu → kreknin rsync `--link-dest` (см. [[vds-kzntsv-bootstrap-2026-05-20]] §backup). +- Notification: общий ntfy topic `vds-backup` на `ntfy.vds.kzntsv.site` (см. [[../entities/vds-kzntsv]] §стек).