Flash NAS mit Proxmox und verschlüsselten Dual Boot Drive Setup

Im letzten Beitrag ging es um das Gerät und das Setup selbst. Hier geht es weiter mit der Installation des Systems. Ich gehe hier Schritt für Schritt durch, das mag ja vielleicht für wen hilfreich sein. Los geht’s!

Installation

Zuerst habe ich mein PiKVM probiert…

… aber das hat nicht funktioniert und meine Versuche mit “Connect drive to Server” beendet. Leider funktioniert das nicht:

Daher doch wieder klassisch mit USB-Stick, aber zumindest mit Ventoy:

Update: Ich habe bemerkt, dass man den Odroid nur einmal richtig neustarten muss, dann erkennt er auch das PiKVM Laufwerk:

Diesmal mit TUI…

… denn bei der grafischen Installation wird beim PiKVM unten die Leiste leider abgeschnitten.

Retrolook:

Nach dem Neustart kann man sich schon in Proxmox einloggen:

Boot Festplatten verschlüsseln

Dieses Mal werde ich nicht damit beginnen Proxmox aufzusetzen und TrueNAS in einer VM zu installieren, sondern zuerst noch die beiden Boot-NVMes verschlüsseln. Dazu fährt man Proxmox wieder runter und bootet in eine Live Linux Distribution, hier Debian 12, aber es gehen auch andere aktuelle Linuxe (es braucht halt mindestens Kernel 5.15, oder neuer und cryptsetup ≥ 2.4 sowie zfsutils-linux). Aber zuerst sehen wir uns noch das Disk-Layout an und notieren die disk identifiers mit lsblk, fdisk -l und zpool status rpool:

Und wichtiger:

Und:

Relevant sind hier die diese Werte:

nvme0n1:
Disk identifier: F852D4D3-0ECE-4192-8BB7-6EF6C33EC279
nvme1n1:
Disk identifier: 8425B552-C0DD-425C-A7E5-0EE0508B4001

Diese notieren und denn die werden wir in der Debian Live Umgebung benötigen.

Vollständigkeitshalber noch ein Backup vom Boot-Drive, auch wenn das neu aufsetzen jetzt wohl nicht so lange dauern sollte. Damit kann man auf eine externe SSD/HDD mit diesem Befehl eine Bit-genaue Kopie darauf erstellen (dd Befehl vom Chatbot):

# Example: Backup /dev/nvme0n1 to an external mount (adjust paths)
dd if=/dev/nvme0n1 of=/mnt/backup/proxmox-disk0.img bs=1M status=progress

Ich habe das aus Faulheit heraus gelassen, da ich gerade kein freie SSD zu Hand gehabt habe und das jetzt suchen, oder auf den Backupserver spielen, dauert viel länger als einfach noch einmal Proxmox installieren. Aber prinzipiell ist das schon eine gute Idee.

Ich habe im PiKVM nun Debian 12 Netinstaller eingespielt, witzig ist, dass mir die Konsole von Proxmox live mitteilt, dass zuerst die Proxmox ISO weg und dann die Debian ISO dazugekommen ist:

Wie dem auch sei, Neustart und PiKVM bzw. den USB-Stick mit Debian auswählen:

Advanced options auswählen:

Und Rescue mode:

Hier Sprache und Keyboard Layout auswählen und Netzwerk-Interface:

Auch einen hostname braucht es wohl für das rescue system:

Schaut mir ja nach einer vollständigen Network-Stack konfiguration aus:

Ich habe dann mit Escape die Zeitzonen-Einstellung unterbrochen und dann scheint endlich das Menü auf:

Hier “Exectue a shell” auswählen:

Und bestätigen:

Jetzt hat man Zugriff auf ein Mini-System (Busybox, das wird auch gerne alle möglichen Gerätschaften verbaut, kann also gut sein, dass der eigene Geschirrspüler oder die “smarte” Lampe, auch so ein Mini-Linux-Busybox betreibt):

Aber da habe ich dann bemerkt, dass die Busybox ja überhaupt nicht ausreicht für irgendwas:

Dann lassen wir die Busybox lieber in Lampen und Geschirrspüler werkeln und Booten in ein Linux Mint.

Dort openssh-server installieren und aktivieren, dann noch Passwort ändern damit SSH auch funktioniert, sowie IP-Adresse herausfinden und schon kann man sich über Terminal verbinden:

sudo apt update
sudo apt install openssh-server
systemctl enable ssh.service
systemctl start ssh.service
sudo passwd mint
ip a

