Files
admin/STATUS.md
vitya 5f8b2dfaf7 docs(.wiki,.tasks): close cms-port-leak-fix — URL Rewrite serverVariables на host IIS
Port :8089/:4443 утечка в admin URLs закрыта. URL Rewrite 2.1 + apphost
allowedServerVariables (HTTPS/SERVER_PORT/SERVER_PORT_SECURE) + Web.config rule
на X-Forwarded-Proto=https → set SERVER_PORT=443/SERVER_PORT_SECURE=1/HTTPS=on
ДО того как ASP.NET читает их в Url.SiteRoot(). Лечит все 11 cms (общий site
snolla). Path B (traefik http entrypoint :80→:8090) abandoned — Docker Desktop
WSL2 NAT quirk на host.docker.internal:80 возвращает 17-byte 301 plain text
независимо от traefik internals. Quirk не reproducible на Linux Docker (synology).

Side regression: pre-existing customErrors mode="off" lowercase в Web.config
пробудился после ASP.NET full-reload (мой rewrite-block edit) — fixed (Off).

Outside scope, open: emspb.snolla.com /admin/assets/<guid>/getList → 500 NullRef
в AssetsJsonViewModelBuilder.cs:22 (model null от GetFolderByPath). User
подтвердил «только этот site». Зафиксировано в snapshot open issue #8.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 18:43:03 +03:00

