From 648159d84f622c220141ed53f4cd136cdc8af37c Mon Sep 17 00:00:00 2001 From: vitya Date: Tue, 19 May 2026 16:01:12 +0300 Subject: [PATCH] docs(.wiki): ingest iis-host-migration attempt 2 (success) + docker-host-loopback-detect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 10 успех — recipe из post-mortem применён полностью: backend port :8089, bak-pre-attempt2 серия, IIS binding + Stop+Start, loop-detect через docker exec wget, 2 canary phone-tests от мобильного интернета, batch 9 cms; stayer routes user-ом подтверждены internal → .yml.disabled. Touched: - sources/iis-host-migration-2026-05-19.md — append Phase 10 - concepts/iis-migration-2026-05-19-postmortem.md — footer attempt-2-succeeded с маппингом recipe A-G - concepts/recovery-architecture-snapshot.md — major rewrite, chain через host-IIS:8089, VM = parallel fallback - entities/snolla-recovery-vm.md — status parallel-fallback, 24-48h soak - entities/windows-recovery-host.md — IIS sites active prod - NEW concepts/docker-host-loopback-detect.md — recipe loop-detect + WinHTTP-proxy gotcha - index.md, log.md --- iis-host-migration-2026-05-19.md | 63 ++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/iis-host-migration-2026-05-19.md b/iis-host-migration-2026-05-19.md index 95dd569..c9f05b6 100644 --- a/iis-host-migration-2026-05-19.md +++ b/iis-host-migration-2026-05-19.md @@ -176,3 +176,66 @@ Production снова на VM-chain (как было в начале сесси - Web.config'и в `C:\sites\` пропатчены правильно (sitePath, conn-strings, stostayer на новый DB) — можно переиспользовать. - IIS sites/pools уже настроены — переключение требует только traefik backend patch + tested correctly. - Recipe для правильной миграции — в [[iis-migration-2026-05-19-postmortem]]. + +--- + +## Phase 10 — Attempt 2 (вечер 2026-05-19, после прочтения post-mortem) + +Повторная попытка миграции, выполненная **по recipe из [[iis-migration-2026-05-19-postmortem]]**. Все 5 главных правил соблюдены, миграция прошла без incidents. + +### Что сделано + +1. **Read-only sanity (без prod-touches):** VM running confirmed, port-scan на хосте показал `:18090` и `:8089` свободны, traefik dir contains 4 серии bak-stamp'ов сохранённых от attempt 1, IIS sites/pools (`snolla, stostayer, stostayer.old`) живы. +2. **Backend port: `:8089`** (recipe-A — НЕ `:80`, НЕ совпадает с traefik publish `:8000/:4443/:8080`, НЕ совпадает с VM NAT forwards `:18080/:18180/:18181`). Выбор user'а (был кандидат `:18090`, user предпочёл `:8089`). +3. **Atomic revert plan ДО старта** (recipe-E): новая bak-серия `.bak-pre-attempt2-2026-05-19` для всех 13 yml (11 cms + 2 stayer), paste-ready команда восстановления записана в `.tasks/STATUS.md`. +4. **IIS binding** `snolla *:8089` добавлен через elevated PS (`New-WebBinding` + `Stop-Website; Start-Website` — recipe-A note: без restart binding не активируется). +5. **Loop-detect через `docker exec`** (recipe-A + recipe-F): `docker exec traefik wget --spider -S --header="Host: emspb.ru" http://host.docker.internal:8089/` → first response `301 → http://www.emspb.ru/` от `Server: Microsoft-IIS/10.0`. `host.docker.internal` resolves to `192.168.65.254:8089` — это Docker Desktop host gateway, **не traefik publish-port**. NO NAT loop. См. [[docker-host-loopback-detect]] про общую технику. +6. **Smoke test с `-MaximumRedirection 0`** (recipe-B): `curl.exe -k -I --max-redirs 0 -H "Host: emspb.ru" https://localhost:4443/` → first response `301`, `Server: Microsoft-IIS/10.0`, `Location: http://www.emspb.ru/`. Это **expected CMS canonical redirect** (та же логика что была на VM). +7. **Canary atomic** — patched ОДИН yml (`emspb.yml`), file-provider auto-reload, public smoke clean → 📱 **phone-test с мобильного интернета** (recipe-C) → `https://emspb.ru/` открылось → ✅. +8. **Second canary** — `labtools.yml`, smoke + phone-test → ✅. +9. **Batch patch** оставшихся 9 cms yml (snolla, rimiz, labtoolspro, pilorama98, tandemmebel, kupimknigi, maljarka, sestech, isc-artmaterials) одним PS-блоком (recipe-G: batch не item-by-item) → smoke 20 hostnames → все `Server: Microsoft-IIS/10.0` ✅. +10. **Stayer routes — disabled** (re-confirmed Phase 7 decision): user подтвердил «stayer'ы локальные, через traefik наружу не светят». Rename `stostayer.yml → stostayer.yml.disabled`, `oldstostayer.yml → oldstostayer.yml.disabled`. `docker restart traefik` (file-provider не подхватил deletion auto-reload). Verify: `stostayer.snolla.com`/`old.stostayer.ru` → `404 text/plain` (traefik no-route). Host IIS sites `:8090`/`:8091` остаются live для прямого/локального доступа. +11. **VM running parallel** (recipe-D): VM **НЕ savestate'ить** минимум 24h+. Освободит RAM/disk только после подтверждённой стабильности host'а. + +### Pitfall found and resolved + +- **WinHTTP proxy strips Server header.** Локальный `curl.exe http://localhost:8090/` returned response без `Server: Microsoft-IIS/10.0` и без `X-Powered-By: ASP.NET` (плюс с `Proxy-Connection: keep-alive`) — выглядело как «не IIS отвечает». Это привело к moment'у panic. Но `docker exec traefik wget ...` (real production path) **показал headers корректно**. Вывод: для loop-detect / IIS-confirmation тестов **использовать `docker exec` из traefik container**, не Windows `curl.exe` — последний ходит через Windows-уровневый proxy который headers вырезает. + +### My mistake during this session + +- Я неверно интерпретировал «мигрировать stayer'ов» как «patch traefik backend → host:8090/8091» (т.е. пускать через traefik наружу). User имел в виду «host IIS уже на :8090/:8091, traefik routes должны быть **DISABLED**». Сделал prod-changing patch → user интервент-stop → revert + rename `.yml.disabled`. См. memory `feedback-migrate-semantics`. Lesson — переспрашивать semantics для internal/low-traffic сервисов перед prod-changing. + +### Финальный chain (после attempt 2) + +``` +Клиент (browser) + → DNS → 94.19.247.14 (public IP) + → OpenWRT NAT 443 → 192.168.1.143:4443 + → traefik:4443 (TLS termination) + → match Host → одно из 11 cms-yml → backend + → http://host.docker.internal:8089/ + ↳ Docker Desktop host gateway 192.168.65.254:8089 + → Windows host IIS site `snolla` (*:80 + *:8089 bindings) + → C:\sites\snolla\, .NET Framework 4.8.1, ApplicationPoolIdentity + → conn → MSSQL container на host:1433 + ← HTTP response +``` + +Stayer chain: traefik routes disabled. `stostayer.snolla.com` / `old.stostayer.ru` → traefik 404. Host IIS sites `:8090`/`:8091` живут для локального доступа. + +VM `snolla-recovery`: **running parallel** (24h+ soak), backend в traefik больше не используется — VM NAT port forwards (`:18080/:18180/:18181`) холостые. + +### Артефакты этой сессии + +- `.tasks/STATUS.md` — статус task'а 🔴 active. +- traefik backups в `data/custom/`: `*.yml.bak-pre-attempt2-2026-05-19` для 13 yml, плюс `stostayer.yml.disabled`, `oldstostayer.yml.disabled`. +- `feedback-migrate-semantics` memory — урок для будущих сессий. +- `concepts/docker-host-loopback-detect.md` — новый concept для loop-detect technique. + +## Что осталось open + +- **24h+ soak** до savestate VM (минимум до утра 2026-05-20, лучше 48h до 2026-05-21). +- **VM cleanup**: после soak — `savestate` (освободит RAM), позже `unregistervm --delete` (освободит ~92 GB). +- **Port forwards OpenWRT** (`host:18080/18180/18181/18189` → VM) — больше не нужны, удалить позже. +- **rimiz.ru / ics-artmaterials.com 404** — CMS-side routing issues, не инфра. Открытым. +- **X-Forwarded headers** (`:4443` в redirect URL) — известный bug [[traefik-on-windows-docker-desktop]] Pitfall 5, отдельная задача.