VBoxManage controlvm snolla-recovery savestate — 45.6s, VMState=saved. Savestate file 1.73 GB (compressed 4096 MB RAM). VBoxHeadless процессы освободили ~4 GB private memory. Resume в 30 сек через startvm --type headless. unregistervm --delete (~95 GB disk reclaim) запланирован на +неделю uptime. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
18 KiB
Task Board
Updated: 2026-05-21
🟢 [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):
- URL Rewrite 2.1 MSI installed (rewrite_amd64_en-US.msi, 6 MB, version 7.1.1993.2351).
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.C:\sites\snolla\Web.config(per-site):<system.webServer>/rewrite/rules+= rule "ForwardedProto-HTTPS" — match.*, conditionHTTP_X_FORWARDED_PROTO == "https", action None, serverVariables setHTTPS=on,SERVER_PORT=443,SERVER_PORT_SECURE=1. BackupWeb.config.bak-pre-portleak-2026-05-19(size 19050 bytes). UTF-8 BOM сохранён.- 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 (общий sitesnolla). Verified: user-side public browser test confirmed — admin SPA loads без:8089в URL'ах для остальных 10 cms hosts. Side regression (pre-existingcustomErrors 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(modelnull от_assetsFoldersService.GetFolderByPath(ctx, ownerId, '')) — user подтвердил «только этот site», CMS-side bug, не в scope. Зафиксировано вrecovery-architecture-snapshotopen 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 close-out: 36h soak passed, 8/8 наших sites зеленые
Status: done (2026-05-21 close-out). Detail: Phase 11 в iis-host-migration-2026-05-19.
Close-out evidence: traefik Up 38h (zero restarts), w3wp 8.8h (scheduled pool recycle ~29h default, не crash), 8/8 наших sites вернули Microsoft-IIS/10.0 через full traefik HTTPS chain (emspb/snolla/on.snolla/pilorama98/labtools.ru/labtools.pro/tandemmebel/kupimknigi). Маljarka/sestech/ics-artmaterials оказались off-infra (DNS снят / parked / external nginx) — не наша инфра, не regression. Новая follow-up task ⚪ iis-traefik-dead-routes-cleanup (низкий приоритет — почистить yml для 3 dead доменов).
VM savestate: done 2026-05-21 05:13 MSK (45.6s, VMState=saved). Savestate file 1.73 GB (C:\Users\vitya\VirtualBox VMs\snolla-recovery\Snapshots\2026-05-21T05-12-43-636491200Z.sav). VBoxHeadless процессы освободили ~4 GB private memory. Resume: VBoxManage startvm snolla-recovery --type headless (~30 сек если понадобится). Disk delete (unregistervm --delete, ~95 GB) — позже через неделю uptime.
Atomic revert (unchanged): 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
⚪ [iis-traefik-dead-routes-cleanup] — почистить traefik yml для 3 off-infra доменов
Status: ready (заведена 2026-05-21 как follow-up к iis-on-host-migration close-out).
Scope: 3 hostname'а в data/custom/*.yml теперь указывают на не-нашу инфру:
maljarka.ru— DNS снят (нет A record)sestech.ru— запаркован у domainparking.ruics-artmaterials.com— A→87.236.16.28 (external nginx-reuseport WP) Next action: найти соответствующие traefik yml,.disableили удалить routes; smoke что хосты-соседи не задеты; уведомить user'а что rimiz.ru (404 CMS-side) — отдельный случай, не сюда. Priority: low — dead-routes не активные backend traffic, просто noise в logs/configs. Branch: master Done: bak-серия.bak-pre-attempt2-2026-05-19для 13 yml; IIS bindingsnolla *: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.com301 →on.snolla.com(canonical default subdomain),on/pilorama98/labtools/emspb.snolla.com200 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 sitesstostayer :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 + updaterecovery-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 traefikBranch: master
🟢 [vds-gc-cron] — weekly GC armed для verdaccio + registry на VDS
Status: done (2026-05-21 00:21 MSK; ~1ч работы). Детали в vds-gc-cron.md.
Result: /etc/cron.d/vds-gc armed — Sun 03:00 MSK registry-gc.sh, Sun 03:30 MSK verdaccio-prune.sh. Scripts в /opt/stacks/gc/scripts/ (notify.sh, registry-gc.sh, verdaccio-prune.sh+verdaccio-prune.js). Logs в /var/log/vds-gc/. Notify через ntfy vds-ops.
Verdaccio prune real run: 8.5G → 6.8G (freed 1.7G), 7021 packages scanned, 1551 modified, 4524 tgz deleted, 0 errors, 73 locally-published versions защищены (@snollajs/* + similar — detected via _distfiles[tgzName] absent). Atomic JSON rewrite (tmp + rename) + _rev bump.
Registry GC smoke: alpine v1+v2 pushed → DELETE manifest → GC freed 61M (whole tree, since both tags pointed одну digest). Empty-storage guard added (first run на свежем registry — /var/lib/registry/docker/registry/v2/repositories отсутствует → skip+min-prio notify, не FAIL).
Atomic revert: ssh vitya@89.253.255.94 'sudo rm /etc/cron.d/vds-gc; sudo systemctl restart cron; sudo rm -rf /opt/stacks/gc /var/log/vds-gc'
Branch: master
🟢 [vds-backup-rsync-kreknin] — daily VDS→kreknin live, smoke green, cron armed
Status: done (2026-05-20 → 2026-05-21 00:00 first-run завершён успешно). Детали в vds-backup-rsync-kreknin.md.
Result: rsync --link-dest pipeline /opt/stacks/backup/scripts/run.sh под cron 0 5 * * * (root) → kreknin /volume1/NetBackup/vds-kzntsv/<DATE>/ + symlink latest. DB dumps (pg/maria/mongo/redis), system config (/etc/ssh, ufw, hosts, docker), ssh keys, /opt/stacks data. Notification dual-channel: email через msmtp+Yandex (/etc/msmtprc) + ntfy publish на vds-backup topic. Retention 7 daily snapshots. Smoke run done — 71,867 files / 11.74G в 21m27s, exit 0. Cron service installed (apt install cron — Ubuntu 24.04 не имел его) + enabled. Next run автоматически 2026-05-21 05:00 MSK.
SPOF gap status: closed for VDS — full restore from kreknin возможен (DB dumps + конфиги + ssh keys).
Open: phone-side smoke (user verifies ntfy push пришёл из реального backup run).
Atomic revert: ssh vitya@89.253.255.94 'sudo systemctl stop cron; sudo rm /etc/cron.d/vds-backup; sudo apt-get remove -y cron msmtp msmtp-mta; sudo rm -rf /etc/msmtprc /opt/stacks/backup /var/log/vds-backup'
Branch: master
🟢 [vds-ntfy-push] — self-hosted ntfy.vds.kzntsv.site live, phone-verified
Status: done (2026-05-20 вечер; ~30 min работы). Detail в vds-ntfy-push.md.
Result: ntfy v2.11.0 на ntfy.vds.kzntsv.site, LE cert (R12, valid до 2026-08-18), admin user vitya / Pryakhin9 (deny-all дефолт, admin role → rw to all), топики vds-backup + vds-ops. Phone-verified — оба push'а пришли в Android ntfy app (screenshot 22:54). Creds в ~/projects/.common/secrets/vds-kzntsv.env + /opt/stacks/ntfy/.env (chmod 600).
Integration ready for: vds-backup-rsync-kreknin (publish status на vds-backup), monitoring scripts (на vds-ops).
Atomic revert: ssh vitya@89.253.255.94 'cd /opt/stacks/ntfy && docker compose down -v && cd .. && rm -rf ntfy' + remove ntfy entries из vds-kzntsv.env.
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