Dann noch einmal sudo fdisk -l /dev/nvme0n1:

Hier ist die Zeile mit Solaris /usr & Apple ZFS wichtig. Dann den folgenden Befehl ausführen mit der entsprechenden Partition:

sudo cryptsetup reencrypt --encrypt --type luks2 --reduce-device-size 16M /dev/nvme0n1p3

Je nach Laufwerksgröße kann das einige Zeit dauern:

Die Erklärung1 vom Chatbot, was dieser Befehl tut:

Jetzt heißt es abwarten bis der Prozess fertig ist. Bei meiner 256GB NVMe hat es gut eine halbe Stunde gedauert:

Finished, time 33m01s,  237 GiB written, speed 122.7 MiB/s

Sobald dies geschehen ist, kann man cryptsetup luksDump /dev/nvme0n1p3 überprüfen ob es funktioniert hat.

Weiters empfiehlt das Modell o3 im “Deep Research” Modus auch noch ein Backup vom LUKS-Header zu machen:

sudo cryptsetup luksHeaderBackup /dev/nvme0n1p3 --header-backup-file /mnt/your-usb/luks0-header.img

Dann kann man schon die zweite Platte verschlüsseln mit:

sudo cryptsetup reencrypt --encrypt --type luks2 --reduce-device-size 16M /dev/nvme1n1p3

Dessen LUKS-Header kann man auch wieder Backupen:

sudo cryptsetup luksHeaderBackup /dev/nvme1n1p3 --header-backup-file /mnt/your-usb/luks1-header.img

Danach kann man beide nun verschlüsselten Laufwerke öffnen mit:

sudo cryptsetup luksOpen /dev/nvme0n1p3 cryptpv0
sudo cryptsetup luksOpen /dev/nvme1n1p3 cryptpv1

Wenn man jetzt lsblk ausführt sollte man cryptpv0 und cryptpv1 sehen. Wenn man grafischer Umgebung unterwegs ist, wie ich mit Linux Mint, dann taucht rpool auch im Explorer auf:

Als nächstes geht es weiter mit dem Befehl, oder so zumindest dachte ich mir das:

sudo zpool import -R /mnt/pve rpool

Ach ja, Linux Mint, sobald man da den Befehl ausführen möchte, sagt einem das System, dass da wohl die Pakete fehlen:

mint@mint:~$ zpool import -R /mnt/pve rpool
Command 'zpool' not found, but can be installed with:
sudo apt install zfsutils-linux  # version 2.2.2-0ubuntu9.1, or
sudo apt install zfs-fuse        # version 0.7.0-25

Die angegeben Pakete sind leider zu alt, wie ich herausgefunden habe:

sudo zpool import -R /mnt/pve rpool
cannot import 'rpool': pool is formatted using a newer ZFS version

Der Chatbot bestätigt das:

Linux Mint neueres ZFS 2.3 beibringen

Nachdem ich nicht ein anderes ISO verwenden möchte, tu ich mir die dkms-Route an. Damit wird ein neueres Kernel-Modul installiert, damit die benötigte Version von ZFS läuft.

Zuerst Updaten und die notwendigen Pakete dafür installieren:

sudo apt update
sudo apt install --yes build-essential dkms linux-headers-$(uname -r)

Die waren bei mir aber eh schon installiert. Jetzt Paketquelle hinzufügen, aber bei Vorschlägen die vom Chatbot kommen…

sudo add-apt-repository ppa:openzfs/latest
sudo apt update

… immer skeptisch sein und nach Quellenangaben fragen, dann stellt sich nämlich gerne heraus, das LLM war wieder einmal kreativ:

Die beiden PPAs (von arter97 und weier) schauen nun hingegen vertrauenswürdig aus. Also:

sudo add-apt-repository ppa:weiers/openzfs-latest  
sudo apt update  
sudo apt install openzfs-zfs-dkms zfsutils-linux

Dann kommt die Konfiguration…

… die man einfach mit Enter bestätigen muss. Dann wird das Kernel-Modul installiert:

Dann:

sudo modprobe zfs

Jetzt spricht Linux Mint die richtige Version von ZFS.

rpool Import

Also noch einmal den Befehl eingeben:

sudo zpool import -f -R /mnt/pve rpool

Der Befehl ist jetzt nicht ganz identisch, denn nach dem Ausschalten des Proxmox Installers wurde der Pool nicht wieder freigegeben, da wir aber eh davon wissen, können wir die Flag -f hinzufügen und es funktioniert, ansonsten beschwert sich zpool:

