diff --git a/.wiki/entities/.gitkeep b/.wiki/entities/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/.wiki/entities/dead-synology-diskstation.md b/.wiki/entities/dead-synology-diskstation.md new file mode 100644 index 0000000..0c2391b --- /dev/null +++ b/.wiki/entities/dead-synology-diskstation.md @@ -0,0 +1,70 @@ +--- +title: Мёртвая Synology DiskStation (source NAS) +type: entity +tags: [hardware, nas, xpenology, raid, dead] +sources: [../sources/nas-recovery-session-2026-05-18.md] +updated: 2026-05-19 +--- + +# Dead Synology DiskStation + +Source NAS, на котором хостились клиентские сайты MoreThenCms до 2026-05-18. **Сейчас off / data unrecoverable средствами DSM.** + +## Hardware + +- **Тип:** XPEnology (DSM 7 на самосборном x86, community-loader) +- **Шасси:** 6 HDD bay +- **Hostname:** `diskstation` +- **Bootloader:** USB-флешка (внешняя относительно дисков) +- **System SSD:** Netac SSD 120 GB (отдельный) — "Отказ системного раздела" к моменту инцидента +- **DSM hostname в сети:** `diskstation` (LAN), без публичного DDNS (доступ через клиентские домены через traefik) + +## Storage pool + +- **RAID 5** на **3 дисках** WD Red **WD40EFAX-68JH4N1 / 68JN4N0** (3.6 TB каждый) +- ~7 TB usable (`/dev/mapper/cachedev_0` 7.0T) +- ⚠️ **WD40EFAX = SMR** — см. [[wd40efax-smr-cascade]] для механики краха. + +## Что было на NAS + +### VMM +- **snolla VM:** Windows-VM с IIS + .NET Framework 4.8 + CMS [[snolla-recovery-vm]] +- MAC: `02:11:32:2A:7C:B9`, IP `192.168.1.15` (DHCP-резервация на роутере) +- OVA-экспорт от 2024-10-27 включён в Hyper Backup → теперь работает на VirtualBox на [[windows-recovery-host]]. + +### Container Manager (docker) +- **mssql:** Server 2019, 5 БД (`MoreThenCms`, `StayerCalculator`, `StayerPrice`, `stostayer`, `TireService`) +- **minio:** RELEASE.2020-07-13T18-09-56Z, 9 бакетов (artmone 2.5 GB, pilorama98 120 MB, books 5 MB, и др.) +- **elasticsearch:** 7.10.1, 3 индекса (для books-стека, не MoreThenCms) +- **imgproxy + nginx-cache** +- **traefik:** 2.6.6, 13 client routes, 40 Let's Encrypt сертификатов +- **gitea:** 2.6 GB +- Прочее: jellyfin, mongo, owncloud, navidrome, mariadb, и т.д. + +### Shares +- `/docker/` — docker-стеки +- `/docker/personal/` — большая часть production-сервисов +- `/backup/` — куда писались ежедневные дампы: + - `/backup/snolla/SQLServer/MoreThenCms.zip` — ежедневный sql-script (101 MB compressed) + - `/backup/snolla/snolla.ova` — 42.5 GB, экспорт VM (последний 2024-10-27) +- `/work/` — рабочая папка разработчика (в восстановление не брали по решению пользователя) + +## Что произошло 2026-05-18 + +См. [[wd40efax-smr-cascade]]. Кратко: первый диск умер в начале мая, ~2 недели пул жил degraded, second disk вылетел 2026-05-18 → RAID 5 за пределами redundancy → пул "Сбой сборки" в DSM. + +## Что НЕ делать с этой коробкой + +- ❌ Repair / Online Assembly в DSM на этом пуле — бесполезно. +- ❌ Вытаскивать оставшиеся 2 диска до решения "нужно ли pro data recovery". +- ❌ Пересоздавать пул на тех же дисках. +- ❌ Ставить новые WD40EFAX (если будут запасные) — же баг останется. + +## План восстановления железа (после ремонта инфраструктуры) + +- Заменить все WD40EFAX на CMR-диски (WD Red **Plus** / Seagate IronWolf / WD Red Pro / HGST Ultrastar). +- Заменить Netac SSD на нормальный consumer SSD (Samsung 870 EVO / WD Red SA500). +- Конфигурация: + - **3 CMR в RAID 5** + ежедневный Hyper Backup + дисциплина replace failed disk в течение 24-48 часов + - **или 4 CMR в RAID 6** (или SHR-2) — толерирует 2 отказа, рекомендуется после такого опыта +- Тест восстановления раз в квартал. diff --git a/.wiki/entities/kreknin-synology.md b/.wiki/entities/kreknin-synology.md new file mode 100644 index 0000000..4c32406 --- /dev/null +++ b/.wiki/entities/kreknin-synology.md @@ -0,0 +1,59 @@ +--- +title: Kreknin Synology (backup target + DDNS) +type: entity +tags: [hardware, nas, synology, backup, hyperbackup] +sources: [../sources/nas-recovery-session-2026-05-18.md] +updated: 2026-05-19 +--- + +# Kreknin Synology + +Удалённая (географически в другом месте) Synology, которая держит Hyper Backup-репо мёртвой синки и сама работает как живой сервер. + +## Доступ + +- **Public IP:** 195.19.90.188 +- **DDNS:** kreknin.site (резолвится на 195.19.90.188) +- **DSM web:** http://kreknin.site:5000 (HTTP; HTTPS 5001 наружу НЕ проброшен) +- **SSH:** vitya@195.19.90.188:22 (был пароль, сейчас SSH-ключ установлен — `id_ed25519_kreknin`) +- **Канал:** "не очень надёжный" по словам пользователя — поэтому неудобно держать там production-сайты. + +## Ограничения SFTP + +- **SFTP-подсистема DSM запускается отдельно от SSH** — Control Panel → File Services → FTP → SFTP. Изначально не была включена. +- **После включения SFTP — DSM jail-chroot'ит подсистему в home юзера.** То есть `vitya` через SFTP видит только `/volume1/homes/vitya/`, не `/volume1/backup/...`. +- **Обход:** `scp -O` (legacy SCP протокол) использует чистый SSH-channel мимо SFTP-subsystem → даёт доступ ко всему, что shell-пользователь видит. + +## Структура + +- **Volume:** один том `/volume1`, 7.0 TB, ~1.2 TB used до восстановления. +- **/volume1/NetBackup/diskstation_1.hbk** — Hyper Backup репо с мёртвой синки. 430 GB compressed (deduplicated), последняя успешная backup-версия 2026-05-09 05:06. +- **Hyper Backup Vault** установлен как пакет на этой синке (см. [[hyper-backup-structure-and-recovery]]). +- Owner данных в репо — `vitya:users` (POSIX) с ACL под `+`. ACL даёт vitya read, но individual файлы `.bak`/`.acme.json` могут иметь `-rw-------` — для них нужен `chmod -R a+rX` из root SSH. + +## VMM статус + +- Установлен (виден `@SavedVM` в `/volume1/`). +- В сессии 2026-05-18 рассматривался вариант поднять `snolla.ova` прямо здесь через VMM как альтернатива переезду на Windows — отвергнут потому что канал не надёжный. + +## Роль в recovery + +- **Источник всех данных:** OVA, sql дампы, docker volumes (mssql, minio, elasticsearch, imgproxy/nginx) — всё тащилось отсюда. +- **Не было записи на этот NAS** во время recovery — только чтение / Hyper Backup restore во временную папку `/volume1/NetBackup/restore-tmp/`, потом backup-shares `/volume1/backup/`, `/volume1/docker/`, `/volume1/work/`. + +## Гипотеза по будущему backup pipeline + +- Эта синка остаётся как backup target, на ней нет SMR-дисков (тип неизвестен на момент сессии, но кратко проверить через `ls /dev/sd*` + smartctl до тяжёлой нагрузки). +- Будущая [[future-resilient-architecture-goals]]: добавить второй backup target (или облачный — Backblaze B2 / S3 Glacier), чтобы не зависеть от одной коробки. + +## Роль источника для миграции на VDS (2026-05-20) + +В сессии [`vds-kzntsv-bootstrap-2026-05-20`](../sources/vds-kzntsv-bootstrap-2026-05-20.md) kreknin сыграл вторую роль — **источник данных** для миграции инфра-сервисов на [`vds-kzntsv`](vds-kzntsv.md). Из restored backup'а ([Hyper Backup](../concepts/hyper-backup-structure-and-recovery.md) `.hbk` мёртвой синки): + +- **Gitea** — `tar c -C /volume1/docker/gitea data postgres docker-compose.yml | ssh vds tar x` (sudo `Pryakhin9` для read postgres datadir uid 999). 2.7G total за 8 мин. +- **Verdaccio** — `rsync /volume1/docker/personal/verdaccio/{storage,config,plugins} → vds:/opt/stacks/verdaccio/`. 9G за 18 мин. +- **Registry** — GC на kreknin (`registry:2.8.3 garbage-collect -m`) сжал 99G → 35G; затем user принял решение **abandon миграцию** и fresh install на VDS. Старый registry data остаётся на kreknin как backup-reference. + +## Roadmap как backup target для VDS + +Планируется ежедневный pull rsync VDS → kreknin в `/volume1/NetBackup/vds-kzntsv/` (см. follow-up task `.tasks/vds-backup-rsync-kreknin.md`). Дополнительный pipe — backup pipe для production-CMS [`windows-recovery-host`](windows-recovery-host.md) → тут же на kreknin — пока не реализован. diff --git a/.wiki/entities/openwrt-router.md b/.wiki/entities/openwrt-router.md new file mode 100644 index 0000000..5742a45 --- /dev/null +++ b/.wiki/entities/openwrt-router.md @@ -0,0 +1,62 @@ +--- +title: OpenWRT Router (192.168.1.1) +type: entity +tags: [hardware, networking, openwrt, nat, dhcp] +sources: [../sources/nas-recovery-session-2026-05-18.md] +updated: 2026-05-19 +--- + +# OpenWRT Router + +Домашний роутер, через который идёт весь публичный трафик к клиентским сайтам. + +## Hardware / OS + +- **Hardware:** MediaTek MT7622 (aarch64), 6 disk-bay шасси (с роутером не связано) +- **OS:** OpenWRT 23.05.4 (r24012-d8dd03c46f) +- **Uptime:** 13+ дней на момент recovery +- **LAN-IP:** 192.168.1.1 +- **LAN-subnet:** 192.168.1.0/24 +- **WAN-public:** 94.19.247.14 + +## Access + +- SSH: `root@192.168.1.1:22` — ssh-key `id_ed25519_openwrt` установлен в `/etc/dropbear/authorized_keys` +- LuCI web: http://192.168.1.1 +- Конфиг через `uci` (UCI infrastructure) + +## Текущий port forwarding setup (после recovery patch) + +Активные: +- `firewall.@redirect[0]` (SSL): WAN **443** → 192.168.1.143:**4443** (Windows-PC, где traefik) +- `firewall.@redirect[1]` (HTTP): WAN **80** → 192.168.1.143:**8000** (Windows-PC, где traefik) +- `firewall.@redirect[9]` (Wireguard): WAN 48820 → 192.168.1.239 (отдельный хост, не трогали) + +Старые (всё ещё активны, но смотрят на мёртвую синку 192.168.1.10 — на которой ничего нет): +- DSM 5000 → 192.168.1.10:5000 +- FTP 21, SFTP 22, MariaDB 36063, SQLServer 23056, PassiveFTP 55536-55899, Cloud Station 6690, SSH 1322 + +В рамках recovery эти **не отключали** (по решению пользователя). Можно отключить через `uci set firewall.@redirect[N].enabled='0'` для снижения шума атак. + +## DHCP-резервации (актуальные) + +| Хост | IP | MAC | Назначение | +|---|---|---|---| +| `windows-recovery-pc` | 192.168.1.143 | 88:66:5A:2F:AA:68 | [[windows-recovery-host]] | +| `snolla` (исторически) | 192.168.1.15 | 02:11:32:2A:7C:B9 | Раньше — VM мёртвой синки. Сейчас MAC присвоен новой [[snolla-recovery-vm]], но VM в NAT-режиме и LAN-IP не получает. | +| `diskstation` | 192.168.1.10 | 22:06:7C:32:00:6F (+ ...:70) | Мёртвая синка [[dead-synology-diskstation]] | +| Прочие | разное | разное | wled-1, hifiberry, и т.д. — не трогаем | + +## Firewall zones + +- **lan:** input=ACCEPT, output=ACCEPT, forward=ACCEPT (внутри LAN всё открыто) +- **wan:** input=REJECT, output=ACCEPT, forward=REJECT, masq=1 (стандарт) +- LAN→WAN forwarding: ALLOW + +Дополнительные input rules для wan (стандартные OpenWRT): Allow-DHCP-Renew, Allow-Ping, Allow-IGMP, Allow-DHCPv6, Allow-MLD, Allow-ICMPv6-*, Allow-IPSec-ESP. + +## Что bgужно сделать (на потом) + +- Отключить устаревшие redirects на 192.168.1.10 (DSM/FTP/SQL/Cloud Station) — снижает attack surface. +- Запланировать DDNS для случая смены публичного IP (REGRU domains всё ещё указывают на 94.19.247.14). +- При планировании [[future-resilient-architecture-goals]] — добавить **second WAN** (3G/4G/LTE через USB-modem) на роутер? OpenWRT поддерживает multi-WAN. diff --git a/.wiki/entities/snolla-recovery-vm.md b/.wiki/entities/snolla-recovery-vm.md new file mode 100644 index 0000000..23cf322 --- /dev/null +++ b/.wiki/entities/snolla-recovery-vm.md @@ -0,0 +1,94 @@ +--- +title: Snolla Recovery VM (VirtualBox) — savestate'нута 2026-05-21 после 36h успешного soak +type: entity +tags: [vm, virtualbox, windows, iis, cms, recovery, savestate] +sources: [../sources/nas-recovery-session-2026-05-18.md, ../sources/iis-host-migration-2026-05-19.md, ../concepts/iis-migration-2026-05-19-postmortem.md] +updated: 2026-05-21 +--- + +# Snolla Recovery VM + +VirtualBox-VM на [[windows-recovery-host]], в которой работает CMS-стек (IIS + .NET + код CMS). Импортирован из OVA-снапшота 2024-10-27, который лежал в Hyper Backup репо. + +**Статус (2026-05-21 05:13 MSK):** VM **savestate'нута** после ~36h soak attempt 2 миграции (`VBoxManage controlvm snolla-recovery savestate`, 45.6s, VMState=`saved`). Savestate file: `Snapshots\2026-05-21T05-12-43-636491200Z.sav` = 1.73 GB (compressed RAM). VBoxHeadless процессы исчезли — освобождено ~4 GB private memory. Disk usage +1.7 GB. + +Resume в любой момент через `VBoxManage startvm snolla-recovery --type headless` (~30 сек). После соак ещё одной недели — `unregistervm --delete` (освободит ~95 GB на C: — `snolla-disk1.vmdk` 95.8 GB + .sav). + +**Предыстория:** все 11 cms hosts мигрированы на host-IIS:8089 ([[iis-host-migration-2026-05-19]] Phase 10), 36h soak passed без rollbacks (Phase 11), 8/8 наших sites зеленые через full traefik HTTPS chain. VM держалась как parallel fallback (recipe-D из [[iis-migration-2026-05-19-postmortem]]) — fallback не понадобился. + +История: утром 2026-05-19 attempt 1 миграции сломал prod (Docker NAT loop), был revert на VM. Через тот же вечер — attempt 2 по recipe (backend port `:8089` вместо `:80`, smoke `-MaximumRedirection 0`, phone-test не-LAN) — succeeded. Подробности обеих попыток в `iis-host-migration-2026-05-19` Phases 1-10. + +## Параметры + +- **VBox name:** `snolla-recovery` +- **UUID:** `66aac8bb-fe70-4ced-87f6-2291cd0e8b74` +- **Расположение:** `C:\Users\vitya\VirtualBox VMs\snolla-recovery\` +- **OS внутри:** Windows (вероятно Server 2016/2019, hostname `SNOLLA`) +- **RAM:** 4096 MB +- **vCPU:** 2 (после оптимизации [[vbox-windows-stability-tuning]] — было 4) +- **Disk:** `snolla-disk1.vmdk`, max 120 GB, реально ~92 GB на хосте +- **Storage controller:** SATA AHCI (после миграции с SCSI LsiLogic, см. [[vbox-windows-stability-tuning]]) +- **Network:** NAT (после миграции с bridged WiFi из-за нестабильности) +- **Paravirt:** `kvm` (matching исходному гипервизору Synology VMM) +- **OS type:** Windows10_64 (исходно был `Other_64`, поправили для оптимальных дефолтов) +- **Guest Additions:** 7.2.8 r173730, RunLevel=3 (полностью активны) + +## NAT Port Forwards + +| Host port | VM port | Назначение | +|---|---|---| +| 13389 | (console) | **VRDE** (VBox Remote Display) — для отладки, не зависит от Windows RDP | +| 23389 | 3389 | RDP внутри VM (Windows Remote Desktop) | +| 8022 | 22 | SSH (OpenSSH Server в VM) | +| 18080 | 80 | IIS Default — основной HTTP CMS | +| 18180 | 8080 | IIS site `stostayer` | +| 18181 | 8081 | IIS site `stostayer.old` | +| 18189 | 8089 | (запасной) | + +## Учётка + +- **Admin:** vitya (домен SNOLLA) +- **Default shell для sshd:** PowerShell (зарегистрирован в `HKLM:\SOFTWARE\OpenSSH` → `DefaultShell`) +- **Authorized SSH key для admin-users:** `C:\ProgramData\ssh\administrators_authorized_keys` (особое место для admin Windows OpenSSH; permissions через `icacls`, group `Администраторы:F` + `СИСТЕМА:F`) + +## IIS-сайты + +| Site | Path | Bindings | Прим. | +|---|---|---|---| +| **MoreThenCms.Web** | `C:\inetpub\wwwroot\MoreThenCms.Web` | `*:80` | **active prod** — catch-all для 11 главных доменов; traefik backend `host.docker.internal:18080` | +| **Snolla.IdentityManager** | `C:\inetpub\wwwroot\Snolla.IdentityManager` | `*:8089` | публично не используется | +| **stostayer** | `C:\stayer\MoreThenCms.Web` | `*:8080` | **active prod** — traefik backend `host.docker.internal:18180`; conn → внешний `89.253.219.2,1433` (но user в session 2026-05-19 поменял на `www.stostayer.ru,1433` для host-копии; **в VM остался старый**) | +| **stostayer.old** | `C:\stayer\stostayer.old` | `*:8081` | **active prod** — traefik backend `host.docker.internal:18181` | +| **stostayer.old/calc** | `C:\stayer\Mis.StoStayer.Calculator.Web` | (sub-app под `:8081`) | существует, sub-app pool `calc` | +| **stostayer.old/price** | `C:\stayer\Mis.StoStayer.Price.Api` | (sub-app под `:8081`) | существует, sub-app pool `price` | +| **stostayer.old/price/tireService** | `C:\stayer\Mis.StoStayer.TireService.Api` | (sub-app под `:8081`) | существует, sub-app pool `tireService` | + +CMS распознаёт клиента по **Host header** — все 11 клиентских доменов идут на `:80` и роутятся внутри CMS-кода. + +**Важно для следующей попытки миграции:** stostayer Web.config в VM указывает на старый `89.253.219.2,1433`, а на host-копии (`C:\sites\stostayer\Web.config`) уже patched на `www.stostayer.ru,1433` с XML-escape `&` в password. Если когда-то будем сводить эти конфиги — host-копия правильнее (старый сервер мёртв). + +## Web.config — критичные настройки (после recovery patch) + +- **Connection string:** `Data Source=10.0.2.2;Initial Catalog=MoreThenCms;User Id=snolla;Password=fXkH4@8O%3pc;...` + - `10.0.2.2` = NAT gateway в VBox = адрес хоста [[windows-recovery-host]] изнутри VM + - До патча было `Data Source=192.168.1.10` (старая мёртвая синка) + - Тот же пароль `fXkH4@8O%3pc` совпадает с SA-паролем MSSQL контейнера (production password из старого compose) +- **Encoding файла:** UTF-8 with BOM (важно — см. [[cms-config-rewrite-pattern]]) +- 4 файла пропатчены аналогично: `MoreThenCms.Web/Web.config`, `Snolla.IdentityManager/Web.config`, `stostayer.old/web.config`, и stayer-проектов (если применимо) + +## Связь со внешним миром + +- VM в NAT-режиме → не имеет LAN-IP +- Из traefik (на хосте) достижима по `host.docker.internal:18080` → NAT-форвард в Windows → VM:80 +- Раньше (когда было bridged) — VM имела IP `192.168.1.15` с MAC `02:11:32:2A:7C:B9`. snolla.yml в traefik/data/custom/ исходно ссылался на `http://192.168.1.15/` — пропатчен на `host.docker.internal:18080/`. + +## Стабильность + +- Нестабильна на bridged-WiFi → переведена в NAT (стало лучше, но всё равно требует осторожности). +- Один случай (после нескольких часов uptime): network adapter в VM "повис" — все TCP-handshake проходили, но через них трафик не шёл. Лечится `ipconfig /release && /renew` внутри VM через VBoxManage guestcontrol. +- **Долгосрочно**: пора планировать scheduled task внутри VM, который при детекции downtime автоматически перезагружает network adapter / iisreset. Или вообще переезд на Hyper-V — рекомендация Microsoft для Windows-гостей. + +## Известные баги в текущей конфигурации + +- **X-Forwarded-Proto/Host headers** не передаются с traefik в IIS → CMS делает redirect на `http://www.:4443/` (mixing HTTP scheme with HTTPS port). Не критично, но требует фикса. +- **Логи в C:\inetpub\logs\** растут (~6 GB на момент recovery) — нужна ротация. diff --git a/.wiki/entities/vds-kzntsv.md b/.wiki/entities/vds-kzntsv.md new file mode 100644 index 0000000..bc04e71 --- /dev/null +++ b/.wiki/entities/vds-kzntsv.md @@ -0,0 +1,127 @@ +--- +title: VDS kzntsv — Rusonyx 160 NVMe cloud server +type: entity +tags: [hardware, vds, cloud, rusonyx, infrastructure, gitea, verdaccio, registry, postgres, mariadb, mongo, redis] +sources: [../sources/vds-kzntsv-bootstrap-2026-05-20.md] +updated: 2026-05-20 +--- + +# VDS kzntsv + +Облачный VDS у Rusonyx, активирован 2026-05-20. Цель — вынести инфраструктурные сервисы (gitea / verdaccio / docker-registry / shared DBs / в будущем seafile, hermes, ntfy) с одной железной коробки на отдельный host. Это первый шаг по closing SPOF gap из [`future-resilient-architecture-goals`](../concepts/future-resilient-architecture-goals.md). + +Production CMS (MoreThenCms) **остаётся на** [`windows-recovery-host`](windows-recovery-host.md) и обсуждается отдельно. + +## Hardware / tariff + +- **Vendor:** Rusonyx (Astra Облако), https://myvm.rusonyx.ru +- **Tariff:** 160 NVMe (заказан 2026-05-19, активирован 2026-05-20) +- **vCPU:** 6 × 2.6 GHz +- **RAM:** 8 GiB +- **Disk:** 160 GiB NVMe +- **OS:** Ubuntu 24.04 LTS (Noble) +- **IPv4:** 1 шт (free) +- **Backup от Rusonyx:** 0 (свой backup pipeline через `[[vds-backup-rsync-kreknin]]`) + +## Доступ + +- **Public IP:** `89.253.255.94` +- **Vendor hostname:** `vps-21075162-534388.host4g.ru` +- **DNS:** `vds.kzntsv.site` (A → 89.253.255.94) + wildcard `*.vds.kzntsv.site` + service hostnames `git/registry/verdaccio.kzntsv.site` (REGRU) +- **VNC console:** через Rusonyx панель (кнопка «Остановить VNC» в Управление сервером → Консоль может потребоваться при stale attachment — см. [`rusonyx-vps-onboarding-quirks`](../concepts/rusonyx-vps-onboarding-quirks.md)) +- **SSH:** `ssh -i ~/.ssh/id_ed25519 vitya@89.253.255.94` (root login + password auth disabled пост-bootstrap; sudo NOPASSWD для vitya) +- **Креды:** `~/projects/.common/secrets/vds-kzntsv.env` (root initial pass, sudo pass, portainer admin, DB passwords, registry, portainer API key, traefik dashboard basicauth) + +## Software stack + +| Слой | Компонент | Версия | Где | +|---|---|---|---| +| OS | Ubuntu | 24.04.4 LTS | host | +| Kernel | Linux | 6.8.0-117-generic | host | +| Firewall | ufw | active | host (allow 22, 80, 443, 5432, 3306, 27017, 6379) | +| Brute-protect | fail2ban | active (sshd jail) | host | +| Engine | Docker CE | 29.5.1 | host (official APT repo) | +| Compose | docker-compose-plugin | v5.1.3 | host | +| Reverse proxy | Traefik | v2.11 LTS | `/opt/stacks/traefik/` | +| Container mgmt | Portainer CE | 2.21.5 | `/opt/stacks/portainer/` | +| Postgres | postgres | 16 (Debian) | `/opt/stacks/databases/postgres/` | +| MariaDB | mariadb | 11.4 | `/opt/stacks/databases/mariadb/` | +| MongoDB | mongo | 7.0 | `/opt/stacks/databases/mongo/` | +| Redis | redis | 7.4-alpine | `/opt/stacks/databases/redis/` | +| Git | gitea | 1.25.5 | `/opt/stacks/gitea/` | +| NPM | verdaccio | 6 | `/opt/stacks/verdaccio/` | +| Docker registry | registry | 2.8.3 + joxit UI | `/opt/stacks/registry/` | + +## Docker networks (external) + +- `proxy` — traefik + всё что выставляется наружу через HTTPS +- `shared-dbs` — DB-park + любой контейнер, который к DBs ходит по DNS-имени `postgres` / `mariadb` / `mongo` / `redis` + +## Hostnames (live, 2026-05-20) + +| Hostname | Service | Auth | Назначение | +|---|---|---|---| +| `portainer.vds.kzntsv.site` | Portainer | vitya / `Pryakhin9-VDS-2026` (18 chars, см. [`portainer-2.21-admin-password-regression`](../concepts/portainer-2.21-admin-password-regression.md)) | Container management | +| `traefik.vds.kzntsv.site` | Traefik dashboard | basicAuth vitya / Pryakhin9 | Traefik runtime view | +| `git.kzntsv.site` | Gitea | kreknin users restored | Git hosting | +| `verdaccio.kzntsv.site` | Verdaccio | kreknin htpasswd (vitya) | Private npm | +| `registry.kzntsv.site` | Docker Registry | vitya / Pryakhin9 (htpasswd) | Docker images | +| `registry-ui.vds.kzntsv.site` | Joxit Registry UI | (proxied к registry, та же auth) | GUI cleanup | +| `postgres.vds.kzntsv.site:5432` | Postgres TLS | postgres / hex32 | Shared DB | +| `mariadb.vds.kzntsv.site:3306` | MariaDB TLS | root / hex32 | Shared DB | +| `mongo.vds.kzntsv.site:27017` | MongoDB TLS | root / hex32 | Shared DB | +| `redis.vds.kzntsv.site:6379` | Redis TLS | hex32 (requirepass) | Shared cache | + +DB TLS: self-signed certs (CN matches hostname), клиент с `verify-none` / `tlsAllowInvalidCertificates`. Pattern см. [`db-tls-self-signed-via-traefik-raw-tcp`](../concepts/db-tls-self-signed-via-traefik-raw-tcp.md). + +## File layout + +``` +/opt/stacks/ +├── traefik/ +│ ├── data/ +│ │ ├── traefik.yml (static config) +│ │ └── dynamic/ +│ │ └── middlewares.yml (basicAuth для dashboard) +│ ├── letsencrypt/ +│ │ └── acme.json (LE certs, 0600) +│ └── docker-compose.yml +├── portainer/ +│ ├── data/ (portainer.db, chisel keys) +│ └── docker-compose.yml (note: run via `docker run`, не compose, чтобы bypass'нуть env-interp на --admin-password) +├── databases/ +│ ├── postgres/{data,certs,docker-compose.yml} +│ ├── mariadb/{data,certs,docker-compose.yml} +│ ├── mongo/{data,certs,docker-compose.yml} +│ └── redis/{data,certs,docker-compose.yml} +├── gitea/ +│ ├── data/{git,gitea,ssh} (mount → /data в контейнере) +│ └── docker-compose.yml +├── verdaccio/ +│ ├── storage/ (npm packages, 8.6 GB, 2063 packages) +│ ├── config/{config.yaml,htpasswd} +│ ├── plugins/ +│ └── docker-compose.yml +└── registry/ + ├── docker/ (registry blobs storage) + ├── auth/htpasswd + └── docker-compose.yml (registry + registry-ui в одном compose) +``` + +## Что входит в backup pipeline (planned) + +См. [`vds-backup-rsync-kreknin`](../../.tasks/vds-backup-rsync-kreknin.md): daily 05:00 MSK rsync → `kreknin.site:/volume1/NetBackup/vds-kzntsv/` с `--link-dest` incremental. DB dumps первым шагом (`pg_dumpall` / `mariadb-dump` / `mongodump` / `redis-cli --rdb`), потом rsync `/opt/stacks/`. Email-нотификация на `vitya.kuznetsov@gmail.com` через SMTP smtp.yandex.ru:465 (noreply@snolla.com / pass в `noreply-snolla-smtp.env`), плюс [`vds-ntfy-push`](../../.tasks/vds-ntfy-push.md) на Android. + +## Связь с другими сущностями + +- Источник данных для миграции gitea/verdaccio — restored backup на [`kreknin-synology`](kreknin-synology.md) (через tar+ssh-pipe и rsync). Registry — fresh install без миграции старых images (user accepted loss). +- Заменяет старый CMS-инфра-host [`windows-recovery-host`](windows-recovery-host.md) **только для инфраструктурных сервисов** (gitea/verdaccio/registry/DBs); production CMS остаётся на recovery-host. +- Не зависит от [`dead-synology-diskstation`](dead-synology-diskstation.md) (тот мёртв). + +## Open issues / TODO + +- DB TLS = self-signed → нужен LE-cert sidecar (lego watch acme.json → extract PEM → reload DBs). Сейчас клиенты обходятся `verify-none`. [`db-tls-self-signed-via-traefik-raw-tcp`](../concepts/db-tls-self-signed-via-traefik-raw-tcp.md). +- Backup pipeline — TODO ([`vds-backup-rsync-kreknin`](../../.tasks/vds-backup-rsync-kreknin.md)). +- GC cron для verdaccio + registry — TODO ([`vds-gc-cron`](../../.tasks/vds-gc-cron.md)). +- ntfy push — TODO ([`vds-ntfy-push`](../../.tasks/vds-ntfy-push.md)). +- Hermes — defer, ждёт уточнения user. diff --git a/.wiki/entities/windows-recovery-host.md b/.wiki/entities/windows-recovery-host.md new file mode 100644 index 0000000..a591b65 --- /dev/null +++ b/.wiki/entities/windows-recovery-host.md @@ -0,0 +1,91 @@ +--- +title: Windows Recovery Host (рабочий PC пользователя) +type: entity +tags: [hardware, windows, docker, virtualbox, iis, recovery] +sources: [../sources/nas-recovery-session-2026-05-18.md] +updated: 2026-05-19 +--- + +# Windows Recovery Host + +Личный Windows-PC пользователя, который во время recovery стал production-сервером для всех клиентских сайтов. + +## Hardware / OS + +- **Hostname:** DESKTOP-NSEF0UK +- **OS:** Windows 11 Pro (предположительно — поддерживает Hyper-V, IIS, .NET Framework) +- **LAN-MAC:** 88:66:5A:2F:AA:68 (Broadcom 802.11ac WiFi) +- **LAN-IP:** 192.168.1.143 (DHCP-резервация на [[openwrt-router]]) +- **Диск C:** ~700 GB total, на старте recovery ~352 GB free, после — ~150 GB free. +- **Юзер:** vitya (admin) + +## Установленный стек + +- **.NET Framework:** 4.8.1 +- **IIS** (W3SVC, на 80, мы планировали остановить — но не остановили, traefik на 8000/4443 не конфликтует) +- **Docker Engine 29.3.1** (Docker Desktop с WSL2 backend) +- **VirtualBox 7.2.8** (установлен в сессии 2026-05-18, через winget) +- **OpenSSH client** (для ssh/scp к kreknin и VM) +- **FileZilla client** (для пользовательских SFTP-перетаскиваний) + +## Сетевое положение + +- За **OpenWRT 23.05.4** [[openwrt-router]] +- Соединение с интернетом через **WiFi** (Broadcom 802.11ac, 288 Mbps) +- За **VLESS-клиентом v2rayN** (роутер default-route шёл через VPN, пришлось настроить **Bypass LAN** правило с `geoip:private` → direct, иначе входящие 80/443 терялись через asymmetric routing) + +## Что хостит сейчас (после attempt 2 успешной миграции на host-IIS, 2026-05-19 вечер) + +**Active prod:** + +| Что | Где | Порт (host) | Прим. | +|---|---|---|---| +| **Native IIS — site `snolla`** | `C:\sites\snolla` (pool `snolla`, .NET v4.0 Integrated, `ApplicationPoolIdentity`) | `*:80`, `*:8089` | **active prod** — catch-all для 11 cms hosts; traefik backend `host.docker.internal:8089` | +| **Native IIS — site `stostayer`** | `C:\sites\stostayer` (pool `stostayer`) | `*:8090` | local-only, traefik route `.yml.disabled` (user: «внутренний, наружу не светить») | +| **Native IIS — site `stostayer.old`** | `C:\sites\stostayer.old` (pool `stostayer.old`) | `*:8091` | local-only, traefik route `.yml.disabled` | +| **traefik 2.6.6** | Docker, network `proxy` | 8000 (http), 4443 (https), 8080 (dashboard) | 11 cms routes → host IIS:8089; 2 stayer routes DISABLED; 3 infra routes | +| **MSSQL 2019** | Docker, named volume `mssql_mssql_data` | 1433 | 5 production DB | +| **MinIO** | Docker, bind-mount `./data` | 9000 | | +| **Elasticsearch 7.10.1** | Docker, bind-mount `./data` | 9200 | books-стек, не CMS | +| **imgproxy** | Docker | 8787 | | +| **imgproxy-nginx** | Docker | 8788 | | + +**Parallel fallback (running, без traffic):** + +| Что | Где | Порт (host) | Прим. | +|---|---|---|---| +| **VirtualBox `snolla-recovery` VM** | `C:\Users\vitya\VirtualBox VMs\snolla-recovery\` | NAT 13389/23389/8022/18080/18180/18181/18189 | parallel fallback на 24-48h soak; затем savestate; см. [[snolla-recovery-vm]] | + +**Прочие inert:** + +| Что | Где | Прим. | +|---|---|---| +| **`C:\sites\snolla-identity-manager\`** | папка без IIS-сайта | deploy-артефакт, не активен | +| **traefik backups** | `data/custom/*.yml.bak-*-2026-05-19` (5 серий) | atomic-revert artefacts; `.bak-pre-attempt2-2026-05-19` — baseline текущей prod conf | + +`Default Web Site` stopped (`autoStart=false`). URL Rewrite + ARR **не установлены**. + +## Ключевые папки + +- `C:\Users\vitya\projects\docker\diskstation\` — compose'ы и данные docker-стеков + - `mssql/`, `minio/`, `elasticsearch/`, `imgproxy/`, `traefik/` + - `traefik/data/custom/*.yml` — file-provider routes для всех 13 client доменов + ES/MinIO/imgproxy +- `C:\Users\vitya\VirtualBox VMs\snolla-recovery\` — VM home, **active prod** (running) +- `C:\nas-recovery\backup\snolla\snolla.ova` — оригинал OVA (45.6 GB, для повторного импорта если что) +- `C:\nas-recovery\vm-sites\wwwroot\`, `C:\nas-recovery\vm-sites\stayer\` — резервная копия IIS-сайтов из VM (использована для миграции на хост; пока хранится как safety net) +- `C:\sites\` — **inert**, готов для следующей попытки миграции (см. [[iis-migration-2026-05-19-postmortem]]): + - `snolla\` — Web.config patched (sitePath + conn → localhost) + - `stostayer\` — Web.config patched (conn → `www.stostayer.ru,1433` с XML-escape `&`) + - `stostayer.old\` — Web.config patched (conn → localhost) + - `snolla-identity-manager\` — deploy-артефакт, IIS-сайта нет +- `C:\Users\vitya\projects\MoreThenCms\` — git-репо с исходниками CMS + +## SSH-ключи на этой машине + +- `~/.ssh/id_ed25519_kreknin` — для [[kreknin-synology]] (vitya@195.19.90.188) +- `~/.ssh/id_ed25519_openwrt` — для [[openwrt-router]] (root@192.168.1.1) +- `~/.ssh/id_ed25519_snolla_vm` — для [[snolla-recovery-vm]] (vitya@127.0.0.1:8022, в admin-keys VM) + +## Что должно случиться, если этот PC погаснет + +- **Всё** — все сайты лягут. **Single point of failure** — главное замечание для [[future-resilient-architecture-goals]].