resilience(roadmap): workshop pass 1 — close design-task; file top-3 impl-tasks

- close [resilience-roadmap-design] 🟢 — roadmap expanded via interactive workshop
  with user (per-service RTO/RPO matrix for 10 services, CMS backup 2-phase plan,
  IIS migration track, 4 secondary topics documented as recommendations)
- file 3 impl-tasks  ready (spawned by roadmap-design):
  - cms-stopgap-backup-daily — Phase 1, plug RPO=∞ via daily rsync to kreknin
  - mssql-minio-migration-to-vds — Phase 2 enabler, achieves RPO 1h target
  - windows-hosting-vendor-research — design-task for IIS migration off home host
- unblock [admin-infra-project-review] 🔵 (last blocker cleared)
- expand .wiki/concepts/future-resilient-architecture-goals.md with §Workshop pass 1
  (canonical) above original §Pre-workshop placeholder (historical)

Key user-decisions zafiksirovany in workshop:
- CMS RTO 4h / RPO 1h (not 1h/15min — overkill for one-person infra)
- MSSQL+MinIO migrate to VDS (not Windows-side managed hosting)
- MSSQL Always-On AG rejected — log shipping every 60min sufficient
- IIS long-term dies with snolla-on-node; transitional via managed Windows host
- Cloud off-site = Yandex Object Storage when needed (kreknin already off-site)
- Monitoring = Uptime Kuma on VDS, high-priority among not-filed

Acceptance per spec (user confirmed plan + concrete impl-tasks top-3 + doc committed) — met.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-21 16:25:04 +03:00
parent d20a9d41e4
commit fd8bb13e75
5 changed files with 361 additions and 14 deletions

View File