mint@mint:~$ sudo zpool import -R /mnt/pve rpool
cannot import 'rpool': pool was previously in use from another system.
Last accessed by (none) (hostid=53695b0c) at Sat May 10 12:36:19 2025
The pool can be imported, use 'zpool import -f' to import the pool.

Das lädt den Proxmox rpool automatisch.

Falls das nicht funktioniert auch mit diesem Befehl manuell den Pfad angeben:

sudo zpool import -f -R /mnt/pve -d /dev/mapper rpool

Jetzt mit zpool status überprüfen, ob der Status eh ONLINE ist:

Hier sieht man auch gleich, dass der rpool auf zwei Festplatten gespiegelt wird. Damit sind wir eigentlich mit der Live Umgebung fast fertig.

chroot: crypttab und Dropbear einrichten

Jetzt müssen wir uns per chroot in in die Proxmox-Installation hineinversetzen. Mit diesem Befehl kann man effektiv so tun als sei man ein anderes (Linux) System und so können wir dem Proxmox System “beibringen” auch mit einer (oder zwei) verschlüsselten Festplatte umzugehen.

So beschreibt es der Chatbot (leider ohne Quellenangabe):

Mit diesem Befehl “schlüpft” man in die Schuhe der Proxmox Installation (“Sein Gesicht, das will ich… mir greifen”):

sudo su
for d in dev proc sys run; do mount --rbind /$d /mnt/pve/$d; done
chroot /mnt/pve /bin/bash

Jetzt sind wir in Proxmox drinnen und müssen diese Befehle ausführen:

apt update
apt install -y cryptsetup-initramfs dropbear-initramfs

Nicht von den Fehlermeldungen beirren lassen…

… das sind nur die Enterprise Repos von Proxmox (die wir später sowieso deaktivieren werden). Diese werden hier nicht benötigt. Die Installation der Pakete funktioniert dennoch:

Mit cryptsetup-initramfs können wir LUKS entschlüsseln und mit dropbear-initramfs installieren wir den minimalistischen SSH-Server, mit dem wir dann das kleine Odroid-NAS aus der Ferne entsperren können bei einem Neustart.

Wir brauchen jetzt die UUIDs um diese in crypttab, hier werden verschlüsselte Laufwerke konfiguriert (analog zu fstab), einzutragen. Also entweder blkid oder spezifisch cryptsetup luksUUID /dev/nvme0n1p3 bzw. cryptsetup luksUUID /dev/nvme1n1p3 ausführen.

Jetzt nano /etc/crypttab ausführen und diese Zeilen (mit angepasster UUID) hinzufügen:

rpool0 UUID=<UUID-of-nvme0n1p3-LUKS> none luks,initramfs
rpool1 UUID=<UUID-of-nvme1n1p3-LUKS> none luks,initramfs

Über die anderen Optionen, le bot2:

Sowie:

Jetzt den ZFS-Cache aktualisieren:

update-initramfs -u -k all
update-grub

Ich habe hier diese Fehlermeldungen bekommen:

root@mint:/# update-initramfs -u -k all
update-initramfs: Generating /boot/initrd.img-6.8.12-9-pve
cryptsetup: ERROR: Couldn't resolve device rpool/ROOT/pve-1
cryptsetup: WARNING: Couldn't determine root device
cryptsetup: ERROR: rpool0: Source mismatch
cryptsetup: ERROR: rpool1: Source mismatch
device-mapper: table ioctl on rpool0  failed: No such device or address
Command failed.
cryptsetup: WARNING: Couldn't determine cipher modules to load for rpool0
device-mapper: table ioctl on rpool1  failed: No such device or address
Command failed.
cryptsetup: WARNING: Couldn't determine cipher modules to load for rpool1
dropbear: WARNING: Invalid authorized_keys file, SSH login to initramfs won't work!
Running hook script 'zz-proxmox-boot'..
Re-executing '/etc/kernel/postinst.d/zz-proxmox-boot' in new private mount namespace..
Copying and configuring kernels on /dev/disk/by-uuid/CF59-9CA5
	Copying kernel and creating boot-entry for 6.8.12-9-pve
Copying and configuring kernels on /dev/disk/by-uuid/CF5A-1FCC
	Copying kernel and creating boot-entry for 6.8.12-9-pve

Diesen Konsolenoutput habe ich dem o3-Modell gefüttert:

Und hier die weiteren Infos in Tabellenform (Quelle):

Die Lösung laut Bot:

