Files
admin/.wiki/concepts/recovery-architecture-snapshot.md
vitya e2338b6fdd wiki(lint): close all 10 lint issues + delete windows-host backup task
- deleted .tasks/windows-host-fallback-backup-daily.md (MSSQL removed on decommission 2026-06-08)
- recovery-architecture-snapshot.md: marked ИСТОРИЧЕСКАЯ ЗАПИСЬ; removed 3 broken [[wiki-links]] (cms-server-port-leak-fix, cms-admin-assets-root-folder-seed, webconfig-password-xml-escape)
- snolla-recovery-vm.md: marked УДАЛЕНА 2026-06-08
- ruvds-iis-host.md: struck 2 resolved risks (imgproxy SPOF, LE renewal); cross-ref winacme
- future-resilient-architecture-goals.md: dead task link → plain text
- mssql-on-vds.md: frontmatter fix; Backup TODO section replaced with implemented block (Express COPY_ONLY, sqlcmd, bind-mount pattern)
- vds-kzntsv.md: added MSSQL row to software stack table
- log.md: update entries for lint + mssql backup implementation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 08:18:19 +03:00

13 KiB
Raw Blame History

title, type, tags, sources, updated
title type tags sources updated
Recovery architecture — текущая инфраструктура (2026-05-19, attempt 2) concept
architecture
current-state
snapshot
recovery
historical
../sources/nas-recovery-session-2026-05-18.md
../sources/iis-host-migration-2026-05-19.md
2026-05-19

ИСТОРИЧЕСКАЯ ЗАПИСЬ — архитектура на 2026-05-19. С тех пор всё изменилось: CMS переехала на ../entities/ruvds-iis-host (2026-05-24), MSSQL/MinIO на ../entities/vds-kzntsv (2026-05-22), imgproxy на ../entities/books-vds (2026-06-08), ../entities/windows-recovery-host декоммишнен (2026-06-08). Содержимое ниже — только для понимания recovery-сессии 2026-05-19. Содержит broken links на несуществующие страницы (cms-server-port-leak-fix, cms-admin-assets-root-folder-seed, webconfig-password-xml-escape).

Recovery Architecture Snapshot

Снимок production-инфраструктуры на конец второй (успешной) попытки миграции 2026-05-19. 14 cms hostnames теперь идут через native IIS на windows-recovery-host напрямую. VM snolla-recoveryparallel-fallback, running но больше не на prod-пути (24h+ soak, потом savestate). 2 stayer routes окончательно disabled через traefik (host IIS sites живут для прямого доступа).

История: attempt 1 в этот же день сломал prod, был revert; recipe — в iis-migration-2026-05-19-postmortem. Attempt 2 выполнен по recipe — см. iis-host-migration-2026-05-19 Phase 10.

Это рабочее, но всё ещё временное состояние — single-point-of-failure на бытовом железе. Замечания по улучшению — future-resilient-architecture-goals.

Цепочка запроса от клиента до CMS (host-IIS chain, attempt 2)