@@ -1,5 +1,5 @@
# Admin Task Board
_Updated: 2026-05-21 (etap-1 + etap-2 secrets pipeline closed)_
_Updated: 2026-05-21 (resilience-roadmap-design workshop pass 1 closed; 3 follow-up impl-tasks filed; review unblocked)_
<!--
Status legend:
@@ -234,12 +234,20 @@ Done — 🟢 с close-note типа `verified end-to-end: tasks+wiki visible in
---
## [resilience-roadmap-design] — Развернуть placeholder `.wiki/concepts/future-resilient-architecture-goals.md` (мигрирует из MoreThenCms в `admin-subtree-import-and-cleanup`) в полноценный fault-tolerance roadmap. Естественная отправная точка для глобальной цели пользователя: «создать отказоустойчивое решение, чтобы такие проблемы как 2026-05-18 не повторялись».
## 🟢 [resilience-roadmap-design] — Развернуть placeholder `.wiki/concepts/future-resilient-architecture-goals.md` (мигрирует из MoreThenCms в `admin-subtree-import-and-cleanup`) в полноценный fault-tolerance roadmap. Естественная отправная точка для глобальной цели пользователя: «создать отказоустойчивое решение, чтобы такие проблемы как 2026-05-18 не повторялись».
Это **design task** (не impl): продукт — обновлённая `concepts/future-resilient-architecture-goals.md` + потенциально цепочка impl-тасок-children. См. `concepts/admin-infra-project.md` §Initial admin agenda E.1.
**Status:** blocked
**Where I stopped:** (not started)
**Status:** done
**Closed:** 2026-05-21 — roadmap expanded via **workshop pass 1** (interactive session с user). Output:
- Doc `concepts/future-resilient-architecture-goals.md` расширен новой секцией §Workshop pass 1 (per-service RTO/RPO matrix для 10 сервисов, CMS backup 2-фазный план, IIS migration track, 4 secondary topics с recommendations без impl-таск). Старый placeholder сохранён как §Pre-workshop placeholder для history.
- **Top-3 impl-tasks filed:** `cms-stopgap-backup-daily` ⚪ (Фаза 1 — plug RPO=∞), `mssql-minio-migration-to-vds` ⚪ (Фаза 2 enabler — achieves RPO 1ч), `windows-hosting-vendor-research` ⚪ (design-таска для IIS-переезда).
- **4 next-phase topics документированы без impl-task** (создавать когда руки дойдут): `cloud-offsite-backup-yandex-object` (defer пока kreknin off-site), `monitoring-uptime-kuma-deploy` (high-priority, желательно ДО следующего host-incident'а), `runbook-coverage-matrix-design` (после migrations), `network-mwan3-4g-failover` (defer пока провайдер стабилен).
- **Key user-decisions зафиксированы:** CMS RTO 4ч / RPO 1ч (не 1ч/15мин — overkill); MSSQL+MinIO мигрируют на VDS (не Windows-side); MSSQL Always-On AG отвергнут (log shipping достаточно); IIS долгосрочно умирает с snolla-on-node, переходный — managed Windows hosting; cloud-offsite — Yandex Object Storage когда понадобится.
- Acceptance per spec (`user подтвердил план + concrete impl-tasks top-3 + документ committed`) — ✅ выполнено.
Unblocks `admin-infra-project-review` (была последним blocker'ом).
**Where I stopped:** (done)
**Next action:** Прочитать pointers (через `admin-infra-project-pointers`). Затем:
1. **Inputs read:** `concepts/recovery-architecture-snapshot.md` (текущее состояние request flow + SPOF list), `concepts/future-resilient-architecture-goals.md` (placeholder с rough goals), `entities/*` (что есть в стеке физически).
@@ -436,7 +444,7 @@ Done — 🟢; secret-management dyra closed.
---
## 🔵 [admin-infra-project-review] — Code-review checkpoint для брейнсторма admin-infra-project (промоушен 2026-05-21).
## [admin-infra-project-review] — Code-review checkpoint для брейнсторма admin-infra-project (промоушен 2026-05-21).
**Спецификация:** `.wiki/concepts/admin-infra-project.md` (ingested 2026-05-21).
**Pre-impl bootstrap:** `admin-infra-project-pointers` — заполнил `.wiki/CLAUDE.md` Domain conventions design-context pointer'ами. Без неё review бы читал stub.
@@ -461,15 +469,49 @@ Done — 🟢; secret-management dyra closed.
**Закрытие:** только когда все findings зафайлены ИЛИ ревьюер подтвердил «нет findings» в close-note.
**Status:** blocked
**Where I stopped:** (not started)
**Next action:** Дождаться 🟢 у всех blocker-тасок (включая `admin-infra-project-pointers` — без него pointers в `.wiki/CLAUDE.md` не залиты, и review будет читать stub). Прочитать спецификацию (см. путь в description). Для каждой импл-таски: `git show <commit>`, прогнать acceptance criteria из её next_action, сверить с design-decisions в спецификации. Findings → новые follow-up tasks через `mcp__projects-meta__tasks_create`.
**Blocker:** agenda: resilience-roadmap-design, secrets-out-of-common, secrets-manager-adopt
**Status:** ready
**Where I stopped:** (not started — all blockers cleared 2026-05-21: resilience-roadmap-design 🟢, secrets-out-of-common 🟢, secrets-manager-adopt 🟢)
**Next action:** Прочитать pointers (`.wiki/CLAUDE.md` §Domain conventions) → спецификацию (`concepts/admin-infra-project.md`). Для каждой импл-таски: `git show <commit>`, прогнать acceptance criteria из её next_action, сверить с design-decisions в спецификации. Findings → новые follow-up tasks через `mcp__projects-meta__tasks_create`. См. чек-лист в description выше.
**Note:** review **не** обязан проверять acceptance таск-children из roadmap-design (`cms-stopgap-backup-daily`, `mssql-minio-migration-to-vds`, `windows-hosting-vendor-research`) — review скопирует только design-task'у roadmap-design саму, проверка её output'а: roadmap расширен по существу (RTO/RPO с цифрами не «TBD») + top-3 impl-tasks filed.
**Branch:** n/a
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: OpeItcLoc03/workshop / 2026-05-21T10:25:43.430Z -->
---
## ⚪ [cms-stopgap-backup-daily] — Фаза 1 CMS backup. Plug текущую дыру RPO=∞ для CMS прод (sites + MSSQL + MinIO на windows-recovery-host). Ежедневный rsync на kreknin до пока MSSQL/MinIO не переедут на VDS через `mssql-minio-migration-to-vds` (тогда списываем этот pipeline).
Это **временное решение** — не строить ничего изощрённого. Cron через Windows Task Scheduler + rsync + ssh-pipe. Достигаемый RPO = 24ч (не target 1ч, но лучше чем ∞).
**Status:** ready
**Where I stopped:** (not started)
**Next action:** См. `cms-stopgap-backup-daily.md` — acceptance + key files + open questions. Order: (1) verify MinIO data dir location через `docker inspect minio`, (2) write PowerShell backup script с тремя ногами (mssql/sites/minio) + ntfy push, (3) test smoke recovery на MSSQL backup, (4) wire через Windows Task Scheduler daily 03:00 MSK, (5) document в `.wiki/concepts/cms-stopgap-backup-pipeline.md`. Spawn'd by [resilience-roadmap-design] workshop pass 1 2026-05-21.
**Branch:** n/a
---
## ⚪ [mssql-minio-migration-to-vds] — Фаза 2 CMS backup. Перенести MSSQL контейнер + MinIO с windows-recovery-host на vds-kzntsv. Achieves target RPO 1ч через интеграцию с существующим `vds-backup-rsync-kreknin` pipeline (tx log backups каждые 60 мин в существующий rsync→kreknin). Снимает SPOF с домашней машины для критических CMS-данных.
После завершения — списать `cms-stopgap-backup-daily` cron на windows-host.
**Status:** ready
**Where I stopped:** (not started)
**Next action:** См. `mssql-minio-migration-to-vds.md` — full acceptance (8 items) + risks + open questions. Major task (1-2 недели realistic). Разбить на sub-phases: (a) MSSQL container deploy на VDS + restore from backup, (b) connection string change + smoke 8 hosts, (c) MinIO migration через `mc mirror`, (d) backup pipeline integration в `/opt/stacks/backup/scripts/run.sh`. **Pre-cutover benchmark обязателен** (admin assets UI / search / catalogs) — WAN latency 10-30ms vs localhost. Spawn'd by [resilience-roadmap-design] workshop pass 1 2026-05-21.
**Branch:** n/a
---
## ⚪ [windows-hosting-vendor-research] — Design-таска (1 день). Выбрать вендора managed Windows hosting для будущего переезда IIS с windows-recovery-host (домашней машины). Output: 1-pager с recommended vendor + cost estimate + migration recipe outline.
Это **переходный** трек до завершения snolla node-rewrite'а (после которого IIS не нужен вообще). Не файлим impl-таску миграции до этой research'и — vendor выбираем сначала.
**Status:** ready
**Where I stopped:** (not started)
**Next action:** См. `windows-hosting-vendor-research.md` — constraints + candidates + acceptance. Steps: (1) research 4 candidates (Rusonyx / Selectel / FirstVDS / Beget), (2) fill comparison table по criteria (RDP / .NET 4.8 / IIS 10 / public IP / cost / SLA / reviews), (3) write top-1 recommendation с trade-off justification, (4) cost estimate monthly + one-time, (5) document в `.wiki/concepts/windows-hosting-vendor-comparison-2026.md`. **Не file** follow-up impl-task `iis-migration-to-managed-windows-hosting` — пусть future-agent file'нёт когда vendor выбран. Spawn'd by [resilience-roadmap-design] workshop pass 1 2026-05-21.
**Branch:** n/a
---
# Imported from MoreThenCms — 2026-05-21 subtree-split migration
Полное содержимое `.tasks/STATUS.md` из MoreThenCms на момент 2026-05-21, **CMS-domain блоки исключены** (остались в MoreThenCms): `cms-admin-assets-root-folders-seed`, `cms-port-leak-fix`, `traefik-maljarka-502-bug`, `cms-maljarka-https-mode-bug-fix`. История per-file сохранена через subtree-split + temp-prefix merge.

View File

@@ -0,0 +1,41 @@
# cms-stopgap-backup-daily
## Goal
Plug текущую дыру **RPO=∞** для CMS прод. CMS sites + MSSQL + MinIO на [[windows-recovery-host]] не имеют бэкапов нового состояния с 2026-05-19 (последний Hyper Backup был 2026-05-09 на мёртвой синке). Если windows-host сгорит сейчас — теряем всё.
Stop-gap: ежедневный rsync на [[kreknin-synology]] (RPO факт = 24ч) до пока MSSQL/MinIO не переедут на VDS через [[mssql-minio-migration-to-vds]], где backup'ы будут через существующий `vds-backup-rsync-kreknin` pipeline (RPO 1ч target).
**Это временное решение** — pipeline списывается после Фазы 2. Поэтому **не строить ничего изощрённого**: cron + rsync + ssh-pipe, паттерн уже работает на VDS.
## Key files
- `C:\sites\*` — IIS site directories (snolla, stostayer, stostayer.old)
- MSSQL container на windows-host, port 1433 — backup через `docker exec mssql /opt/mssql-tools/bin/sqlcmd ... BACKUP DATABASE ... TO DISK = '/var/opt/mssql/backup/...'`, потом скопировать `.bak` файлы из volume `mssql_mssql_data` на host
- MinIO data dir — `C:\Users\vitya\projects\docker\diskstation\minio\data\` (verify on impl)
- Target: `kreknin.site:/volume1/NetBackup/windows-cms/<DATE>/` (создать), retention 7 daily snapshots
- SSH key: `~/.ssh/id_ed25519_kreknin` (vitya@195.19.90.188), пароль см. [[../entities/kreknin-synology]]
- Notify: ntfy `vds-ops` topic (`https://ntfy.vds.kzntsv.site/vds-ops`, auth vitya/Pryakhin9, см. [[../entities/vds-kzntsv]])
## Acceptance
1. Daily ~03:00 MSK cron (Windows Task Scheduler) на windows-host выполняет:
- MSSQL FULL backup всех 5 prod DBs (MoreThenCms, Stayer*, stostayer, TireService) → `D:\backup\mssql\<DATE>\`
- rsync `D:\backup\mssql\``kreknin:/volume1/NetBackup/windows-cms/<DATE>/mssql/`
- rsync `C:\sites\``kreknin:/volume1/NetBackup/windows-cms/<DATE>/sites/`
- rsync MinIO data dir → `kreknin:/volume1/NetBackup/windows-cms/<DATE>/minio/`
2. ntfy push на `vds-ops` topic с status (success/failure + total size + duration)
3. Retention: 7 daily snapshots на kreknin (старше — auto-delete через script или kreknin-side cron)
4. **Smoke recovery test:** на отдельной машине / VM загрузить MSSQL backup в чистый MSSQL container, проверить что хотя бы одна DB readable (`SELECT TOP 1 ... FROM Articles` или эквивалент)
5. Documented in `.wiki/concepts/cms-stopgap-backup-pipeline.md` (создать) с atomic revert recipe
## Decisions log
- 2026-05-21: создана как **Фаза 1** из roadmap-workshop'а (см. [[../.wiki/concepts/future-resilient-architecture-goals]] §"CMS backup pipeline — 2-фазный план"). User-decision: не строить proper RPO 1ч pipeline на windows-host т.к. MSSQL/MinIO мигрируют на VDS в обозримом (2-4 недели). Этот pipeline = bridge, не target-state.
## Open questions
- [ ] Точное location MinIO data dir на windows-host — узнать на ходу через `docker inspect minio | jq '.Mounts'`
- [ ] Windows Task Scheduler vs WSL cron для расписания — TBD на impl (Task Scheduler нативнее, WSL даёт привычные bash-скрипты)
- [ ] Encryption бэкапов at-rest перед отправкой на kreknin — defer (kreknin наш host под нашим контролем)
- [ ] MSSQL backup — full ежедневно или differential? Full ~~достаточно для RPO 24ч stop-gap; tx-log backups оставляем на Фазу 2 для RPO 1ч
## Notes
Паттерн `vds-backup-rsync-kreknin` ([[../.tasks/vds-backup-rsync-kreknin]]) — reference implementation на VDS-стороне. Адаптировать на Windows: PowerShell вместо bash, rsync.exe (через Git Bash или Cygwin), SSH-ключ Windows path.
Atomic revert: `Unregister-ScheduledTask -TaskName "cms-stopgap-backup" -Confirm:$false; Remove-Item D:\backup\mssql\* -Recurse`. На kreknin: backup snapshots оставить как archive (read-only после revert).

View File

@@ -0,0 +1,62 @@
# mssql-minio-migration-to-vds
## Goal
Перенести MSSQL контейнер + MinIO с [[../entities/windows-recovery-host]] на [[../entities/vds-kzntsv]] чтобы:
1. **Снять SPOF с windows-recovery-host** (домашняя машина) для критических CMS-данных
2. **Achieve target RPO 1ч** через подключение к существующему `vds-backup-rsync-kreknin` pipeline (tx log backups каждые 60 мин в существующий rsync→kreknin)
3. **Унифицировать DB park** — MSSQL рядом с pg/maria/mongo/redis в `/opt/stacks/databases/`
4. **Подготовить ground** для будущего IIS migration на managed Windows hosting ([[windows-hosting-vendor-research]] → impl-таска позже)
Это **Фаза 2** roadmap'а CMS backup'ов. После завершения — списать [[cms-stopgap-backup-daily]] pipeline.
## Key files / refs
- **Source MSSQL:** docker container на windows-host, image `mcr.microsoft.com/mssql/server:2019-latest`, volume `mssql_mssql_data`, 5 production DBs (MoreThenCms, Stayer*, stostayer, TireService) — см. [[../.wiki/concepts/recovery-architecture-snapshot]] §"Запущенные docker контейнеры"
- **Source MinIO:** docker container на windows-host, image `minio/minio:RELEASE.2020-07-13T18-09-56Z`, volume bind `./data`
- **Target MSSQL:** `/opt/stacks/databases/mssql/{data,certs,docker-compose.yml}` на VDS — паттерн как у existing DBs, см. [[../.wiki/entities/vds-kzntsv]]
- **Target MinIO:** `/opt/stacks/storage/minio/` (новый stack на VDS)
- **CMS connection strings (изменить):**
- MSSQL: `Data Source=localhost,1433``Data Source=mssql.vds.kzntsv.site,1433` (через traefik raw-TCP passthrough)
- MinIO: endpoint `localhost:9000``minio.vds.kzntsv.site:9000`
- **Existing backup pipeline для расширения:** `/opt/stacks/backup/scripts/run.sh` на VDS (см. [[../.tasks/vds-backup-rsync-kreknin]] — 🟢 done)
- **TLS pattern:** self-signed certs через traefik raw-TCP passthrough, см. [[../.wiki/concepts/db-tls-self-signed-via-traefik-raw-tcp]] + [[../.wiki/concepts/traefik-tcp-passthrough-vs-starttls]]
## Acceptance
1. **MSSQL container на VDS** запущен, 5 prod DBs восстановлены (cold cutover: stop CMS app pool → backup MSSQL host-side → restore on VDS → repoint connection strings → start CMS app pool)
2. **MinIO на VDS** запущен, content мигрирован (`mc mirror` от source к target)
3. **CMS connection strings updated** в web.config (или эквиваленте), sites функциональны (smoke test 8 hosts: 200 OK + asset loading + admin/assets/getList — это известный hot-path)
4. **Pre-cutover benchmark выполнен** — admin assets UI / search / catalog response times измерены до и после миграции, **latency degradation <2x** (target). Если worse — discussed с user перед commit'ом cutover (возможно retreat или оптимизация query patterns)
5. **Backup pipeline на VDS расширен:** добавлены в `run.sh`:
- `mssql_dump_full` ежедневно (как pg_dumpall pattern)
- `mssql_tx_log_backup` ежечасно (новая нога — `BACKUP LOG` через `docker exec mssql sqlcmd ...`)
- `minio_mirror` ежедневно (`mc mirror` либо rsync data dir)
6. **ntfy push verified** для расширенного pipeline (включает MSSQL+MinIO size/duration)
7. **`cms-stopgap-backup-daily` cron на windows-host отключён** после первого успешного VDS-pipeline run (atomic swap, не parallel-running, чтобы не оставлять confusing-state двух pipelines)
8. **Documented** в [[../.wiki/concepts/mssql-minio-on-vds]] (создать) с:
- architecture diagram (IIS → traefik VDS → MSSQL/MinIO containers)
- rollback recipe (если cutover failed — vernut' connection strings + reactivate stop-gap pipeline)
- migration runbook (что делал, в каком порядке)
## Decisions log
- 2026-05-21: создана из roadmap-workshop'а ([[../.wiki/concepts/future-resilient-architecture-goals]] §Фаза 2). User-confirmed: MSSQL+MinIO мигрируют на VDS (vs alternative — оставить на managed Windows host рядом с IIS). Reasons:
- DB park уже на VDS, unified backup operation
- Linux containers стабильнее и дешевле в обслуживании чем Windows-side MSSQL
- VDS уже работает, не плодим хосты
- Подготавливает ground для IIS-migration (после неё IIS host сможет быть thin — только web layer)
## Open questions
- [ ] **MSSQL Express vs Developer vs Standard на Linux container** — TBD по licensing. Production size MoreThenCms — проверить, помещается ли в Express limits (10GB per DB, 1410MB RAM). Если нет — Developer (бесплатно для non-prod, формально не для прод) или Standard ($$$$). Альтернатива — migration MSSQL → PostgreSQL (упомянуто в roadmap как long-term option) — отдельный major project.
- [ ] **MinIO migration approach**`mc mirror` overnight (zero-downtime если кратко) или maintenance window (cleaner)?
- [ ] **Cutover timing** — нужен ли downtime window клиентам, или можно zero-downtime через MSSQL log shipping (source → target replay, потом final switch)?
- [ ] **CMS connection-string change** — где живёт config (web.config? отдельный appsettings? hardcoded в DLL?). Если hardcoded — нужен DLL rebuild который требует build env, отложен в [[../.wiki/concepts/cms-admin-assets-root-folder-seed]] §"Долгосрочный TODO"
- [ ] **Hermes service на windows-host?** (упомянут как defer в [[../.wiki/entities/vds-kzntsv]] Open issues) — проверить не зависит ли от MSSQL/MinIO, если да — мигрируется заодно или ломается
## Risks
- **WAN latency IIS→MSSQL:** теперь 10-30ms vs localhost. Большинство CMS-операций batchey, не latency-sensitive. **Pre-cutover benchmark обязателен** для hot-paths (admin assets UI / search / каталоги) — flag если round-trip-heavy. См. acceptance item 4.
- **MSSQL Linux compat:** некоторые edge-case T-SQL features differ (CLR, FileStream, full-text search). Smoke test обязателен — `EXEC sp_helpdb` + проверить что нет CLR assemblies / FileStream filegroups в prod DBs.
- **TLS overhead:** rawTCP through traefik adds minor latency vs direct connection. Negligible (<1ms) но проверить.
- **Cutover rollback:** если CMS не работает после repoint — quick revert connection strings возможен **только** если MSSQL на windows-host оставлен running parallel ~24-48ч после cutover. План: stop receiving writes на windows-MSSQL (read-only), но container running, для emergency rollback. Через 48ч uptime — stop windows-MSSQL container, через неделю — `docker rm + docker volume rm`.
## Notes
Эта таска — major (1-2 недели работы realistic). Можно разбить на sub-phases при impl: (a) MSSQL container deploy + restore from backup, (b) connection string change + smoke, (c) MinIO migration, (d) backup pipeline integration. Каждая sub-phase = свой commit с atomic revert recipe.
Atomic revert (full): revert CMS web.config → windows-host MSSQL/MinIO; восстановить cms-stopgap-backup-daily cron; на VDS — `docker compose down -v` для mssql + minio stacks; удалить новые ноги из `run.sh`.

View File

@@ -0,0 +1,54 @@
# windows-hosting-vendor-research
## Goal
**Design-таска (1 день)**. Выбрать вендора managed Windows hosting для будущего переезда IIS с [[../entities/windows-recovery-host]] (домашней машины). Цель — конкретный recommendation: **vendor + tariff + migration approach + cost estimate**.
Это **переходный** трек до завершения snolla node-rewrite'а (после которого IIS не нужен вообще, всё в docker/VDS). Не файлим impl-таску миграции до этой research'и — vendor выбираем сначала. Output этой таски — pre-requisite для будущей impl-таски `iis-migration-to-managed-windows-hosting` (большая, не сейчас).
## Key constraints для оценки
- **RDP-доступ** обязателен (IIS configs руками удобнее, web-deploy не масштабируется на 8+ sites)
- **.NET Framework 4.8 native** (snolla CMS на 4.8.1, **не** .NET Core/.NET 6+)
- **IIS 10** или совместимый (URL Rewrite 2.1 нужен — см. [[../.wiki/concepts/cms-server-port-leak-fix]])
- **HTTPS + custom certs / LE** — currently traefik 4443 → IIS 8089; на managed может быть vendor-managed cert или своя LE setup
- **SSH / SFTP / WinRM для deploys** (для sites contents — IIS site dirs ~100MB-1GB каждая)
- **External MSSQL/MinIO connection** обязателен (после [[mssql-minio-migration-to-vds]] они на [[../entities/vds-kzntsv]]) — **не нужно** DB на этом hosting
- **Public IP** или alternative (Cloudflare Tunnel?) — куда DNS клиентских доменов будет указывать
- **Budget reference:** current Rusonyx VDS 160 NVMe ~2000₽/мес; managed Windows обычно 2-3x = 4000-6000₽/мес ожидаемо
## Candidates для investigation
- **Rusonyx** (у тебя уже там VDS-аккаунт + опыт онбординга — см. [[../.wiki/concepts/rusonyx-vps-onboarding-quirks]]) — есть Windows VPS-планы
- **Selectel** — managed cloud, есть Windows VPS dedicated, хорошие reviews
- **FirstVDS** — Windows VPS традиционно, дешевле Selectel
- **Beget** — Windows hosting, обычно shared (проверить про CMS-deploy access — нужен ли VPS-уровень)
- **JustHosting / IHC** — может быть relevant как backup-option
## Acceptance
1. **Comparison table:** vendor × columns:
- RDP / SSH / WinRM
- .NET Framework version (native install? сами ставим? supports 4.8?)
- IIS version + URL Rewrite доступность
- Public IP (включён? extra?)
- Cost monthly (Windows VPS tariff + Windows license если BYOL)
- One-time setup cost
- Migration friction (есть ли import tools? чистый IIS deploy?)
- SLA (uptime guarantee, ticket response time)
- User reviews / community feedback
2. **Top-1 recommendation** с обоснованием trade-off'а (cheap-and-simple vs feature-rich). Не меню — одна рекомендация.
3. **Migration approach outline:** backup IIS sites + configs → deploy on target → DNS swap → cutover plan. Один level deep (не runbook полный, его пишет уже impl-таска).
4. **Cost estimate:** monthly + one-time setup для recommended vendor.
5. **Documented in** `.wiki/concepts/windows-hosting-vendor-comparison-2026.md` (создать) — markdown с table + recommendation + sources (links to vendor pages, дата сверки).
6. **Follow-up impl-task** `iis-migration-to-managed-windows-hosting` file'нута как ⚪ ready **после** research (не самим этим таском — пусть future-agent file'нёт когда vendor выбран и user готов начать миграцию).
## Decisions log
- 2026-05-21: создана из roadmap-workshop'а ([[../.wiki/concepts/future-resilient-architecture-goals]] §"IIS migration track"). User-stated long-term direction: snolla на node, после чего IIS не нужен вообще. Pre-this: managed Windows host = переходный, чтобы убрать SPOF домашней машины. **Не оптимизируем под "идеальный навсегда"** — vendor выбираем чтобы comfortably прожить 6-18 мес. Поэтому cost > feature-completeness в trade-off.
## Open questions
- [ ] **Дата ожидаемого готового snolla-on-node** — влияет на whether-to-bother миграцией. Если node-build готов через 3 мес → managed hosting вообще не нужен, stay on windows-recovery-host as-is + accept SPOF risk; если через 12+ мес → migration оправдана. User input needed.
- [ ] **Будет ли куплен Windows Server license отдельно** (если vendor требует BYOL — Bring Your Own License) или vendor-included? Добавляет cost.
- [ ] **DDoS protection требуется?** На текущем setup нет (через бытовой провайдер); на public managed Windows тоже обычно нет default, доп-опция. Defer пока не было атаки.
- [ ] **Multi-site IIS vs single-site:** 8 hosts на одном IIS instance vs split по бOльшему количеству VPS. Single-site проще, multi-site = sub-SPOF разбит, но 2-3x cost. Default рекомендация — single-site если cost важен.
## Notes
**Anti-pattern для избегания:** не выбирать первого попавшегося vendor без сравнения. RU Windows-hosting рынок небольшой, но цены и качество разнятся 2-5x. Read reviews on vds.menu, otzyvy.pro перед commitment.
**После выбора:** трехмесячный pilot с одним low-traffic site (например `kupimknigi.spb.ru` — самый низкий трафик per [[../.wiki/concepts/recovery-architecture-snapshot]]) перед миграцией всех 8. Снижает risk catastrophic migration failure.

View File

@@ -1,16 +1,164 @@
---
title: Future Resilient Architecture — цели на потом
title: Future Resilient Architecture — roadmap
type: concept
tags: [planning, architecture, resilience, roadmap, todo]
tags: [planning, architecture, resilience, roadmap]
sources: [../sources/nas-recovery-session-2026-05-18.md]
updated: 2026-05-19
updated: 2026-05-21
---
# Future Resilient Architecture
Placeholder для глобальной задачи "выстроить отказоустойчивую архитектуру" — обсуждается **после** того как recovery полностью устаканится.
Roadmap "выстроить отказоустойчивую архитектуру чтобы инциденты типа 2026-05-18 не повторялись". Документ **живой** — переоценивается после каждого incident'а и major-migration'а.
Эта страница — **черновик целей**, не план. По ходу обсуждения распилится на специфичные концепты + ADR (architectural decision records).
Структура:
- **§Workshop pass 1 (2026-05-21)** — текущий зафиксированный план, decisions per service. Это **canonical** часть документа.
- **§Pre-workshop placeholder (2026-05-19)** — изначальные наброски без user-confirmation, оставлены для history. Не source of truth.
## Workshop pass 1 — 2026-05-21
Roadmap expanded from placeholder to concrete decisions + impl-tasks. Workshop session с user (vitya) 2026-05-21. Каждое decision ниже = user-confirmed, не unilateral recommendation. Trace разговора зафиксирован в `[resilience-roadmap-design]` close-note (см. `.tasks/STATUS.md`).
### Per-service RTO/RPO matrix
Globальные RTO/RPO разнесены **per service** — cost-of-downtime у разных сервисов разный. Числа = target, не факт. Откалибруются после first incident в новой архитектуре.
| Сервис | RTO (max downtime) | RPO (max data loss) | Rationale |
|---|---|---|---|
| **CMS прод-сайты** (snolla/labtools/pilorama98/tandemmebel/emspb/kupimknigi/maljarka — 8 hosts) | **4 ч** | **1 ч** | клиентский трафик = деньги; больше 4ч → звонки клиентов |
| **CMS DB (MSSQL)** | **4 ч** | **1 ч** | orders + контент; час правок переживёшь, день — нет |
| **CMS content** (IIS files `C:\sites\*` + MinIO) | **4 ч** | **24 ч** | картинки/asset'ы меняются редко |
| **OpenWRT router** | **1 ч** | n/a | сетевой SPOF — без него весь public IP мёртв, tied к CMS |
| **Traefik** (на windows-host) | **4 ч** | n/a | живёт на том же host'е что CMS, RTO одинаковый |
| **Gitea** | **8 ч** | **24 ч** | один пользователь, полдня без push переживёшь |
| **Verdaccio** | **8 ч** | **24 ч** | без деплоев фронтов полдня — ок |
| **Registry** | **24 ч** | **n/a** (rebuild) | "новых наделаю" decision при VDS bootstrap, см. [[../sources/vds-kzntsv-bootstrap-2026-05-20]] §3.3 |
| **Shared DB-park** (PG/Maria/Mongo/Redis на VDS) | **8 ч** | **24 ч** | dev/staging, не прод-трафик |
| **ntfy** | **4 ч** | n/a | алерт-канал; без него слепой но не сломанный |
**Decisions зафиксированы (что отвергнуто):**
- **99.99% uptime / continuous replication / hot-standby для CMS** — отвергнуто как непропорционально дорогое для one-person infra.
- **MSSQL Always-On AG** — отвергнуто (требует Enterprise license), log shipping каждые 60 мин достаточно для RPO 1ч.
- **MSSQL → PostgreSQL миграция** — оставлено как long-term option (упомянуто в §Pre-workshop placeholder), не приоритет — отдельный major project, требует CMS-side rewrite.
**Калибровочные факты:**
- 2026-05-18 incident: RTO факт = 15 ч, RPO факт = 9 дней (Hyper Backup от 2026-05-09).
- Target 4ч / 1ч для CMS = **огромный шаг** от текущей baseline.
- Прогресс 2026-05-20: VDS поднят → infra (gitea/verdaccio/registry/DB-park) уже decoupled с windows-host SPOF. CMS — пока нет.
### CMS backup pipeline — 2-фазный план
**Текущий статус (2026-05-21):** CMS прод (sites + MSSQL + MinIO) на [[../entities/windows-recovery-host]] **не имеет ни одного бэкапа нового состояния** — последний Hyper Backup 2026-05-09 был с мёртвой синки. RPO факт = ∞ (если host сгорит сейчас — теряем всё).
**Фаза 1 — stop-gap (1-2 дня работы, на этой неделе):**
Impl-task: [[../../.tasks/cms-stopgap-backup-daily]].
- MSSQL: ежедневный `BACKUP DATABASE FULL` → локальный `D:\backup\` → ночной rsync на [[../entities/kreknin-synology]]
- IIS files (`C:\sites\*`): ежедневный rsync → kreknin
- MinIO data dir: ежедневный rsync → kreknin
- Cron через Windows Task Scheduler + SSH-pipe (паттерн как у [[../../.tasks/vds-backup-rsync-kreknin]])
- Достигаемый RPO = 24ч (плохо vs target 1ч, но **лучше чем ∞** и достаточно как мост до Фазы 2)
- **Не строить ничего изощрённого** — это патч на 2-4 недели до миграции MSSQL/MinIO.
**Фаза 2 — proper RPO 1ч после миграции на VDS (1-2 недели работы):**
Impl-task: [[../../.tasks/mssql-minio-migration-to-vds]].
- MSSQL container на [[../entities/vds-kzntsv]] как часть `/opt/stacks/databases/` рядом с pg/maria/mongo/redis
- MinIO контейнер на VDS отдельным stack'ом `/opt/stacks/storage/`
- CMS app в IIS на windows-host ходит через TCP на `mssql.vds.kzntsv.site:1433` / `minio.vds.kzntsv.site:9000` — connection strings меняются, остальное прозрачно (паттерн уже работает для DBs через traefik raw-TCP, см. [[traefik-tcp-passthrough-vs-starttls]] + [[db-tls-self-signed-via-traefik-raw-tcp]])
- Backup pipeline = расширение **существующего** `/opt/stacks/backup/scripts/run.sh` на VDS: добавить `sqlcmd BACKUP LOG` ежечасно + ежедневный full в существующий rsync-pipeline к kreknin
- **Достижение RPO 1ч** = tx log backup каждые 60 мин (или 15 — tunable)
- **Risk:** сетевая латентность IIS→MSSQL теперь WAN (10-30ms vs localhost). Большинство CMS-операций batchey, не latency-sensitive — но **pre-cutover benchmark обязателен** для hot-paths (admin assets UI / search / каталоги).
**Stop-gap pipeline списывается после Фазы 2** — backup data будет идти через VDS-pipeline.
### IIS migration track
**Текущий статус:** IIS на [[../entities/windows-recovery-host]] — temp-solution recovery 2026-05-19 (изначально recovery-host был VM, переехали на native IIS host для стабильности — см. [[../sources/iis-host-migration-2026-05-19]]). Домашняя машина = SPOF + физический риск (пожар / залив / кража / power-loss).
**Target end-state (долгосрочный):** snolla CMS переписан на node → IIS не нужен вообще, всё в docker на VDS. Это **dev-работа**, вне scope этой roadmap'ы. Прогресс отслеживается отдельно user'ом.
**Переходный план:** managed Windows hosting (RU-провайдер), куда переедет IIS до завершения node-rewrite'а.
Impl-task (research-only): [[../../.tasks/windows-hosting-vendor-research]] (1 день).
- Output: 1-pager с recommended vendor + plan / cost estimate / migration recipe outline.
- Comparison candidates: Rusonyx (у тебя уже там VDS), Selectel, FirstVDS, Beget.
- Critical constraints: RDP-доступ, .NET Framework 4.8 native, IIS 10, external MSSQL/MinIO connectivity (на VDS после Фазы 2).
После research → файлим follow-up impl-task `iis-migration-to-managed-windows-hosting` (большая, mes+ работы) — но **не сейчас**, пока на windows-host'е работает + stop-gap backup'ы плюсуют RPO 24ч safety net.
### Cloud off-site backup target (3-й уровень 3-2-1)
**Recommendation (не файлится impl-таской пока):** **Yandex Object Storage** (~1.6₽/GB/мес Standard tier, S3-compatible — работает с restic / rclone / duplicati). РФ-юрисдикция → нет cross-border сюрпризов.
**Альтернатива rejected:** Backblaze B2 — дешевле (~$5/TB/мес) но cross-border payment friction + sanctions risk.
**Defer impl:** [[../entities/kreknin-synology]] уже географически off-site (другая локация). Cloud добавится **поверх** kreknin'а, когда захочется паранойи "kreknin тоже может сгореть" или после первого incident'а где kreknin не помог. До этого: kreknin = "1 off-site" из 3-2-1.
**Future impl-task:** `cloud-offsite-backup-yandex-object` — ⚪ ready (не file'нута), создать когда руки дойдут.
### Network resilience
**Recommendation (не файлится impl-таской):** **defer multi-WAN.** Провайдер исторически стабилен. OpenWRT mwan3 + 4G/LTE USB-modem = страховка ~3-5к₽ единоразово + симка ~200₽/мес, но low-probability event. Возвращаемся после первого incident'а с потерей провайдера.
**Cloudflare Tunnel** (free tier, IP-абстракция, no DDoS-protection): отдельный вопрос для workshop pass 2 — добавляет vendor dependency на edge, trade-off обсуждается отдельно когда станет интересно (особенно после миграции MSSQL/MinIO на VDS — тогда windows-host станет thin web-layer, легче абстрагировать его IP).
**Future impl-tasks (не file'нуты):**
- `network-mwan3-4g-failover` — ⚪ ready, file когда подгорит провайдером
- `cloudflare-tunnel-edge-abstraction` — workshop pass 2 решение
### Monitoring stack
**Recommendation (не файлится impl-таской, но приоритет high среди not-filed):** **Uptime Kuma на VDS.** Docker, ставится за 30 мин на `/opt/stacks/monitoring/`, push-нотификации через ntfy (уже работает `vds-ops` topic — см. [[../../.tasks/vds-ntfy-push]]). Покрывает HTTP/TCP/ping/DNS healthchecks + cert-expiry warnings.
**Anti-recommend:** Prometheus + Grafana — overkill для one-person infra, full-stack observability нужен когда 20+ сервисов. Внешний (Pingdom/UptimeRobot) — платный, лучше self-host раз VDS уже есть.
**Initial monitor set (для impl):**
- HTTP 200 OK на 8 CMS hosts (snolla.com, labtools.ru/pro, pilorama98.ru, tandemmebel.ru, emspb.ru, kupimknigi.spb.ru, maljarka.tandemmebel.ru)
- HTTP 200 на инфра-hosts: git.kzntsv.site, verdaccio.kzntsv.site, registry.kzntsv.site, ntfy.vds.kzntsv.site
- TCP на DB-park ports: postgres/mariadb/mongo/redis (5432/3306/27017/6379)
- Ping на windows-recovery-host (94.19.247.14) и VDS (89.253.255.94)
- Cert-expiry warnings (Uptime Kuma встроено)
**Желательно установить ДО** того как windows-host опять упадёт — чтобы инцидент был "ntfy push 2 мин назад", а не "мне Серёга позвонил".
**Future impl-task (не file'нута):** `monitoring-uptime-kuma-deploy` — ⚪ ready, **приоритет high** среди not-filed.
### Runbook coverage matrix
**Текущее покрытие** (post-mortem chronologies с step-by-step recipe):
- [[../sources/nas-recovery-session-2026-05-18]] — NAS-loss recovery
- [[../sources/iis-host-migration-2026-05-19]] — IIS migration recipe
- [[../sources/vds-kzntsv-bootstrap-2026-05-20]] — VDS bootstrap
**Missing runbooks:**
- VDS-loss recovery (если Rusonyx упал / аккаунт потерян)
- Cert-expiry (acme.json renewal failure, manual DNS-01 через REGRU)
- DB-corruption restore (per-service: MSSQL, postgres, mariadb, mongo)
- Ransomware-recovery (encrypted backups restore protocol)
- OpenWRT-loss (новый роутер, restore configs)
**Defer:** runbook'и для **текущей** переходной архитектуры устареют через 2 мес (после `mssql-minio-migration-to-vds` + `iis-migration-to-managed-windows-hosting`). Пишем после стабилизации архитектуры — иначе тратим время на документацию которая не доживёт до использования.
**Future impl-task (не file'нута):** `runbook-coverage-matrix-design` — ⚪ ready, file **после** migrations завершены.
### Top-3 impl-tasks filed (2026-05-21)
1. **[[../../.tasks/cms-stopgap-backup-daily]]** ⚪ — Фаза 1, plug RPO=∞ за 1-2 дня.
2. **[[../../.tasks/mssql-minio-migration-to-vds]]** ⚪ — Фаза 2 enabler, achieves RPO 1ч target.
3. **[[../../.tasks/windows-hosting-vendor-research]]** ⚪ — design-task для IIS-переезда (1 день research, output = recommendation + cost).
### Workshop pass 2 — open agenda
Что **не** обсуждалось в этом проходе (для следующего workshop'а когда руки дойдут):
- Cloudflare Tunnel — edge abstraction trade-off
- Off-site cloud target — конкретный configure (decision уже сделано, ждёт kreknin-incident'а или паранойи)
- Hermes service — defer, ждёт уточнения user
- snolla node-rewrite progress — dev-track, периодически переоценивать impact на этот roadmap (если близко к completion → managed Windows hosting миграция отменяется)
- DR drill cadence — failover тесты раз в квартал (упомянуто в §Pre-workshop placeholder, не закрыто)
---
## Pre-workshop placeholder (2026-05-19) — historical draft
> **Note:** ниже — изначальные наброски до workshop pass 1. Не source of truth, оставлены для history. Concrete decisions — в §Workshop pass 1 выше.
## Что сейчас не так