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

9.6 KiB
Raw Blame History

title, type, tags, ingested, raw_path, updated
title type tags ingested raw_path updated
NAS Recovery Session 2026-05-18/19 source
recovery
nas
synology
virtualbox
traefik
mssql
minio
elasticsearch
2026-05-19 ../../.tasks/nas-recovery.md 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.10Data 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.15host.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 — на потом.