62 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Task Board
_Updated: 2026-05-19_
## 🟢 [cms-port-leak-fix] — утечка `:8089`/`:4443` в admin URLs закрыта через URL Rewrite serverVariables
**Status:** done (2026-05-19 вечер; verified user-side в браузере, остальные 10 cms работают). Detailed wiki concept — [[cms-server-port-leak-fix]].
**Root cause:** `MoreThenCms.Admin\Mis\Web\Mvc\UrlHelpers\UrlHelpers.cs:14-37` `Url.SiteRoot()` читает `SERVER_PORT`/`SERVER_PORT_SECURE` из server vars, и в attempt2-host setup `SERVER_PORT=8089` → leak. Десятки .cshtml файлов (admin views + `_Layout`/`_LogInLayout`) рендерят это в `mis.siteRoot` и `<style background: url(...)>`. На VM работало просто потому что `SERVER_PORT=80` (см. SSH probe VM IIS bind = `*:80`).
**Path tried (failed):** **B (traefik http entrypoint :80→:8090 + backend `host.docker.internal:80`)** — Docker Desktop's WSL2 NAT proxy на Windows перехватывает `host.docker.internal:80`/`gateway.docker.internal:80`/LAN IP :80 и возвращает 301 plain text **независимо** от того что traefik listening на :8090 inside. Quirk Windows Docker Desktop, не traefik. Не работает на этом стэке.
**Path applied (working):** **C (URL Rewrite 2.1 + serverVariables в Web.config)**:
1. URL Rewrite 2.1 MSI installed (rewrite_amd64_en-US.msi, 6 MB, version 7.1.1993.2351).
2. `applicationHost.config` (admin): `<system.webServer>/rewrite/allowedServerVariables` += `HTTPS`, `SERVER_PORT`, `SERVER_PORT_SECURE` через `appcmd set config ... /commit:apphost`. Backup `.bak-pre-portleak-2026-05-19`.
3. `C:\sites\snolla\Web.config` (per-site): `<system.webServer>/rewrite/rules` += rule "ForwardedProto-HTTPS" — match `.*`, condition `HTTP_X_FORWARDED_PROTO == "https"`, action None, serverVariables set `HTTPS=on`, `SERVER_PORT=443`, `SERVER_PORT_SECURE=1`. Backup `Web.config.bak-pre-portleak-2026-05-19` (size 19050 bytes). UTF-8 BOM сохранён.
4. Smoke через `docker exec traefik wget https://127.0.0.1:443/admin/account/login --header='Host: emspb.snolla.com'` (через полный traefik HTTPS chain, traefik 2.x шлёт X-Forwarded-Proto: https автоматом) → `mis.siteRoot = 'https://emspb.snolla.com'` (БЕЗ `:8089`) ✅. То же для `labtools.snolla.com` ✅. **Затрагивает все 11 cms hosts** (общий site `snolla`).
**Verified:** user-side public browser test confirmed — admin SPA loads без `:8089` в URL'ах для остальных 10 cms hosts. **Side regression** (pre-existing `customErrors mode="off"` lowercase — fatal config error после ASP.NET full-reload) — пойман и пофиксен (`mode="Off"`). **Outside scope (открыт):** `emspb.snolla.com /admin/assets/<guid>/getList` → 500 NullRef в `AssetsJsonViewModelBuilder.cs:22` (`model` null от `_assetsFoldersService.GetFolderByPath(ctx, ownerId, '')`) — user подтвердил «только этот site», CMS-side bug, не в scope. Зафиксировано в `recovery-architecture-snapshot` open issue #8.
**Atomic revert:** `Copy-Item C:\sites\snolla\Web.config.bak-pre-portleak-2026-05-19 C:\sites\snolla\Web.config -Force` + ~3 сек app pool reload. apphost allowedServerVariables можно оставить (inert без rule). URL Rewrite MSI можно оставить (no rules = no behavior).
**Branch:** master
---
## ⚪ [vds-kzntsv-bootstrap] — поднять облачный VDS под gitea/verdaccio/seafile/registry/hermes
**Status:** ready (тариф **160 NVMe Rusonyx** заказан 2026-05-19; ждём выделение IP; OS Ubuntu 24.04)
**Where I stopped:** заказ на Rusonyx размещён (6 vCPU / 8GB RAM / 160GB NVMe / Ubuntu 24.04, без ispmanager/Backup/CMS). zero-day bootstrap чек-лист готов. Detailed план в [vds-kzntsv-bootstrap.md](vds-kzntsv-bootstrap.md).
**Open questions:** owncloud дубль (`docker/owncloud/` vs `docker/personal/owncloud/`) — какой live для миграции в seafile; DNS-cut стратегия.
**Next action:** (1) ждём выделение IP от Rusonyx → DNS A `vds.kzntsv.site` в REGRU; (2) zero-day bootstrap (sudo-user + ssh hardening + ufw + fail2ban + docker); (3) параллельно — registry GC + verdaccio prune **на kreknin** до миграции (write-op, требует согласия).
**Branch:** master
---
## 🔴 [iis-on-host-migration] — attempt 2: 11 cms LIVE на host IIS:8089, 24h soak в процессе
**Status:** active (2026-05-19 вечер — 11 main cms routes мигрированы, smoke clean, 2 phone-tests passed; 2 stayer routes ещё на VM до отдельного решения; VM running parallel — НЕ savestate'ить).
**Done:** bak-серия `.bak-pre-attempt2-2026-05-19` для 13 yml; IIS binding `snolla *:8089` + Stop/Start Website; loop-detect через `host.docker.internal:8089` ≠ NAT loop (resolves to 192.168.65.254 host gateway) ✅; 11 cms yml (snolla, rimiz, labtools, labtoolspro, pilorama98, tandemmebel, emspb, kupimknigi, maljarka, sestech, isc-artmaterials) patched `:18080 → :8089`; host-side smoke 20 hostnames → все `Server: Microsoft-IIS/10.0` ✅; 📱 phone-tests (mobile internet): `emspb.ru` ✅, `labtools.ru` ✅; traefik logs clean (only known docker.sock noise); pre-existing CMS issues подтверждены и НЕ regression: `rimiz.ru/ics-artmaterials.com 404` (CMS-routing); `snolla.com` 301 → `on.snolla.com` (canonical default subdomain), `on/pilorama98/labtools/emspb.snolla.com` 200 OK.
**Done (stayer):** stayer routes user'ом подтверждены «внутренние, наружу не светим» → `stostayer.yml → stostayer.yml.disabled`, `oldstostayer.yml → oldstostayer.yml.disabled`; `docker restart traefik`; verify: `stostayer.snolla.com`/`old.stostayer.ru` → 404 traefik no-route ✅; host IIS sites `stostayer :8090`/`stostayer.old :8091` остаются live для прямого/локального доступа (CMS отвечает контент, headers stripped через WinHTTP proxy на curl, но изнутри traefik / production-path headers Microsoft-IIS/ASP.NET корректные).
**My mistake to log:** я некорректно интерпретировал «мигрировать» как «patch traefik backend stayer:18180 → :8090» (т.е. пускать через traefik наружу). User имел в виду «host IIS уже есть, traefik routes должны быть DISABLED». Сделал patch backend → user интервент-stop → revert + rename `.disabled`. Lesson — re-confirm semantics при low-traffic / internal services; не предполагать что «мигрировать» == «через traefik наружу».
**Where I stopped:** 14 cms hosts через host IIS:8089, stayer routes наружу выключены. Soak в процессе.
**Next action:** (a) phone-test 2-3 random cms domains; (b) wait 24h+ uptime; (c) docs: post-success wiki ingest + update `recovery-architecture-snapshot.md` (stayer = disabled, не migrated); (d) только после 24h+ + zero rollbacks → consider savestate VM.
**Atomic full revert (paste-ready):** ```Get-ChildItem C:\Users\vitya\projects\docker\diskstation\traefik\data\custom\*.yml.bak-pre-attempt2-2026-05-19 | %{ Copy-Item $_.FullName -Destination ($_.FullName -replace '\.bak-pre-attempt2-2026-05-19$','') -Force }; Move-Item C:\Users\vitya\projects\docker\diskstation\traefik\data\custom\stostayer.yml.disabled C:\Users\vitya\projects\docker\diskstation\traefik\data\custom\stostayer.yml -Force -EA SilentlyContinue; Move-Item C:\Users\vitya\projects\docker\diskstation\traefik\data\custom\oldstostayer.yml.disabled C:\Users\vitya\projects\docker\diskstation\traefik\data\custom\oldstostayer.yml -Force -EA SilentlyContinue; docker restart traefik```
**Branch:** master
---
## 🟢 [nas-recovery] — клиентские сайты восстановлены, работают из публичного интернета
**Status:** done (2026-05-19 ~10:00 MSK — 15 часов работы)
**Final state:** OpenWRT NAT → traefik 2.6.6 (host:8000/4443) → VirtualBox VM snolla-recovery (IIS + CMS) + docker-стек на хосте (MSSQL/MinIO/ES/imgproxy/nginx). 13 client routes, 40 LE certs валидны. Проверено: пользовательский клиент из публичного интернета открывает snolla.com, pilorama98.ru, labtools.ru/pro, tandemmebel.ru, emspb.ru.
**Backup pull:** C:\nas-recovery\vm-sites\ (~11 GB inetpub/wwwroot + stayer/) — на случай если VM снова станет нестабильной.
**Open issues (минор):**
- X-Forwarded-Proto/Host: CMS делает redirect с портом 4443 в URL — нужно добавить middleware в traefik или включить trust в IIS.
- MinIO/Azure storage — пользователь упомянул "не так всё", ждём пояснение.
- docker-сокет проброс в traefik — daemon connection error (некритично, file-provider routing работает).
- VM в bridged-WiFi была нестабильной → переехали на NAT + port forwards.
- acme.json renewal через HTTP-01 фейлится для доменов с DNS не на нашем IP — нужно переключить на DNS-01 через REGRU (creds в env уже).
**Branch:** master
---
<!--
Status legend:
🔴 Active — only one at a time
🟡 Paused — in progress, resumable
⚪ Ready — defined, not started
🟢 Done — kept until merged
🔵 Blocked — waiting on external input
-->