Files
admin/STATUS.md
vitya f9bdb97be3 docs(.wiki,.tasks): vds-kzntsv-bootstrap done — 3 phases shipped
VDS Rusonyx 160 NVMe (89.253.255.94 / vds.kzntsv.site) активирован
2026-05-20. 3 фазы за ~6 часов:

- Phase 1: harden + docker 29.5.1 + traefik v2.11 + portainer 2.21.5
- Phase 2: shared DB park (postgres 16 / mariadb 11.4 / mongo 7 /
  redis 7) via traefik raw TCP forward + self-signed TLS
- Phase 3: миграция gitea (132 repos), verdaccio (2063 pkgs), registry
  fresh install (user accepted loss old images) + Joxit GUI

Ingest 1 source + 1 entity (vds-kzntsv) + 6 concepts (traefik-tcp-
passthrough-vs-starttls / portainer-2.21-admin-password-regression /
db-tls-self-signed-via-traefik-raw-tcp / rusonyx-vps-onboarding-quirks
/ registry-gc-mount-and-modify-flag / compose-bcrypt-escape-trap).

3 follow-up  tasks: vds-gc-cron, vds-backup-rsync-kreknin, vds-ntfy-push.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 22:39:31 +03:00

14 KiB
Raw Blame History

Task Board

Updated: 2026-05-20

🟢 [cms-admin-assets-root-folders-seed] — seed 15 missing root AssetsFolder rows в DB, admin assets открывается

Status: done (2026-05-19 вечер). Browser-verified user'ом на pilorama98/emspb. Detail в cms-admin-assets-root-folder-seed. Result: 15 rows inserted (idempotent NOT EXISTS query). Affected: emspb.ru, pilorama98.ru, labtools.pro, kupimknigi.spb.ru, sestech.ru, aquamax.spb.ru, artmone.pro, priemka-kvartiry.ru, profund.spb.ru, ics-artmaterials.com, _voda-indigo.ru + 4 sites с NULL PrimaryDomain. Inserted FolderId/OwnerId captured в .tasks/cms-admin-assets-root-folders-seed.inserted-rows.txt для atomic revert. Long-term TODO (deferred): null-guard в AssetsJsonViewModelBuilder.Build (CMS code) — defensive fix чтобы не crash'ить если root missing. Требует recompile MoreThenCms.Admin.dll, ждёт build env (vds-kzntsv-bootstrap). Branch: master


🟢 [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/registry мигрированы (3/3 phases done 2026-05-20)

Status: done (2026-05-20 вечер — все 3 заявленные фазы закрыты) Where I stopped: Phase 1 + Phase 2 завершены . VDS 89.253.255.94 / vds.kzntsv.site Ubuntu 24.04 upgraded через VNC. sudo vitya (NOPASSWD) + ssh-key + hardened sshd (key-only) + ufw 22/80/443 + DB-порты + fail2ban + docker 29.5.1 + buildx + compose. Traefik v2.11 на traefik.vds.kzntsv.site (basicAuth vitya:Pryakhin9). Portainer CE 2.21.5 на portainer.vds.kzntsv.siteадмин-пароль был принудительно изменён на Pryakhin9-VDS-2026 (18 chars) из-за hard min-12-char policy в Portainer 2.21+ (regression от 2.20). API key получен и сохранён в vds-kzntsv.env. 4 DB-стека (Postgres 16, MariaDB 11.4, Mongo 7, Redis 7) подняты с self-signed TLS, доступны снаружи через traefik raw-TCP passthrough на <db>.vds.kzntsv.site:<port> (HostSNI(*) — traefik tls.passthrough+SNI не работает с STARTTLS-протоколами PG/MariaDB; rawTCP forward, DBs терминируют TLS сами). Все DB passwords (PG/Maria/Mongo/Redis) — strong random hex16, сохранены в vds-kzntsv.env. Open questions: LE certs для DBs (сейчас self-signed → клиент verify-skip; permanent fix позже через lego sidecar extract из traefik acme.json). Next action: Phase 3 миграция с kreknin ВСЯ DONE . 3.1 gitea (132 repos, 4 users, v1.25.5 на git.kzntsv.site). 3.2 verdaccio (8.6G storage, 2063 packages, secret 32 chars). 3.3 registry — отказались от миграции старых 35G images (user: «новых наделать могу»), fresh install на registry.kzntsv.site + Joxit UI на registry-ui.vds.kzntsv.site (DELETE_IMAGES=true для GUI cleanup, REGISTRY_STORAGE_DELETE_ENABLED для API delete). Auth vitya:Pryakhin9 (см. vds-kzntsv.env). Follow-up tasks: vds-gc-cron, vds-backup-rsync-kreknin, vds-ntfy-push. Branch: master


🔴 [iis-on-host-migration] — attempt 2: 11 cms LIVE на host IIS:8089, 24h soak в процессе

Status: active (вернулась к фокусу после закрытия vds-kzntsv-bootstrap; soak продолжается, нужна проверка после 24h+ uptime) 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


[vds-gc-cron] — cron GC для verdaccio и registry на VDS

Status: ready (заведена 2026-05-20). Детали + sketch implementation в vds-gc-cron.md. Where I stopped: task создана как follow-up к vds-kzntsv-bootstrap Phase 3 — после стабилизации миграции нужно автоматизировать periodic GC чтобы registry не разрастался снова до 99G, и verdaccio storage не пух от старых версий. Next action: дождаться завершения vds-kzntsv-bootstrap Phase 3, потом написать cron + GC-скрипты + проверить. Branch: master


[vds-backup-rsync-kreknin] — ежедневный rsync VDS→kreknin в 05:00 MSK + email-нотификация

Status: ready (заведена 2026-05-20). Детали + sketch implementation в vds-backup-rsync-kreknin.md. Where I stopped: task создана для backup pipeline VDS → kreknin (closing SPOF gap из future-resilient-architecture-goals). SMTP creds для noreply@snolla.com на Yandex сохранены в ~/projects/.common/secrets/noreply-snolla-smtp.env. Рекомендованный recipient vitya.kuznetsov@gmail.com. Дублирующий канал — vds-ntfy-push (push на телефон). Next action: msmtp setup на VDS + rsync script с DB dumps + --link-dest incremental + cron 05:00 + email на vitya.kuznetsov@gmail.com + ntfy publish. Retention 7d/4w/6m. Branch: master


[vds-ntfy-push] — self-hosted ntfy.vds.kzntsv.site для push-нотификаций на телефон

Status: ready (заведена 2026-05-20). Детали + sketch implementation в vds-ntfy-push.md. Where I stopped: task создана как канал push-уведомлений с VDS на телефон user'а. Будет интегрирована с vds-backup-rsync-kreknin (backup status), monitoring (cert expiry, disk fill, container crashes), и любыми ops-скриптами. Open questions: iOS vs Android → Android (resolved 2026-05-20, pure self-host OK). Auth model (per-topic ACL recommend); список топиков. Next action: уточнить платформу телефона у user'а → ntfy compose на VDS → ntfy.vds.kzntsv.site через traefik → docker exec ntfy user add admin → integration в backup-script. 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