Клиент (browser)
  → DNS resolve (REGRU): *.snolla.com (включая on.snolla.com — default subdomain),
       labtools.ru/pro, pilorama98.ru, tandemmebel.ru, emspb.ru, kupimknigi.spb.ru,
       maljarka.tandemmebel.ru, sestech.ru, ics-artmaterials.com, rimiz.ru (404 CMS-side)
       → 94.19.247.14 (public IP, статический у провайдера)
  → router OpenWRT (192.168.1.1) [[openwrt-router]]
       → NAT 443 → 192.168.1.143:4443
       → NAT 80 → 192.168.1.143:8000
  → Windows-PC (192.168.1.143) [[windows-recovery-host]]
       → traefik 2.6.6 на 4443/8000
            → TLS termination, certResolver=letsEncrypt из acme.json
            → match по Host header (file-provider rules в data/custom/*.yml)
            → backend = http://host.docker.internal:8089/
       → host:8089 → IIS site `snolla` (binding *:8089)
  → IIS native на хосте
       → site `snolla`, .NET Framework 4.8.1, AppPoolIdentity
       → C:\sites\snolla\, sitePath patched, conn → localhost
       → ASP.NET CMS code (.NET Framework 4.8)
       → Connection strings:
            → MSSQL: Data Source=localhost,1433 (host:1433 = MSSQL container)
            → MinIO/storage: вопрос снят пользователем
            → Elasticsearch: не используется CMS
  → MSSQL container на host:1433
       → 5 production DB (MoreThenCms, Stayer*, stostayer, TireService)
  ← HTTP response back through chain

VM snolla-recovery: running parallel, no traffic (24h+ soak fallback). NAT port forwards :18080/:18180/:18181/:18189 холостые. Будет savestate'ena после стабильности → потом unregistervm для освобождения ~92 GB.

Stayer chain — DISABLED через traefik

stostayer.snolla.com / old.stostayer.ru
  → DNS → 94.19.247.14
  → router → traefik
  → match Host → нет routes (stostayer.yml.disabled, oldstostayer.yml.disabled)
  → traefik 404 "no route"

Host IIS sites stostayer (:8090) и stostayer.old (:8091) живут для прямого/локального доступа. Conn-strings:

  • stostayer: Data Source=www.stostayer.ru,1433, user stayer_site, password XML-escaped (web.config, pass-protected)
  • stostayer.old: Data Source=localhost (наш MSSQL контейнер)

Запущенные docker контейнеры на хосте

Container Image Port (host) Volume
traefik traefik:v2.6.6 4443, 8000, 8080 named: traefik_traefik_letsencrypt; bind: data/traefik.yml, data/custom/
mssql mcr.microsoft.com/mssql/server:2019-latest 1433 named: mssql_mssql_data (filled from production tar)
minio minio/minio:RELEASE.2020-07-13T18-09-56Z 9000 bind: ./data
imgproxy darthsim/imgproxy:latest 8787 (нет state)
imgproxy-nginx nginx:alpine 8788 bind: ./nginx/cache, ./nginx/nginx.conf
elasticsearch elasticsearch:7.10.1 9200 bind: ./data

Все на docker network proxy (external).

Traefik routes (после attempt 2)

11 cms yml репойнтены на host IIS:8089. 2 stayer yml — .disabled.

File Hosts Backend Статус
snolla.yml snolla.com + 10 *.snolla.com subdomains (rule explicit) host.docker.internal:8089 active → host IIS
rimiz.yml rimiz.ru, www.rimiz.ru host.docker.internal:8089 active (но CMS-side 404 — known)
labtools.yml labtools.ru, www.labtools.ru host.docker.internal:8089 active → host IIS
labtoolspro.yml labtools.pro, www.labtools.pro host.docker.internal:8089 active → host IIS
pilorama98.yml pilorama98.ru, www.pilorama98.ru host.docker.internal:8089 active → host IIS
tandemmebel.yml tandemmebel.ru, www.tandemmebel.ru host.docker.internal:8089 active → host IIS
emspb.yml emspb.ru, www.emspb.ru host.docker.internal:8089 active → host IIS (canary 1, phone-test )
kupimknigi.yml kupimknigi.spb.ru host.docker.internal:8089 active → host IIS
maljarka.yml maljarka.tandemmebel.ru host.docker.internal:8089 active → host IIS
sestech.yml sestech.ru, www.sestech.ru host.docker.internal:8089 active → host IIS
isc-artmaterials.yml ics-artmaterials.com, www.ics-artmaterials.com host.docker.internal:8089 active → host IIS (CMS-side 404 — known)
stostayer.yml.disabled stostayer.snolla.com (n/a, route disabled) DISABLED, host IIS :8090 локально
oldstostayer.yml.disabled old.stostayer.ru (n/a, route disabled) DISABLED, host IIS :8091 локально

Backup-stamp файлы (накопились за обе попытки):

  • *.yml.bak-2026-05-19 — самый ранний backup (до session).
  • *.yml.bak-phase3-2026-05-19 — rollback baseline (attempt 1 → revert state, всё на VM :18080).
  • *.yml.bak-hostip-2026-05-19 — failed attempt 1 (host.docker.internal:80 ⇒ Docker NAT loop).
  • *.yml.bak-stayer-switch-2026-05-19 — stayer switch attempt artefact (Phase 5/6 prev session).
  • *.yml.bak-pre-attempt2-2026-05-19 — текущая live conf attempt 2 (host:8089 backend). Это baseline для atomic revert этой попытки.

Плюс file-provider маршруты для инфраструктурных хостов:

File Host Backend
elasticsearch.yml elasticold.kzntsv.site http://elasticsearch:9200 + basicAuth books:...
minio.yml minio.kzntsv.site http://minio:9000
imgproxy.yml imgproxy.kzntsv.site http://imgproxy-nginx:80

И мёртвые (не отключены, но смотрят в никуда):

  • disk.yml → 192.168.1.10:5005 (Synology disk на мёртвой синке)
  • dsm.yml → 192.168.1.10:5000 (DSM мёртвой синки)

Host IIS configuration (active prod)

Site Bindings Physical path Pool identity Прим.
snolla *:80, *:8089 C:\sites\snolla ApplicationPoolIdentity (.NET v4.0 Integrated) active prod — catch-all для 11 cms hosts, traefik backend :8089
stostayer *:8090 C:\sites\stostayer ApplicationPoolIdentity local-only (traefik route disabled), conn → www.stostayer.ru,1433
stostayer.old *:8091 C:\sites\stostayer.old ApplicationPoolIdentity local-only (traefik route disabled), conn → localhost,1433
Default Web Site (stopped, autoStart=false)

ACL: IIS AppPool\<site>:(OI)(CI)M рекурсивно на каждом site root.

DNS

Все домены остались указывать на 94.19.247.14 (public IP, статический). REGRU как registrar/DNS.

Backup инфраструктура

Текущая (на момент 2026-05-19, после attempt 2):

  • kreknin-synology держит Hyper Backup репо мёртвой синки (~430 GB). Новых бэкапов с recovered Windows-PC НЕТ.
  • Локально на Windows-PC: C:\nas-recovery\vm-sites\ (~11 GB, дамп IIS sites из VM до patches) — резерв если host-IIS сломается катастрофически. После 48h+ uptime можно почистить.
  • C:\nas-recovery\backup\snolla\snolla.ova (42.5 GB) — оригинал OVA. После cleanup VM можно удалить.

Дыра: если Windows-PC сгорит — всё ляжет. Никакой репликации, никакого off-site backup для нового рабочего состояния.

SSH ключи и доступ

После recovery — отозвать публичные ключи Claude из этих 3 машин (~/.ssh/authorized_keys или эквивалент). См. соответствующие entity-страницы.

Известные открытые баги

  1. X-Forwarded headers не передаются от traefik в IIS → CMS делает redirect с :4443 в URL.RESOLVED 2026-05-19 вечер через URL Rewrite 2.1 + <serverVariables> rule на host IIS. Также закрыл утечку :8089 в admin SPA после attempt 2 миграции.
  2. rimiz.ru → 404. CMS-side, не инфра.
  3. ics-artmaterials.com → 404. Аналогично — CMS-side (www.ics-artmaterials.com → 301 → ics-artmaterials.com → 404).
  4. emspb.snolla.com /admin/assets/<guid>/getList → 500 NullReferenceException.RESOLVED 2026-05-19 вечер через DB seed root AssetsFolder rows для 15 sites без них (включая emspb, pilorama98, и др.). Симптом был НЕ site-specific — общий для всех sites которые никогда не использовали admin assets UI. Долгосрочный TODO — null-guard в AssetsJsonViewModelBuilder.Build (требует recompile DLL, отложено до восстановления build env).
  5. acme.json HTTP-01 renewal будет фейлить для доменов с DNS не на нашем IP → переезд на DNS-01 через REGRU до истечения сертификатов (~3 месяца).
  6. *C:\inetpub\logs* растёт — нужна ротация.
  7. docker.sock provider в traefik не работает — но не блокирует (всё через file-provider). См. traefik-on-windows-docker-desktop Pitfall 3.
  8. WinHTTP proxy на хосте strips response headers для curl.exe http://localhost:... — для loop-detect/IIS confirmation использовать docker exec traefik wget или Invoke-WebRequest. См. docker-host-loopback-detect.

Single Points of Failure

  • Один Windows-PC (если сгорит — всё ляжет)
  • Один публичный IP / провайдер
  • Один WiFi-канал
  • Один OpenWRT-роутер
  • Один host IIS instance обслуживает весь cms-трафик (VM остаётся parallel fallback ещё 24-48h)
  • Один MSSQL контейнер (single primary, нет replica)
  • Один MinIO (single drive, не distributed)

Каждый SPOF — кандидат на улучшение в future-resilient-architecture-goals.