# On the live system (outside chroot) make sure both LUKS containers are open
cryptsetup luksOpen /dev/nvme0n1p3 cryptpv0
cryptsetup luksOpen /dev/nvme1n1p3 cryptpv1
 
# Bind all runtime dirs **and** /dev/mapper into the jail
mount --rbind /dev  /mnt/pve/dev
mount --rbind /proc /mnt/pve/proc
mount --rbind /sys  /mnt/pve/sys
mount --rbind /run  /mnt/pve/run
 
# Enter the chroot
chroot /mnt/pve /bin/bash
 
# Make sure the mapper nodes are really visible INSIDE
ls -l /dev/mapper/cryptpv*

Wir haben die beiden LUKS Container ja eigentlich eh offen gelassen. Von daher verstehe ich nicht ganz, inwiefern uns das hier hilft. Aber ich sehe, dass der Pfad /mnt/pve nicht innerhalb von chroot verfügbar ist. Hm, aber das ist ja eigentlich gar nicht der gemappte Pfad, der ist ja unter /dev/mapper/cryptpv*. Aber das ist ja nur das device, da wäre es jetzt gut zu verstehen, was das alles heißt. Schauen wir zuerst noch einmal weiter, ls -l /dev/mapper/cryptpv* zeigt uns auf jeden Fall die beiden devices:

Aber rpool fehlt hier:

Auch zpool status zeigt den rpool an:

Das ist eigenartig. Also die Lösung vom Bot ist das selbe noch einmal machen. Einzig die bind mounts bleiben noch übrig. Vielleicht hat der Befehl von oben (for d in dev proc sys run; do mount --rbind /$d /mnt/pve/$d; done) nicht alle Pfade richtig ge-bind-mountet. Oder ich verstehe da was nicht ganz richtig. Letzteres kann gut sein, denn die ganze chroot-erei ist für mich eher noch Voodoo.

Wie auch immer, ich habe meine Zweifel angemeldet…

… und die Antwort war dann a) eine Kehrtwende und b) etwas unerwartet:

Der letzte Punkt hier ist besonders pikant, das vorher noch unbedingt zu lösende Problem hat sich wohl als zu ignorieren entpuppt. Im verlinkten Beitrag auf der Seite herold.space wird tatsächlich genau darauf hingewiesen, dass man diese Zeilen ignorieren soll:

Das sind ja gute Nachrichten, den “cosmetic fix” spare ich mir für diese einmalige Angelegenheit. Das heißt wir können gleich noch Dropbear und eine statische IP-Adresse konfigurieren und dann sollten wir mit chroot und der Live Distro fertig sein.

Für Dropbear muss man die folgenden Befehle ausführen, im Prinzip gibt man Dropbear den public key jenes Systems, mit welchen man bei einem Start des Odroids LUKS entschlüsseln möchte. Perspektivisch wird das bei mir ein kleiner Raspberry Zero 2 W werden, aber vorerst hinterlege ich einfach den öffentlichen SSH-Schlüssel meines Laptops:

mkdir -p /etc/dropbear-initramfs
printf '%s\n' "ssh-ed25519 AAAA...your_key..." > /etc/dropbear-initramfs/authorized_keys
chmod 600 /etc/dropbear-initramfs/authorized_keys
chown root:root /etc/dropbear-initramfs/authorized_keys

Wenn man möchte kann man unter /etc/dropbear/initramfs/dropbear.conf auch gleich noch angeben…

DROPBEAR_OPTIONS="-s -c cryptroot-unlock"

… dass nur noch per SSH-Schlüssel eingeloggt werden kann (-s) und, dass sobald ein Login erfolgt, sofort die Entschlüsselung von LUKS vorgenommen werden soll (-c cryptroot-unlock mehr Infos im Proxmox-Forum). Man meldet sich an und wird sofort nach dem LUKS-Passwort gefragt. Man hat also die Möglichkeit entweder manuell oder per Skript zu entschlüsseln.

Jetzt müssen wir der initramfs Umgebung noch eine statische IP-Adresse mitteilen, damit wir darauf zugreifen können. Es kann und soll sogar die selbe IP-Adresse sein wie das des zu entsperrenden Rechners:

Die angegeben Quellen beschreiben zwar das Entsperren über SSH, aber in keiner davon wird irgendwas zu der IP-Adressen-Auswahl gesagt. Vielleicht ist das allen Wissenenden eh so klar, dass es keiner Zeile wert ist? Die obige Erklärung klingt zumindest recht plausibel von da her vertraue ich dem einmal und werde die selbe IP-Adresse verwenden.

