Files
admin/.wiki/sources/nas-recovery-session-2026-05-18.md
vitya 98bcc37d32 import: .wiki/sources/ from MoreThenCms via subtree-split
git-subtree-dir: .wiki/sources
git-subtree-mainline: d25c0577c8
git-subtree-split: a5e96432bc
2026-05-21 13:46:39 +03:00

79 lines
9.6 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.
---
title: NAS Recovery Session 2026-05-18/19
type: source
tags: [recovery, nas, synology, virtualbox, traefik, mssql, minio, elasticsearch]
ingested: 2026-05-19
raw_path: ../../.tasks/nas-recovery.md
updated: 2026-05-19
---
# NAS Recovery Session 2026-05-18/19
15-часовая сессия восстановления клиентских сайтов после краха NAS Synology, на котором они хостились. Источник истины — лог переписки восстановления + `.tasks/nas-recovery.md`. Здесь сжатая хронология; конкретные паттерны и решения распилены по `concepts/`, инфраструктурные сущности — по `entities/`.
## Контекст до краха
- **Source NAS (теперь мёртвый):** Synology DiskStation на XPEnology (самосборное x86 железо + DSM через community-loader). На нём:
- VMM (Virtual Machine Manager) → Windows-VM **snolla** с IIS + .NET Framework 4.8 CMS [[snolla-recovery-vm]]
- Container Manager → docker-стек: MSSQL Server 2019, MinIO 2020-07-13, Elasticsearch 7.10.1, imgproxy+nginx, traefik 2.6.6, gitea, и др.
- 11 клиентских сайтов под одной VM (snolla.com + 10 client TLDs: rimiz.ru, labtools.pro/ru, pilorama98.ru, tandemmebel.ru, emspb.ru, kupimknigi.spb.ru, maljarka.tandemmebel.ru, sestech.ru, ics-artmaterials.com)
- **Backup target NAS (живой):** [[kreknin-synology]] на 195.19.90.188 / kreknin.site, держит Hyper Backup репо.
- **Бэкап-задача:** "rsync Server 1", последняя успешная — 2026-05-09 05:06 (за 9 дней до краха).
См. также: [[dead-synology-diskstation]], [[wd40efax-smr-cascade]].
## Хронология
**2026-05-18 ~17:00 MSK:** инцидент — второй из 3 дисков RAID 5 на mёртвой синке вышел из строя. Пул past redundancy. Diagnose см. [[wd40efax-smr-cascade]].
**~17:30:** оценка вариантов. Выбран маршрут "восстановление на локальной Windows-машине пользователя" ([[windows-recovery-host]]) с гибридной архитектурой: VM для CMS (из OVA-экспорта) + docker-контейнеры для backend-сервисов.
**~18:00:** SSH-доступ к [[kreknin-synology]] (изначально по паролю, потом через ssh-ключ). Разбор структуры `.hbk` репо. См. [[hyper-backup-structure-and-recovery]].
**~19:00:** старт Hyper Backup restore через DSM UI на удалённой синке во временную папку `/volume1/restore-tmp/`. Restore инициировал также создание новых шар `backup/`, `docker/`, `work/` на root уровне `/volume1/`. Длительность ~3 часа на 277 GB selective набор.
**~21:00 — параллельно:**
- SFTP-pull `snolla.ova` (42.5 GB) на Windows — через FileZilla (SFTP сервис DSM требовалось включить отдельно, ACL/chroot нюансы).
- Локальная подготовка: установлены IIS, VirtualBox 7.2.8.
- На Windows запущен MSSQL контейнер 2019-latest пустым (для отладки compose).
- v2rayN на Windows: настроены routing rules "Bypass LAN" (`geoip:private` → direct), иначе VPN ловил inbound 80/443 traffic.
**~22:00:** найден `MoreThenCms202605090301.zip` — ежедневный `.sql` дамп БД (101 MB compressed, 547 MB unpacked). Попытка restore через `sqlcmd -i` — упала на строке 457k из-за `$(function(){...})` в данных (jQuery JS в email-template таблицах). Sqlcmd интерпретировал `$()` как переменную. См. [[mssql-restore-pitfalls]].
**~23:00:** повторный sqlcmd с флагом `-x` (disable var substitution). Параллельно pull `/docker/personal/mssql/` (25 GB) как альтернатива — через ACL-fix `chmod -R a+rX`, потом `scp -O` (legacy SCP, обход chrooted SFTP).
**2026-05-19 ночь (Claude автономно):**
- OVA import в VirtualBox завершился (42.7 мин)
- sqlcmd v2 длился ~2.5 часа, тоже падал.
- Решение: **bind-mount проблемы → named volume + `chown -R 10001:0`** через temp alpine container. Это сработало. См. [[mssql-container-data-restore]].
- Имя dead synology в БД-файлах было всё с одинаковым паролем `fXkH4@8O%3pc` (production SA password из старого `docker-compose.yml`). Аккаунт `sa` оказался **disabled**, потребовался `mssql-conf set-sa-password` под `--user 0:0` (root) → re-enable.
**~02-08:00 утра:** VM на VBox не загружалась. Кросс-гипервизорный crash. См. [[vbox-windows-stability-tuning]] — путь к стабильности через SCSI→SATA, отключение Hyper-V driver в Safe Mode, `--paravirtprovider kvm`, OS type Windows10_64, Guest Additions.
**~09:30:** VM стабилизирована. Network drama #1: bridged через WiFi нестабильно (promiscuous mode проблемы у WiFi-адаптера). Switched VM nic1 на NAT + port forwarding в VBoxManage: host:23389→VM:3389, host:8022→VM:22, host:18080→VM:80, host:18180→VM:8080, host:18181→VM:8081, host:18189→VM:8089.
**~10:00:** OpenSSH server установлен внутри VM. SSH-ключ для Claude в `C:\ProgramData\ssh\administrators_authorized_keys` (особая локация для admin-users, локализованная группа `Администраторы` через icacls). Default shell sshd переключен на PowerShell.
**~10:30:** Web.config-патч во всех 4 сайтах VM: `Data Source=192.168.1.10``Data Source=10.0.2.2` (VBox NAT gateway = host). Encoding ловушка: `Set-Content` без `-Encoding utf8` записал UTF-16 LE — IIS вернул 500.19 invalid XML. Fix: `[System.IO.File]::WriteAllText` с `UTF8Encoding($true)` (BOM). См. [[cms-config-rewrite-pattern]].
**~11:00:** Traefik 2.6.6 запущен на хосте. Полный цикл правок: `--configFile=/traefik.yml` явно (не находил автоматом), named volume для `letsencrypt/` (bind-mount показывал `0777` Linux-side, traefik требует `0600`), 13 custom yml файлов пропатчены `192.168.1.15``host.docker.internal:18080`. docker.sock провайдер не работал (Docker Desktop особенности) → minio/imgproxy/elasticsearch traefik-labels переписаны как file-provider в `data/custom/`. См. [[traefik-on-windows-docker-desktop]].
**~11:30:** OpenWRT [[openwrt-router]] на 192.168.1.1: DHCP-резервация Windows-PC на 192.168.1.143 (его MAC 88:66:5A:2F:AA:68), port forwards 80→8000 и 443→4443 (host:8000/4443 ↔ traefik). VM получила старый MAC `02:11:32:2A:7C:B9` из DHCP-резервации `snolla` — IP 192.168.1.15 сохранился для совместимости с `snolla.yml` (но потом перешли на NAT, IP стал внутренним).
**~12:00:** Public test через домен/чужой WiFi: **`https://snolla.com`, `https://pilorama98.ru`, `https://labtools.ru`, `https://labtools.pro`, `https://tandemmebel.ru`, `https://emspb.ru`, `https://kupimknigi.spb.ru`, `https://maljarka.tandemmebel.ru` отвечают `200 OK` end-to-end.** Recovery functionally complete.
## После полного recovery — резервный pull
В фоне на Windows: tar+ssh stream `C:\inetpub\wwwroot\` (8.9 GB) и `C:\stayer\` (2.27 GB) из VM в `C:\nas-recovery\vm-sites\` — как фолбэк если VM снова станет нестабильной (был один случай glitch network — лечился `ipconfig /release /renew` через `VBoxManage guestcontrol`).
## Открытые вопросы / нюансы
- **X-Forwarded-Proto/Host headers** между traefik и CMS не настроены → CMS делает redirect с `:4443` в URL.
- **MinIO / Azure storage** в CMS: connection string использует Azure SDK (AccountName=snolla, AccountKey=...), но в production реально работало с MinIO. Точная схема "не так, как казалось" по словам пользователя — ждёт пояснения.
- **acme.json renewal через HTTP-01** фейлится для доменов с DNS не на нашем IP. Решение — DNS-01 через REGRU (creds в `traefik/docker-compose.yml` env уже, в `traefik.yml` закомментировано).
- **VM long-term stability**: один случай network glitch уже был. Возможна планка scheduled task внутри VM — auto release/renew при детекции downtime.
## Архитектурное замечание
Сохранение работающей конфигурации не равно отказоустойчивости. Текущая инфраструктура [[recovery-architecture-snapshot]] сильнее, чем была (Hyper Backup проверен, восстановление практикой), но **single-point-of-failure всё ещё есть**: один Windows-PC, одна VM, один публичный IP, один роутер. Глобальная задача [[future-resilient-architecture-goals]] — на потом.