النسخ الاحتياطي للأجهزة الافتراضية¶
ينسخ BombVault أجهزة KVM/libvirt الافتراضية دون تركيب أي مسار من libvirt. يشغّل virsh على المضيف عبر SSH (qemu+ssh://)، ويقرأ أقراص الأجهزة ويكتبها عبر تركيب Host Data (المسار /mnt على المضيف هو /host/user في الحاوية)، وينسخ NVRAM الخاص بـ UEFI عبر SSH. ولأنه لا يُركَّب أي شيء يخص libvirt، فلا يمكن أن يتعارض BombVault مع مدير الأجهزة الافتراضية في 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 المضيف في الشبكة المحلية غير قابل للوصول، فاستخدم عنوان shim للمضيف على شبكة الحاوية الفرعية. تجده على المضيف بـ
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: الطريقة لكل جهاز¶
لكل جهاز افتراضي الطريقة في بطاقة VM بعلامة التبويب «الإعدادات» الخاصة به (افتح الجهاز تحت النسخ الاحتياطية):
- آمنة (إيقاف تشغيل) هي الافتراضية. تُطفئ الجهاز وتنسخ الأقراص وتشغّله من جديد، فتكون النسخة متسقة دائمًا. تنتظر حتى عشر دقائق ليُطفئ النظام الضيف نفسه، ولا تفرض الإطفاء أبدًا. النظام الضيف الذي ما زال يعمل بعد ذلك يُترك كما هو، وتفشل تلك النسخة مع ذكر السبب. وإن أُطفئ الضيف خلال الساعة التالية، يشغّله BombVault من جديد. وإن تعذّر تشغيله، تقول النسخة الفاشلة ذلك.
- لقطة حية تنسخ جهازًا يعمل عبر لقطة خارجية و
blockcommit. تحتاج إلى أن يقع القرص على/mnt/cacheأو/mnt/diskXلا على/mnt/user. ومع وكيل ضيف qemu داخل الجهاز تكون اللقطة هادئة، ودونه تكون اللقطة متسقة كما بعد انهيار مفاجئ. على جهاز مطفأ تعود «لقطة حية» إلى «آمنة» من تلقاء نفسها. وحين يتعذر أخذ اللقطة، تفشل تلك النسخة ويبقى الجهاز يعمل، لأن الجهاز الذي اخترت نسخه حيًّا لا يُطفأ لذلك أبدًا.
ما الذي تتركه النسخة¶
قد تنجح النسخة ومع ذلك لا تحمل الجهاز كاملًا. يحمل التشغيل حينئذ ملاحظة بلون التحذير تسمّي ما ينقص:
- أقراص لا يقرؤها BombVault. يُترك القرص المخصص للقراءة فقط، وقرص
lun، وقرصnetworkأوvolume، وتسمّي الملاحظة كلًا منها مع جهاز الهدف ونوعه. ويبقى التعريف في النسخة يسردها. ولا يُسمّى cdrom ولا floppy. أما جهاز الكتل العادي الذي ليس zvol من ZFS فيُفشل النسخة بدلًا من ذلك. - حالة TPM مُحاكى. ليس لها مسار في XML النطاق. يعدّ مدير الأجهزة في Unraid مثل هذا TPM للجهاز الذي يستخدم BIOS OVMF TPM، لذا تظهر الملاحظة على Unraid أيضًا. والضيف الذي يحفظ سرًا في TPM الخاص به، كما يفعل BitLocker، قد يطلب مفتاح الاسترداد بعد استعادة تفقد تلك الحالة، فأبقِ ذلك المفتاح في متناولك.
الأقراص الرقيقة¶
تُبقي الاستعادة القرص الرقيق (thin) رقيقًا، سواء استبدلت القرص أو كتبت قرصًا جديدًا: يكتب restic سلاسل الأصفار ثقوبًا في الملف الجديد، ويعيد BombVault الكتل الصفرية للملف المستبدَل بـ fallocate --dig-holes بعد كتابته. وأثناء استبدال restic لملف يأخذ ذلك الملف حجمه الكامل، إن كان في الـ pool متسع له. ونظام الملفات الذي لا يدعم ثقب الملفات يُبقي القرص بحجمه الكامل، ويقول السجل ذلك. ويظل فحص المساحة يحسب القرص الجديد بحجمه الكامل.
استعادة تفشل¶
الاستعادة في المكان تُطفئ الجهاز، وتكتب الأقراص، ولا تستبدل التعريف وNVRAM إلا بعد كتابة الأقراص. والاستعادة التي تفشل تترك الجهاز معرَّفًا مع NVRAM الخاص به. فإن لم تتغير أقراصه وكان يعمل، يعمل من جديد. وإن كانت قد تغيرت يبقى مطفأً، لأن إقلاع قرص مكتوب نصفه سيكتب فوقه، ويقول التشغيل ذلك. واستعادة النسخة نفسها من جديد تكمل العمل.
اللقطات المسجلة في libvirt، وهي ليست الطريقة التي ينشئها بها مدير الأجهزة في Unraid، توقف الاستعادة في المكان قبل أن يُمس الجهاز، لأن libvirt لا يستطيع إزالة جهاز له لقطات كهذه. احذفها أولًا.
الكتل المتغيرة فقط¶
يمكن نسخ جهاز بأقراص qcow2 بقراءة ما تغيّر فقط. فعّل الكتل المتغيرة فقط في البطاقة نفسها، فيستخدم BombVault واجهة النسخ في libvirt بدلًا من الطريقة أعلاه:
- يبدأ مهمة نسخ بنمط السحب (
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 بلا واجهة النسخ، أو مساحة حرة قليلة جدًا تحت /config، تعني النسخة المعتادة بالطريقة أعلاه. تقول البطاقة أيًّا منها استخدمه آخر تشغيل ولماذا.
المتطلبات: libvirt بواجهة النسخ (جُرّب مع libvirt 12.2 وQEMU 10.2 على Unraid 7.3)، وsshd مع AllowStreamLocalForwarding yes (وهو الافتراضي، وكذلك في Unraid الذي يعطّل تمرير TCP)، وأقراص qcow2. ترفض libvirt نقاط التحقق على الأقراص الخام، وينشئ Unraid vdisks خامًا افتراضيًا. يواصل الجهاز عمله أثناء النسخ كما مع «لقطة حية»، وتشغل المقاطع المنتظرة لـ restic ما يصل إلى 4 GiB تحت /config.
أجهزة لها لقطات Unraid¶
اللقطة التي يأخذها مدير الأجهزة الافتراضية في Unraid تحوّل قرص qcow2 إلى سلسلة: الصورة الأصلية في الأسفل، وفوقها ملف لكل لقطة، يحمل كل منها ما تغيّر فقط منذ الذي تحته. يكتب الجهاز في أحدث ملف. قرص بلقطتين هو ثلاثة ملفات.
ينسخ BombVault جهازًا كهذا كاملًا:
- كل ملف في السلسلة. يتتبع سلسلة الدعم لكل قرص حتى نهايتها وينسخ كل ملف فيها، مع قائمة لقطات Unraid (
/etc/libvirt/qemu/snapshotdb/<vm>/snapshots.db، تُقرأ عبر SSH). السلسلة التي لا يمكن تتبعها حتى نهايتها، مثلًا لأن ملفًا في المنتصف مفقود، تُفشل النسخة وتسمّي الملف. - النسخة الحية تحافظ على اللقطات. لقطة حية تضع طبقة مؤقتة في الأعلى أثناء قراءة القرص ثم تدمجها بعد ذلك، في الصورة التي تحتها مباشرة فقط. السلسلة بعد النسخة هي نفسها قبلها. الجهاز بلا لقطات يتصرف كما كان دائمًا.
- الاستعادة تعيد السلسلة. الاستعادة في المكان تكتب كل ملف حيث كان وتعيد قائمة لقطات Unraid، فيسرد مدير الأجهزة اللقطات من جديد. والاستعادة بجانب الأصل تكتب الملفات في مجلد النسخة وتوجّه الأقراص المستعادة إلى الملفات المستعادة، فلا تقرأ النسخة من صور الأصل أبدًا. تعود قائمة لقطات Unraid مع الاستعادة في المكان فقط، لأنها تسمّي الملفات حيث نُسخت. بدونها تقلع النسخة بالطريقة نفسها، ولا يسرد مدير الأجهزة لها لقطات.
- الكتل المتغيرة فقط تقرأ ما يراه الضيف، فتعود استعادته ملف qcow2 واحدًا مسطّحًا دون اللقطات.
- الاستعادة تعيد قرص النسخة التي تختارها. اللقطات المأخوذة أو المدموجة منذ تلك النسخة لا تغيّر ذلك. النسخة المأخوذة قبل لقطة تعرّف الجهاز على الملف الذي تحمله، والنسخة المأخوذة قبل دمج تعيد طبقتها العلوية وتعمل عليها. تبقى الملفات الأحدث حيث هي، غير مستخدمة ودون تغيير. والنسخة التي تحمل طبقة علوية دون الملف الذي تحتها تُرفض قبل أن يُمس الجهاز. ولا يسرد تعريف الجهاز بعد الاستعادة أي سلسلة، فيقرأ libvirt السلسلة من الملفات المستعادة.
مثال: جهاز بلقطتين¶
للجهاز homeassistant قرص واحد، vdisk1.qcow2، ولقطتان أخذتهما في مدير الأجهزة قبل تحديثين. قرصه الآن سلسلة من ثلاثة ملفات. يعمل طوال الوقت، لذا يستخدم لقطة حية.
- افتح النسخ الاحتياطية ثم
homeassistantثم علامة التبويب الإعدادات. في بطاقة VM تحقق من أن الطريقة هي لقطة حية وأن الكتل المتغيرة فقط معطّلة. - اضغط نسخ احتياطي الآن في رأس الصفحة.
- حين ينتهي التشغيل يكون سطره في أحدث التشغيلات بعلامة التبويب تحقق أخضر. ظل الجهاز يعمل طوال الوقت، وتحمل النسخة ملفات القرص الثلاثة وقائمة لقطات Unraid.
- في مدير الأجهزة تبقى اللقطتان في مكانهما، ويظل القرص يقرأ عبر الملفات الثلاثة نفسها.
بعد شهر يسوء تحديث وتريد حالة الأمس بجانب المعطوبة لتقارن:
- افتح الاستعادة، واختر VMs وانقر
homeassistant. - أبقِ النسخة الموصى بها من الليلة الماضية واختر بجانب الأصل تحت إلى أين.
- اضغط استعادة. تقع الملفات الثلاثة في مجلد باسم الجهاز مع
-restored، ويشير القرص المستعاد إلى الملفات المستعادة. لا يتغير شيء على الجهاز العامل.
لإرجاع الجهاز كله بدلًا من ذلك، اختر استبدال الأصل مع تفعيل نسخ الحالة الحالية احتياطيًا أولًا. ينسخ BombVault الحالة المعطوبة، ويُطفئ الجهاز، ويكتب الملفات الثلاثة وقائمة لقطات Unraid، ويشغّله من جديد.
TrueNAS SCALE¶
الخطوات أعلاه مكتوبة لـ Unraid، لكن رابط qemu+ssh:// نفسه يعمل مع أي libvirtd تستطيع الحاوية بلوغه، ومنه TrueNAS SCALE الذي عادت فيه الأجهزة الافتراضية على libvirt منذ 25.04.2. في TrueNAS تحتاج سلسلة الاتصال إلى تجاوز، ويوضع المفتاح على root في إعدادات المستخدمين الخاصة بـ TrueNAS. وثلاثة أشياء أخرى تغيّر ما تحمله النسخة: الأقراص على zvols، وحالة vTPM، والأسماء التي يعطيها TrueNAS لأجهزته.
1. مقبس libvirt¶
لا يستمع libvirtd في TrueNAS حيث تتوقعه سلسلة الاتصال المبنية من حقول Host SSH. اضبط LIBVIRT_URI بدلًا من ذلك، مع المعامل الإضافي ?socket=:
يستخدم BombVault LIBVIRT_URI كما كُتب تمامًا، ولا حاجة إلى LIBVIRT_HOST وLIBVIRT_SSH_USER وLIBVIRT_SSH_PORT. لكل واحد منها غير مضبوط يأخذ BombVault المضيف والمستخدم والمنفذ من العنوان لأوامر SSH الخاصة به أيضًا، فيصل نسخ NVRAM ونسخ مجموعات بيانات ZFS إلى الجهاز نفسه الذي يصل إليه virsh. المتغير الذي تضبطه بنفسك يفوز دائمًا، ويسمّي سجل الإقلاع الهدف الذي أخذه من العنوان. في TrueNAS يحتاج مستخدم غير root أيضًا إلى zfs allow <user> snapshot,destroy,mount <dataset> لنسخ مجموعات بيانات ZFS، راجع مجموعات بيانات ZFS.
ضع عنوان TrueNAS في الشبكة المحلية في العنوان. حين لا يكون LIBVIRT_URI ولا LIBVIRT_HOST مضبوطًا يأخذ BombVault البوابة الافتراضية للتطبيق مضيفًا، لأن host.docker.internal لا يُحل في تطبيق TrueNAS، ويسمّي سجل الإقلاع العنوان الذي اختاره. يكفي هذا لنسخ مجموعات بيانات ZFS. أما نسخ الأجهزة الافتراضية فما زالت تحتاج إلى العنوان من أجل المقبس.
يحتاج التطبيق إلى القدرة 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 كما هو موصوف أعلاه.
النسخة المتماثلة لـ ZFS إلى خادم ثانٍ تدخل بمفتاح خاص بها تعرضه نافذة النسخة المتماثلة. مفتاح SSH المضيف لا يسمح بنسخة متماثلة، ومفتاح النسخة المتماثلة لا يسمح بنسخ الأجهزة الافتراضية.
لا يرى TrueNAS التغييرات التي تُجرى بـ virsh
وسيط TrueNAS، الطبقة التي تقف خلف شاشات أجهزته الافتراضية، مقصود به أن يكون الطريقة الوحيدة لتغيير أجهزته. أمر virsh عبر رابط SSH هذا، وهو ما يشغّله نسخ BombVault واستعادته للأجهزة، يتجاوزه، وقد يوفّق TrueNAS لاحقًا أو يكتب فوق حالة لم ينشئها. هذا مأخوذ من سلوك TrueNAS الموثّق ولم يُرَ على جهاز حقيقي. إنه نوع الخطر نفسه الذي يوفّق فيه مدير الأجهزة في Unraid التغييرات المجراة خارجه، لكنه أحدّ على TrueNAS.
3. الأقراص على zvols¶
أقراص أجهزة TrueNAS كثيرًا ما تكون zvols، أي أجهزة كتل 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 MiB يحمل 200 MiB من البيانات: أضافت أول نسخة 211 MB، والثانية دون أي تغيير 52 KB، وبعد تغيير 1 MiB أضافت 3.6 MB. أما zvol نفسه عبر zfs send فأضاف 214 MB في كل تشغيل.
كل تشغيل يكتب أيضًا لقطة صغيرة بالوسم vm:<name> تحمل XML النطاق، بعد دخول كل الأقراص. الجهاز الذي أقراصه كلها zvols لا لقطة ملفات له، وهذه هي التي تسرد التشغيل تحت الجهاز وتجعله قابلًا للاستعادة.
تكتب الاستعادة كل 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 على نفسه.
التصدير كملفات يترك zvols خارجًا. الجهاز الذي أقراصه كلها zvols يُرفض بهذا السبب، فاستعده من نسخة احتياطية. وللجهاز الذي له أقراص ملفات أيضًا يحمل التصدير أقراص الملفات وملاحظة تسمّي zvols التي تركها.
جُرّب هذا على TrueNAS SCALE 25.10 مع ZFS 2.3.4: ثلاث نسخ لـ zvol تجريبي، واستعادة في المكان بعد أن كُتب فوق zvol وكبر، واستعادة على zvol كان قد حُذف. قرئت كل استعادة بمجموع SHA-256 نفسه الذي للمصدر، وعاد zvol إلى حجمه القديم، ولم تبق لقطة ولا استنساخ. ونُسخ جهاز كامل قرصه الوحيد zvol وهو يعمل، بـ «آمنة» وبـ «لقطة حية»، وهو مطفأ، وجرت هناك أيضًا استعادة جهاز كامل (إلغاء التعريف، وكتابة zvols، والتعريف، والإقلاع): قرئ zvol بمجموع المصدر نفسه وبدأ الجهاز.
أقراص الملفات، كما يستخدمها Unraid، لا يمسها شيء من هذا.
4. حالة vTPM¶
يمكن أن يكون للجهاز TPM افتراضي، تحتاجه أنظمة Secure Boot وWindows 11 الضيفة. تقع حالته خارج القرص وNVRAM، فنسخة لهذين فقط تعيد ضيفًا بـ TPM جديد فارغ.
- TPM عبور (passthrough)، شريحة حقيقية تُمرَّر إلى الضيف، يسمّي مساره في XML النطاق. يحفظ BombVault حالته بجانب NVRAM عبر SSH ويكتبها قبل
virsh define، بأفضل جهد مثل NVRAM: قراءة أو كتابة فاشلة تُسجَّل ولا تُفشل النسخة أو الاستعادة. - vTPM مُحاكى، من النوع الذي يعدّه TrueNAS لأنظمة Windows 11 وSecure Boot الضيفة، لا ينشر مسار حالة في XML النطاق، لذا لا تُنسخ حالته. لا يخمّن BombVault مسارًا، وتنتهي النسخة بملاحظة أن حالة TPM الخاص بالجهاز ليست فيها. احتفظ بمفتاح استرداد ذلك الضيف، مثل مفتاح BitLocker، في متناولك قبل استعادته.
- لا يمكنك إرفاق TPM بجهاز TrueNAS بنفسك. واجهة أجهزة الأجهزة الافتراضية في 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، أو عنوان shim أو عنوان الشبكة المحلية. |
| المتغيرات مفقودة تحت Edit | استورد القالب من جديد. الحاوية الموجودة تحتفظ بإعداداتها المحفوظة القديمة. |
| جهاز بلقطات Unraid يفشل ويسمّي ملفًا | لا يمكن تتبع سلسلة دعم القرص حتى نهايتها. تحقق في مدير الأجهزة من أن كل لقطات ذلك القرص ما زالت موجودة، وأن الملف المسمّى موجود تحت /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 ومهلة اتصال.