Копии виртуальных машин¶
BombVault копирует виртуальные машины KVM/libvirt без монтирования какого-либо пути libvirt. Он запускает virsh на хосте по SSH (qemu+ssh://), читает и пишет диски виртуальных машин через монтирование Host Data (/mnt на хосте — это /host/user в контейнере) и копирует UEFI NVRAM по SSH. Поскольку ничто, принадлежащее libvirt, не монтируется, BombVault никогда не может помешать VM Manager в Unraid.
Это руководство охватывает настройку, методы копирования, виртуальные машины со снимками Unraid и TrueNAS SCALE. Копиям контейнеров ничего из этого не нужно.
Копии наборов данных ZFS используют то же SSH-соединение, с тем же ключом, хостом и пользователем. Как только копии виртуальных машин подключаются, подключаются и записи наборов данных ZFS. См. Наборы данных ZFS.
Что вы настраиваете¶
| Настройка | Где | По умолчанию | Значение |
|---|---|---|---|
Host SSH: Address (LIBVIRT_HOST) |
переменная шаблона | host.docker.internal |
Хост Unraid, к которому обращаются по SSH |
Host SSH: Port (LIBVIRT_SSH_PORT) |
переменная шаблона | 22 |
Порт SSH в Unraid |
Host SSH: User (LIBVIRT_SSH_USER) |
переменная шаблона | root |
Пользователь SSH на хосте |
| Открытый ключ | Настройки, Интеграции, SSH хоста | создаётся при первом запуске | Авторизуйте его на хосте |
BombVault создаёт свою пару ключей SSH при первом запуске в /config/ssh/id_ed25519, она хранится в appdata. Ключ хоста закрепляется в /config/ssh/known_hosts при первом подключении.
Шаблон заполняет Host SSH: Address заглушкой 192.168.x.x. BombVault считает её незаданной и пробует host.docker.internal, что работает в сети bridge по умолчанию. В пользовательской сети замените её на IP хоста в локальной сети (шаг 3 Б).
Шаг 1: включите SSH на хосте Unraid¶
- В Unraid откройте Settings, Management Access и задайте Use SSH значение Yes.
- Если вы меняли порт SSH, запомните его. Host SSH: Port должен совпадать.
Шаг 2: авторизуйте открытый ключ BombVault¶
/root в Unraid живёт в памяти и очищается при каждой загрузке, поэтому ключ должен лежать ещё и на флешке. Выполните это в терминале Unraid:
K=$(docker exec BombVault cat /config/ssh/id_ed25519.pub)
mkdir -p /root/.ssh /boot/config/ssh && chmod 700 /root/.ssh
grep -qxF "$K" /root/.ssh/authorized_keys 2>/dev/null || echo "$K" >> /root/.ssh/authorized_keys
grep -qxF "$K" /boot/config/ssh/root.pubkeys 2>/dev/null || echo "$K" >> /boot/config/ssh/root.pubkeys
chmod 600 /root/.ssh/authorized_keys
Unraid 6.9 и новее при каждой загрузке копируют /boot/config/ssh/root.pubkeys в authorized_keys пользователя root, так что это переживает перезагрузки. Это действует для любого входа root, какие бы имя хоста или порт ни использовал BombVault.
Шаг 3: сеть¶
BombVault должен открыть TCP-соединение от контейнера к порту SSH хоста. Выберите случай, который подходит вашей настройке.
А. BombVault в сети bridge по умолчанию¶
- Оставьте Host SSH: Address равным
host.docker.internalили заглушке шаблона. Шаблон добавляет--add-host=host.docker.internal:host-gateway, что указывает на шлюз docker0, то есть на хост. - Задайте Host SSH: Port равным вашему порту SSH.
Б. BombVault в пользовательской сети¶
Контейнер в br0.x, macvlan или ipvlan не может достать до хоста через host.docker.internal, потому что 172.17.0.1 — это docker0, недоступный из br0.x. Вместо этого:
- В Unraid задайте Settings, Docker, Host access to custom networks значение Enabled.
- Задайте Host SSH: Address равным IP хоста Unraid в локальной сети, то есть адресу, по которому вы открываете веб-интерфейс.
- Если сеть контейнера и хост находятся в разных VLAN, разрешите маршрут на роутере или файрволе: из VLAN контейнера к IP хоста на порт SSH по TCP.
- Если IP хоста в локальной сети всё равно недоступен, используйте IP-шим хоста в подсети контейнера. Найдите его на хосте командой
ip -4 addr show | grep -B2 <container-subnet>.
Проверьте, что хост отвечает¶
Выполните это в терминале Unraid с вашим IP и портом:
docker exec BombVault timeout 6 bash -c 'echo > /dev/tcp/192.168.1.10/22' && echo OPEN || echo UNREACHABLE
OPEN означает, что путь работает. UNREACHABLE означает, что сеть из шага 3 нужно починить, прежде чем делать что-либо ещё.
Шаг 4: задайте переменные и проверьте¶
- В Unraid откройте Docker, нажмите BombVault, выберите Edit, задайте Host SSH: Address (и Host SSH: Port, если он не 22) и нажмите Apply. Если переменных нет, импортируйте шаблон заново, потому что Unraid хранит сохранённую конфигурацию существующего контейнера.
- В BombVault откройте Настройки, Интеграции, SSH хоста и нажмите Проверить соединение. Оно должно стать зелёным.
Тот же вызов из терминала перечисляет ваши виртуальные машины:
docker exec BombVault virsh -c "qemu+ssh://root@192.168.1.10:22/system?keyfile=/config/ssh/id_ed25519&known_hosts=/config/ssh/known_hosts&known_hosts_verify=auto" list --all
Шаг 5: метод для каждой виртуальной машины¶
У каждой виртуальной машины есть Метод в карточке ВМ на её вкладке «Настройки» (откройте виртуальную машину в разделе Резервные копии):
- Graceful (выключение) используется по умолчанию. Он выключает виртуальную машину, копирует диски и запускает её снова, так что копия всегда согласованная. Он ждёт до десяти минут, пока гость выключится, и никогда не выключает его принудительно. Гость, который после этого всё ещё работает, остаётся как есть, а копия завершается ошибкой с причиной. Если гость выключится в течение следующего часа, BombVault запустит его снова. Если этот запуск не удастся, неудавшийся запуск копии об этом сообщит.
- Живой снимок копирует работающую виртуальную машину через внешний снимок и
blockcommit. Нужен диск на/mnt/cacheили/mnt/diskX, а не на/mnt/user. С гостевым агентом qemu в виртуальной машине снимок согласованный (quiesced), а без него он согласован лишь на уровне сбоя (crash-consistent). У выключенной виртуальной машины живой режим сам переключается на Graceful. Когда снимок сделать не удаётся, эта копия завершается ошибкой, а виртуальная машина продолжает работать, потому что виртуальную машину, которую вы решили копировать вживую, ради этого никогда не выключают.
Что копия не включает¶
Копия может пройти успешно и всё же содержать не всю виртуальную машину. Тогда у запуска есть заметка с предупреждением, которая называет, чего не хватает:
- Диски, которые BombVault не читает. Диск только для чтения,
lun, а также дискnetworkилиvolumeпропускаются, и заметка называет каждый из них с целевым устройством и типом. Определение в копии их по-прежнему перечисляет. Cdrom и флоппи-дисковод не называются. Обычное блочное устройство, которое не является zvol ZFS, вместо этого приводит к ошибке копии. - Состояние эмулируемого TPM. У него нет пути в XML домена. Unraid VM Manager настраивает такой TPM для виртуальной машины с BIOS OVMF TPM, поэтому заметка появляется и в Unraid. Гость, который хранит секрет в своём TPM, как это делает BitLocker, может после восстановления без этого состояния спросить свой ключ восстановления, так что держите этот ключ под рукой.
Тонкие диски¶
Восстановление сохраняет тонкий диск тонким, заменяет ли оно диск или пишет новый: restic записывает последовательности нулей как дыры в новом файле, а BombVault после записи возвращает нулевые блоки заменённого файла через fallocate --dig-holes. Пока restic заменяет файл, этот файл занимает полный размер, если на пуле хватает места. На файловой системе без пробивания дыр диск остаётся полного размера, и журнал об этом сообщает. Проверка свободного места по-прежнему считает новый диск по полному размеру.
Неудавшееся восстановление¶
Восстановление на месте выключает виртуальную машину, записывает диски, а определение и NVRAM заменяет только после того, как диски записаны. Неудавшееся восстановление оставляет виртуальную машину определённой вместе с её NVRAM. Если её диски не изменились и она работала, она запускается снова. Если они могли измениться, она остаётся выключенной, потому что загрузка с наполовину записанного диска писала бы поверх него, и запуск об этом сообщает. Повторное восстановление той же копии доводит дело до конца.
Снимки, зарегистрированные в libvirt (Unraid VM Manager делает снимки по-другому), останавливают восстановление на месте до того, как виртуальная машина будет затронута, потому что libvirt не может удалить виртуальную машину, у которой они есть. Сначала удалите их.
Только изменённые блоки¶
Виртуальную машину с дисками qcow2 можно копировать, читая только изменившееся. Включите Только изменённые блоки в той же карточке, и BombVault использует API копирования libvirt вместо метода выше:
- Он запускает задачу копирования в режиме pull (
virsh backup-begin), которая в тот же момент создаёт контрольную точку с именемbombvault-<time>, и читает диски по SSH-соединению через проброшенный сокет Unix. Когда гостевой агент отвечает, файловые системы гостя замораживаются только на время запуска задачи. Размораживание, которое не удалось, пробуется снова около пятнадцати секунд, а если гость всё равно не размораживается, BombVault отправляет уведомление. - Первый запуск читает все выделенные блоки. Последующие читают только блоки, которые битовая карта контрольной точки отмечает как записанные после предыдущей копии.
- Каждый диск хранится как папка сегментов фиксированного размера с тем, что видит гость. Неизменённые сегменты берутся из предыдущего снимка без чтения, так что каждый снимок полный и восстанавливается сам по себе.
- Восстановление собирает диск из его сегментов и преобразует обратно в qcow2 через
qemu-img. Диск имеет то же содержимое, что и в момент копирования, но файл новый, qcow2, а цепочка базовых образов возвращается сплющенной. - Проверка перед таким восстановлением перечисляет каждый диск, который он пересобирает, и считает его в полном размере гостя, дважды для qcow2, поскольку сырой образ и его преобразованная копия лежат рядом, пока старый файл не заменён. Это максимум, который может занять диск, так что нехватка по этому счёту делает строку места серой, а не блокирует. Проверка восстановления после первой копии и Проверить восстановление также убеждаются, что снимок содержит каждый сегмент каждого диска нужного размера.
- Между запусками у виртуальной машины в libvirt нет записанной контрольной точки. BombVault хранит определение новейшей контрольной точки
bombvault-в/config/vm-checkpointsи удаляет только запись libvirt о ней (virsh checkpoint-delete --metadata). Её битовая карта остаётся в файле qcow2 и продолжает считать записи, а следующий запуск возвращает контрольную точку на место (virsh checkpoint-create --redefine) перед началом. libvirt отказывается удалять определение виртуальной машины с контрольными точками, и именно это позволяет Remove VM в Unraid и восстановлению работать как обычно. - Задача копирования, которую BombVault оставил работающей, потому что остановился посреди копирования, завершается, когда BombVault запускается снова, вместе с контрольными точками, которые этот запуск оставил записанными.
- Выключение переключателя, исключение виртуальной машины из расписания или удаление её копий тоже завершает такую задачу и, пока виртуальная машина работает, удаляет и битовую карту. На выключенной виртуальной машине libvirt не может её удалить, и она остаётся в образе неиспользуемой.
- Контрольные точки других инструментов остаются нетронутыми. Виртуальную машину, у которой они есть, нельзя восстановить, пока их не удалят, и восстановление останавливается, не коснувшись виртуальной машины.
Переключатель сам отступает. Отсутствующая или сломанная контрольная точка, диск, изменивший размер, или новейший снимок, не относящийся к изменённым блокам, означает, что весь диск читается ещё раз. Выключенная виртуальная машина, сырой диск или zvol, отсутствие SSH-соединения с хостом, libvirt без API копирования или слишком мало места в /config означают обычную копию методом выше. Карточка говорит, что из этого использовал последний запуск и почему.
Требования: libvirt с API копирования (проверено с libvirt 12.2 и QEMU 10.2 в Unraid 7.3), sshd с AllowStreamLocalForwarding yes (по умолчанию, в Unraid тоже, где отключена переадресация TCP) и диски qcow2. libvirt отказывается создавать контрольные точки на сырых дисках, а Unraid по умолчанию создаёт сырые vdisk. Виртуальная машина продолжает работать во время копирования, как при живом режиме, а сегменты, ждущие restic, занимают до 4 ГиБ в /config.
Виртуальные машины со снимками Unraid¶
Снимок, который делает VM Manager в Unraid, превращает диск qcow2 в цепочку: исходный образ внизу, а поверх него по одному файлу на снимок, в каждом только то, что изменилось после лежащего под ним. Виртуальная машина пишет в самый новый файл. Диск с двумя снимками — это три файла.
BombVault копирует такую виртуальную машину целиком:
- Каждый файл цепочки. Он идёт по цепочке базовых образов каждого диска до конца и копирует каждый файл в ней вместе со списком снимков Unraid (
/etc/libvirt/qemu/snapshotdb/<vm>/snapshots.db, читается по SSH). Цепочка, которую нельзя пройти до конца, например потому что файл посередине пропал, проваливает копию и называет файл. - Живая копия сохраняет снимки. Живой снимок кладёт сверху временный слой, пока читает диск, а потом сливает его обратно, только в образ прямо под ним. После копии цепочка такая же, как до неё. Виртуальная машина без снимков ведёт себя как всегда.
- Восстановление возвращает цепочку. Восстановление на месте записывает каждый файл туда, где он был, и возвращает список снимков Unraid, так что VM Manager снова перечисляет снимки. Восстановление рядом с оригиналом записывает файлы в папку копии и направляет восстановленные диски на восстановленные файлы, так что копия никогда не читает из образов оригинала. Список снимков Unraid возвращается только при восстановлении на месте, потому что он называет файлы там, где они были скопированы. Без него копия загружается так же, а VM Manager просто не перечисляет для неё снимков.
- Только изменённые блоки читает то, что видит гость, поэтому его восстановление возвращается одним сплющенным файлом qcow2 без снимков.
- Восстановление возвращает диск выбранной вами копии. Снимки, сделанные или слитые после этой копии, этого не меняют. Копия, сделанная до снимка, определяет виртуальную машину на файле, который в ней есть, а копия, сделанная до слияния, возвращает свой слой и работает на нём. Более новые файлы остаются на месте, неиспользуемые и неизменённые. Копия, в которой есть слой, но нет файла под ним, отклоняется до того, как виртуальная машина будет затронута. После восстановления определение виртуальной машины не перечисляет цепочку, так что libvirt читает её из восстановленных файлов.
Пример: виртуальная машина с двумя снимками¶
У виртуальной машины homeassistant один диск, vdisk1.qcow2, и два снимка, которые вы сделали в VM Manager перед двумя обновлениями. Теперь её диск — цепочка из трёх файлов. Она работает всё время, поэтому использует Живой снимок.
- Откройте Резервные копии, затем
homeassistant, затем её вкладку Настройки. В карточке ВМ проверьте, что Метод равен Живой снимок, а Только изменённые блоки выключено. - Нажмите Создать резервную копию в шапке страницы.
- Когда запуск завершён, его строка в Последние запуски на вкладке Проверка зелёная. Виртуальная машина всё время продолжала работать, а копия содержит все три файла диска и список снимков Unraid.
- В VM Manager оба снимка по-прежнему на месте, а диск по-прежнему читается через те же три файла.
Через месяц обновление идёт не так, и вы хотите вернуть вчерашнее состояние рядом со сломанным, чтобы сравнить:
- Откройте Восстановление, выберите Виртуальные машины и щёлкните
homeassistant. - Оставьте рекомендуемую копию прошлой ночи и выберите Рядом с оригиналом в Куда.
- Нажмите Восстановить. Три файла ложатся в папку с именем виртуальной машины и
-restored, а восстановленный диск указывает на восстановленные файлы. Работающая виртуальная машина не меняется.
Чтобы откатить всю виртуальную машину, выберите Заменить оригинал с включённым Сначала сделать копию текущего состояния. BombVault скопирует сломанное состояние, выключит виртуальную машину, запишет обратно три файла и список снимков Unraid и запустит её снова.
TrueNAS SCALE¶
Шаги выше написаны для Unraid, но то же соединение qemu+ssh:// работает с любым libvirtd, до которого может достать контейнер, включая TrueNAS SCALE, где виртуальные машины снова работают на libvirt начиная с 25.04.2. В TrueNAS строку подключения нужно переопределить, а ключ добавляется пользователю root в собственных настройках пользователей TrueNAS. Ещё три вещи меняют то, что содержит копия: диски на zvol, состояние vTPM и имена, которые TrueNAS даёт своим виртуальным машинам.
1. Сокет libvirt¶
libvirtd в TrueNAS слушает не там, где ожидает строка подключения, построенная из полей SSH хоста. Задайте вместо этого LIBVIRT_URI с дополнительным параметром ?socket=:
BombVault использует LIBVIRT_URI в точности как записано, и LIBVIRT_HOST, LIBVIRT_SSH_USER и LIBVIRT_SSH_PORT не нужны. Для каждой из них, которая не задана, BombVault берёт хост, пользователя и порт из URI и для собственных команд SSH, так что копирование NVRAM и копии наборов данных ZFS достают до той же машины, что и virsh. Переменная, которую вы задали сами, всегда главнее, а журнал загрузки называет цель, которую взял из URI. В TrueNAS пользователю, отличному от root, для копий наборов данных ZFS нужен ещё zfs allow <user> snapshot,destroy,mount <dataset>, см. Наборы данных ZFS.
Впишите в URI адрес TrueNAS в локальной сети. Если не заданы ни LIBVIRT_URI, ни LIBVIRT_HOST, BombVault берёт шлюз приложения по умолчанию как хост, потому что host.docker.internal в приложении TrueNAS не разрешается, а журнал загрузки называет выбранный адрес. Для копий наборов данных ZFS этого достаточно. Для копий виртуальных машин по-прежнему нужен URI для сокета.
Для копий виртуальных машин приложению нужна возможность SETPCAP вместе с CHOWN, DAC_OVERRIDE, FOWNER, SETGID и SETUID. Без неё libvirt останавливается с ошибкой «cannot apply process capabilities». YAML в разделе TrueNAS SCALE задаёт их все вместе с SYS_CHROOT, который нужен для снимка вместо остановки.
В TrueNAS SCALE 25.10.0 путь к сокету проверен на настоящем оборудовании: стандартный qemu:///system завершается ошибкой Failed to connect socket to '/var/run/libvirt/libvirt-sock': No such file or directory, а тот же вызов с ?socket=/run/truenas_libvirt/libvirt-sock перечисляет домены.
2. Ключ BombVault в TrueNAS¶
Шаг 2 выше пишет на флешку Unraid и здесь не применим. В TrueNAS:
- Включите службу SSH в System, Services.
- В Credentials, Users измените root и вставьте открытый ключ BombVault из Настройки, Интеграции, SSH хоста как его открытый ключ SSH. TrueNAS сохраняет его при перезагрузках и обновлениях.
Свежие установки TrueNAS 24.10 и новее не дают root пароля, а для входа по ключу он не нужен. Если вы предпочитаете не использовать root, авторизуйте ключ для учётной записи администратора с sudo и впишите её имя вместо root в LIBVIRT_URI. Тогда копиям наборов данных ZFS нужен zfs allow, как описано выше.
Реплика на второй сервер входит с собственным ключом, который показывает окно реплики. Ключ SSH хоста не авторизует реплику, а ключ реплики не авторизует копии виртуальных машин.
TrueNAS не видит изменений, сделанных через virsh
Предполагается, что middleware TrueNAS, слой за его экранами виртуальных машин, — единственный способ менять его виртуальные машины. Команда virsh по этому SSH-соединению, то есть то, что запускают копирование и восстановление виртуальных машин BombVault, идёт в обход него, и TrueNAS может позже согласовать или перезаписать состояние, которого не создавал. Это следует из документированного поведения TrueNAS и на настоящем сервере не наблюдалось. Это риск того же рода, что и согласование VM Manager в Unraid изменений, сделанных вне него, только острее в TrueNAS.
3. Диски на zvol¶
Диски виртуальных машин TrueNAS часто являются zvol, блочными устройствами ZFS в /dev/zvol/<pool>/<dataset>, а не файлами qcow2. restic не может копировать блочное устройство по его пути так, как копирует файл, поэтому BombVault узнаёт диск zvol в XML домена (<source dev="..."> вместо <source file="...">) и работает с ним по тому же SSH-соединению. Контейнеру BombVault инструменты ZFS не нужны.
Копия zvol:
zfs snapshot <dataset>@bombvault-vm-<time>фиксирует момент времени, в том числе пока виртуальная машина работает.zfs clone -o volmode=dev -o readonly=onделает этот снимок читаемым как устройство.volmode=devне даёт хосту сканировать разделы гостя.ddчитает устройство, и сырой образ попадает в restic одним файлом,/vm-disks/<dataset>.img, с тегомvm:<name>:zvol:<dev>. restic режет его на куски по содержимому, так что блоки, не изменившиеся с прошлой копии, не сохраняются заново.- Клон и снимок потом уничтожаются, удалась копия или нет. Если BombVault остановился посреди копирования, следующая копия этого zvol сначала удаляет снимок
bombvault-vm-<time>и его клон<dataset>-bombvault-vm-<time>. Все остальные снимки он не трогает и сохраняет тот, с которого что-то ещё клонировали. Журнал называет, что удалено или сохранено.
BombVault не использует для этого zfs send. Каждая запись потока send несёт GUID снимка и текущую контрольную сумму, так что restic не нашёл бы ничего от прошлой копии для повторного использования и каждый раз сохранял бы весь диск заново. Измерено на TrueNAS SCALE 25.10 с zvol на 512 МиБ, содержащим 200 МиБ данных: первая копия добавила 211 МБ, вторая без изменений 52 КБ, а после изменения 1 МиБ 3,6 МБ. Тот же zvol через zfs send добавлял 214 МБ при каждом запуске.
Каждый запуск также записывает маленький снимок с тегом vm:<name> с XML домена, когда все диски уже внутри. У виртуальной машины, все диски которой — zvol, файлового снимка нет, и именно этот снимок показывает запуск под виртуальной машиной и делает её восстанавливаемой.
Восстановление записывает каждый zvol обратно на месте, так же как файловый диск записывается в свой файл, так что восстановленная виртуальная машина загружает восстановленные данные:
- Прежде чем что-либо тронуто, BombVault проверяет, что запуск содержит образ каждого диска zvol. Запуск, где его нет, отклоняется, а виртуальная машина остаётся как есть.
- Существующий zvol сначала получает снимок
<dataset>@bombvault-before-restore-<time>со временем в UTC, как и каждое имя снимка BombVault, так что оно может отличаться от местных часов на несколько часов. Журнал называет его, аzfs rollbackк нему отменяет восстановление, пока он самый новый снимок zvol. Когда появляется более новый, например от следующего восстановления, это делаетzfs rollback -r, уничтожая более новые снимки. Он остаётся, пока вы не удалите его черезzfs destroy, когда восстановленная виртуальная машина заработает. - Zvol, которого больше нет, создаётся с размером, который был у него при копировании, а существующий другого размера возвращается к этому размеру.
ddзаписывает образ на/dev/zvol/<dataset>. При включённом сжатии, как по умолчанию в TrueNAS, пустые части образа возвращаются как дыры и не занимают места.
Для восстановления на другой экземпляр нужен пул назначения. Оно переносит файловые диски в папку назначения, но папка не называет пула ZFS, поэтому без него BombVault отклоняет восстановление до его начала. Передайте пул параметром zvolPool в POST /api/foreign/restore: каждый zvol сохраняет свой путь ниже пула (tank/vms/win10/disk0 на flashpool становится flashpool/vms/win10/disk0), и XML домена указывает на него. В окне Из старой папки с копиями на странице «Восстановление» поля для этого нет, поэтому оно доступно только прямым вызовом API. Восстановление на том же экземпляре записывает каждый zvol обратно в него же.
Экспорт файлами пропускает zvol. Виртуальная машина, все диски которой — zvol, отклоняется с этой причиной, так что восстановите её из копии. Для виртуальной машины с ещё и файловыми дисками экспорт содержит файловые диски и заметку, называющую пропущенные zvol.
Это опробовано на TrueNAS SCALE 25.10 с ZFS 2.3.4: три копии пробного zvol, восстановление на месте после того, как zvol был перезаписан и вырос, и восстановление на zvol, который удалили. Каждое восстановление читалось обратно с тем же SHA-256, что и у источника, zvol снова имел старый размер, а ни снимка, ни клона не осталось. Целая виртуальная машина, единственный диск которой — zvol, была скопирована работающей, с Graceful и с живым режимом, и выключенной, и там же прошло восстановление целой виртуальной машины (удалить определение, записать zvol, определить, загрузить): zvol прочитался с контрольной суммой источника, и виртуальная машина запустилась.
Файловые диски, как их использует Unraid, ничего из этого не затрагивает.
4. Состояние vTPM¶
У виртуальной машины может быть виртуальный TPM, который нужен гостям с Secure Boot и Windows 11. Его состояние лежит вне диска и NVRAM, так что копия только этих двух вернула бы гостя с новым пустым TPM.
- Passthrough TPM, настоящая микросхема, переданная гостю, называет свой путь в XML домена. BombVault сохраняет его состояние рядом с NVRAM по SSH и записывает обратно перед
virsh define, по возможности, как и NVRAM: неудавшееся чтение или запись пишется в журнал и не проваливает копию или восстановление. - Эмулируемый vTPM, какой TrueNAS настраивает для гостей Windows 11 и Secure Boot, не публикует в XML домена пути к состоянию, поэтому его состояние не копируется. BombVault не гадает путь, и копия завершается с заметкой, что состояния TPM этой виртуальной машины в ней нет. Держите ключ восстановления такого гостя, например ключ BitLocker, под рукой, прежде чем его восстанавливать.
- Подключить TPM к виртуальной машине TrueNAS самостоятельно нельзя. API устройств виртуальных машин в TrueNAS SCALE 25.10 принимает только
CDROM,DISPLAY,NIC,PCI,RAW,DISKиUSBи отклоняетTPMкак неизвестный тип.
Обработка TPM проверена только модульными тестами и на настоящем госте TrueNAS с vTPM не запускалась. Виртуальная машина без TPM копируется и восстанавливается точно так же, как раньше.
NVRAM сохраняется как обычно. TrueNAS хранит его для каждой виртуальной машины в /var/db/system/vm/nvram/<id>_<name>_VARS.fd, и XML домена называет этот путь.
5. Имена виртуальных машин в TrueNAS¶
В Unraid имя виртуальной машины в libvirt — то, которое вы выбрали. TrueNAS придумывает имя в libvirt сам и менял способ дважды:
| Версия TrueNAS | Имя в libvirt | Где живёт ваше имя |
|---|---|---|
| 25.10 «Goldeye» | {id}_{name}, например 1_debian |
в имени libvirt, после {id}_ |
| 26 | UUID виртуальной машины, например 550e8400-e29b-41d4-a716-446655440000 |
только в <title> XML домена |
На хосте, который BombVault определяет как TrueNAS или который называет PLATFORM=truenas, список «Резервные копии» показывает ваше имя: debian вместо 1_debian в 25.10 и <title> вместо UUID в 26 или UUID, если названия нет. Это лишь то, что показывает список. Каждый вызов virsh и настройки отдельной виртуальной машины по-прежнему используют имя libvirt, так что копирование и восстановление всегда действуют на нужную виртуальную машину. В TrueNAS 26 это означает, что виртуальная машина, которую TrueNAS создаёт заново с новым UUID, появляется как новая запись без своих настроек, хотя её имя выглядит тем же. В Unraid ничего не меняется, в том числе для виртуальной машины, названной 10_Windows.
Схема 25.10 наблюдалась на настоящем сервере TrueNAS SCALE 25.10. Схема TrueNAS 26 взята из документации TrueNAS и проверена только модульными тестами.
Устранение неполадок¶
| Признак | Причина и исправление |
|---|---|
| Проверить соединение зависает, затем завершается ошибкой | До хоста не достучаться. Проверьте шаг 3 (сеть, VLAN, файрвол), а также Host SSH: Address и Port. |
Permission denied (publickey), хотя ключ в authorized_keys |
StrictModes в sshd отклоняет файл ключа, потому что у родительской папки неправильный владелец или режим. Это часто бывает, когда /root/.ssh — ссылка на флешку FAT (/boot/config/ssh/...), доступную для записи всем. Журнал хоста показывает Authentication refused: bad ownership or modes for directory .... Добавьте StrictModes no в конфигурацию sshd хоста в глобальный раздел, до любого блока Match, затем выполните /etc/rc.d/rc.sshd restart. Unraid при каждой загрузке пишет /etc/ssh/sshd_config заново, поэтому сохраните это, как описано ниже. |
Permission denied (publickey) и ключа действительно нет |
Повторите шаг 2 и проверьте, что SSH включён. |
Host key verification failed |
Выполните docker exec BombVault rm -f /config/ssh/known_hosts и проверьте снова. |
Проверка из шага 3 пишет UNREACHABLE |
Контейнер не достаёт до порта SSH хоста. См. шаг 3: доступ хоста к пользовательским сетям, маршрутизация VLAN или IP-шим либо IP в локальной сети. |
| В Edit нет переменных | Импортируйте шаблон заново. Существующий контейнер хранит свою старую сохранённую конфигурацию. |
| Виртуальная машина со снимками Unraid не копируется и называет файл | Цепочку базовых образов диска нельзя пройти до конца. Проверьте в VM Manager, что каждый снимок этого диска ещё на месте и что названный файл существует внутри /mnt. |
Другие признаки неполадок с виртуальными машинами описаны в разделе Устранение неполадок.
Как пережить перезагрузки¶
Unraid при каждой загрузке пишет /etc/ssh/sshd_config заново, поэтому изменения на стороне хоста приходится делать заново при загрузке:
- Порт SSH хранится в
/boot/config/ident.cfg, задаётся через веб-интерфейс Unraid. StrictModes no, если он понадобился выше, не сохраняется. Применяйте его при загрузке из/boot/config/go:
# /boot/config/go: keep SSH key auth working with flash-based authorized_keys
( for i in $(seq 1 30); do [ -f /etc/ssh/sshd_config ] && break; sleep 2; done
grep -q '^StrictModes no' /etc/ssh/sshd_config || \
sed -i '0,/^Match /s/^Match /StrictModes no\n&/' /etc/ssh/sshd_config
# SIGHUP reloads sshd's config in place: it keeps the listener + open sessions
# and avoids the "killing listener process / Restarting SSH server daemon"
# warning that `rc.sshd restart` prints at boot. Only reload if sshd is already
# up; if it starts after this runs, it reads the edited config on its own.
pidof sshd >/dev/null && killall -HUP sshd ) &
- Собственный ключ SSH BombVault и
~/.ssh/configлежат в/config(appdata) и создаются заново при каждом запуске, так что переживают перезапуски контейнера и хоста.
Безопасность¶
Авторизованный ключ даёт root на хосте, тот же уровень доверия, что и сокет Docker, который BombVault уже использует. Держите BombVault в доверенной сети. Ключ ed25519 хранится с режимом 0600 в appdata, а ключ хоста закреплён. Каждая команда хоста передаётся отдельными аргументами, никогда через удалённую оболочку, а SSH-соединение использует BatchMode и тайм-аут подключения.