Das Hinzufügen der IP-Adresse geht nun entweder über eine GRUB_CMDLINE_LINUX unter /etc/default/grub Eingabe…

GRUB_CMDLINE_LINUX="rd.neednet=1 ip=192.168.1.xxx::192.168.1.1:255.255.255.0:<optionaler-hostname-von-initramfs>:eth0:none"

… oder über einen Eintrag in /etc/initramfs-tools/initramfs.conf:

IP=192.168.1.50::192.168.1.1:255.255.255.0::eth0:none

Achtung, vorher noch einmal mit ip a überprüfen welches Network-Interface verwendet wird. Bei mir ist es enp2s0, es hätte aber auch enp1s0 sein können, aber ich habe das Netzwerkkabel halt an der linken Buchse vom Odroid H4 Plus angesteckt. Daran sollte man halt denken, wenn man zwei LAN-Buchsen hat, nicht dass man irgendwann einmal das Kabel auf der anderen Stelle ansteckt und sich dann wundert warum Dropbear nicht erreichbar ist und das System nicht mehr entsperrt werden kann. Falls mir das passieren sollte, verspreche ich hier ein kleines Update einzufügen.

Wenn jemanden die Furcht ob dieses Problems umgeht, kann man es auch kompliziert machen und einen Network-Bond in initramfs erstellen:

Ich bin jetzt auch einmal “most people” und spare mir das. Wobei jetzt wo ich drüber nachdenke, glaube, dass “most people” überhaupt recht wenig mit dem ganzen Zeugs hier zu tun haben, geschweige denn verstehen, was das alles soll. Aber von diesen leichten Anflügen von Nieschigkeit lassen wir uns nicht aufhalten und tippen mutig weiter.

Alles Relevante updaten:

update-grub
update-initramfs -u -k all

Zum Überprüfen, ob es Dropbear eh wirklich in initramfs geschafft hat folgendes ausführen:

ls /boot | grep initrd.img
lsinitramfs /boot/initrd.img-6.8.12-9-pve | grep # Oder was auch immer man installiert hat als Proxmox-Kernel

Bei mir:

root@mint:/mnt# ls /boot | grep initrd.img
initrd.img-6.8.12-9-pve
root@mint:/mnt# lsinitramfs /boot/initrd.img-6.8.12-9-pve | grep dropbear
etc/dropbear
etc/dropbear/dropbear.conf
etc/dropbear/dropbear_ecdsa_host_key
etc/dropbear/dropbear_ed25519_host_key
etc/dropbear/dropbear_rsa_host_key
scripts/init-bottom/dropbear
scripts/init-premount/dropbear
usr/sbin/dropbear

Jetzt können wir endlich chroot und auch die Live Umgebung beenden.

Neustart und Test

Zuerst chroot beenden:

exit

Alles unter /mnt/pve rekursiv unmounten:

sudo umount -R /mnt/pve

Das hat irgendwie wieder nicht ganz funktioniert. Das Live System hat sich wohl die gemounteten Pfade “gekrallt” und will nicht wirklich. Ich habe immer wieder “device busy” bekommen.

Live GUI beenden:

sudo systemctl isolate multi-user.target

Überprüfen:

sudo fuser -mv /mnt/pve     # should now return nothing

Da war dann immer noch was und…

sudo umount -R /mnt/pve

… geht nicht.

Das liegt wohl am obigen Befehl:

Und dann die Nerven verlieren und einfach mit Force-Flag (-f) Pool exportieren:

zpool export -f rpool

Dann bemerken, dass das Ganze mit GUI vielleicht nicht das Beste war. Also einfach neustarten.

Hier noch der Senf von ChatGPT:

Jähes Fazit

OK, das war schon eine lange Sitzung. Prinzipiell funktioniert es schon, aber das gesamte Setup muss ich mir im Detail noch einmal anschauen. Ich hoffe manche werden Interessantes darin finden. Zu diesem Thema werde ich bei Gelegenheit noch zurückkommen.

Update: Es hat sich herausgestellt, dass das Dropbear Setup leider spinnt (Dropbear will nur RSA Keys, das will aber sonst niemand…), bis ich eine Lösung habe, muss ich das Flash-NAS via PiKVM entsperren, aber grundsätzlich läuft das System sehr stabil. Daher war das bisher nur einmal notwendig.

Footnotes

  1. Die Quellenangaben dazu:

  2. Quelle: