Pi 4 Raspberry Pi 4 (8 GB) als Proxmox VE Test-Node Installation von Debian 13 (Trixie) ARM64 auf einem Raspberry Pi 4 mit 8 GB RAM. Das Root-Dateisystem wird mit LUKS2 verschlüsselt und beim Booten über Dropbear-SSH entsperrt. Die Einrichtung erfolgt von einem Linux-PC mit debootstrap und einer ARM64-chroot-Umgebung. Das System erhält eine feste IP-Adresse, automatische Zeitsynchronisierung und eine deutsche UTF-8-Locale. 1. Voraussetzungen Raspberry Pi 4 mit 8 GB RAM USB-SSD mit mindestens 64 GB Debian-13-Linux-PC Ethernet-Verbindung USB-Boot-fähige Raspberry-Pi-Firmware SSH-Schlüssel für Administration und LUKS-Entsperrung Netzwerkkonfiguration Hostname darkside IP-Adresse 10.100.0.61 Netzmaske 255.255.0.0 (/16) Gateway 10.100.0.1 DNS 1.1.1.1 Interface eth0 Zeitzone Europe/Berlin Locale de_DE.UTF-8 2. Datenträger vorbereiten Die SSD besteht aus einer unverschlüsselten Boot-Partition und einer mit LUKS2 verschlüsselten Root-Partition. Partition Format Verwendung Partition 1 FAT32 /boot/firmware Partition 2 LUKS2 Verschlüsseltes Root-Dateisystem cryptroot ext4 Debian und virtuelle Maschinen Alle folgenden administrativen Befehle werden als root ausgeführt. Benötigte Pakete auf dem Linux-PC installieren: apt update apt install -y \ debootstrap \ debian-archive-keyring \ qemu-user \ qemu-user-binfmt \ binfmt-support \ cryptsetup \ parted \ dosfstools \ e2fsprogs \ ca-certificates Datenträger identifizieren: lsblk -o NAME,SIZE,MODEL,TYPE,MOUNTPOINTS Im folgenden Beispiel wird /dev/sdb als Zielgerät verwendet. Die Gerätebezeichnung unbedingt prüfen. Alle Partitionen der SSD müssen ausgehängt sein. Achtung: Die folgenden Befehle löschen sämtliche Daten auf dem ausgewählten Datenträger. Bei einem bereits installierten System diesen Abschnitt überspringen. DISK=/dev/sdb parted -s "$DISK" mklabel msdos parted -s "$DISK" mkpart primary fat32 1MiB 1025MiB parted -s "$DISK" mkpart primary 1025MiB 100% parted -s "$DISK" set 1 boot on partprobe "$DISK" udevadm settle Partitionen festlegen: BOOT=/dev/sdb1 ROOT=/dev/sdb2 3. LUKS2-Verschlüsselung Boot-Partition formatieren: mkfs.vfat -F32 -n PVEBOOT "$BOOT" Root-Partition mit AES-256-XTS und Argon2id verschlüsseln: cryptsetup luksFormat \ --type luks2 \ --cipher aes-xts-plain64 \ --key-size 512 \ --pbkdf argon2id \ --pbkdf-memory 524288 \ --pbkdf-parallel 2 \ --iter-time 2000 \ --verify-passphrase \ "$ROOT" Eine lange, zufällig erzeugte Passphrase verwenden. Die tatsächlichen Argon2-Parameter werden auf dem einrichtenden Rechner kalibriert und müssen später auf dem Raspberry Pi getestet werden. LUKS-Partition öffnen: cryptsetup open "$ROOT" cryptroot Dateisystem erstellen: mkfs.ext4 -L pve-root /dev/mapper/cryptroot UUIDs ermitteln und notieren: cryptsetup luksUUID "$ROOT" blkid -s UUID -o value "$BOOT" 4. Debian installieren Dateisysteme einhängen: mkdir -p /mnt/Temp/1 mount /dev/mapper/cryptroot /mnt/Temp/1 mkdir -p /mnt/Temp/1/boot/firmware mount "$BOOT" /mnt/Temp/1/boot/firmware Debian 13 installieren: debootstrap \ --arch=arm64 \ --keyring=/usr/share/keyrings/debian-archive-keyring.gpg \ trixie \ /mnt/Temp/1 \ https://deb.debian.org/debian Crypttab konfigurieren nano /mnt/Temp/1/etc/crypttab Eintrag: cryptroot UUID=LUKS-UUID none luks,initramfs LUKS-UUID durch die zuvor ermittelte UUID ersetzen. Fstab konfigurieren nano /mnt/Temp/1/etc/fstab Inhalt: /dev/mapper/cryptroot / ext4 defaults,noatime 0 1 UUID=BOOT-UUID /boot/firmware vfat defaults,umask=0077 0 2 BOOT-UUID durch die UUID der FAT32-Partition ersetzen. 5. ARM64-chroot betreten Systemdateisysteme einbinden: for DIR in dev proc sys run; do mount --rbind "/$DIR" "/mnt/Temp/1/$DIR" mount --make-rslave "/mnt/Temp/1/$DIR" done DNS-Konfiguration für die Installation: cp -L /etc/resolv.conf /mnt/Temp/1/etc/resolv.conf ARM64-chroot betreten: chroot /mnt/Temp/1 /bin/bash Architektur prüfen: dpkg --print-architecture Die Ausgabe muss arm64 sein. Die folgenden Befehle werden innerhalb der chroot-Umgebung ausgeführt. 6. Debian-Basissystem APT-Paketquellen prüfen: nano /etc/apt/sources.list Die folgenden Debian-Quellen verwenden. Gleichwertige vorhandene Einträge unter /etc/apt/sources.list.d nicht duplizieren. deb https://deb.debian.org/debian trixie main non-free-firmware deb https://deb.debian.org/debian trixie-updates main non-free-firmware deb https://security.debian.org/debian-security trixie-security main non-free-firmware Pakete installieren: apt update apt install -y \ linux-image-arm64 \ raspi-firmware \ initramfs-tools \ cryptsetup-initramfs \ dropbear-initramfs \ openssh-server \ ifupdown2 \ systemd-sysv \ systemd-timesyncd \ locales \ tzdata \ ca-certificates \ curl \ git \ nano \ less \ busybox 7. Locale konfigurieren Das System erhält die deutsche UTF-8-Locale. Die Locale muss erzeugt werden, bevor sie von Shell, SSH und Programmen verwendet werden kann. Locale-Konfiguration öffnen: nano /etc/locale.gen Folgende Zeile aktivieren: de_DE.UTF-8 UTF-8 Falls ein Kommentarzeichen vor der Zeile steht, dieses entfernen. Locale erzeugen: locale-gen Systemsprüngliche Locale setzen: update-locale LANG=de_DE.UTF-8 Verfügbare Locales prüfen: locale -a Erwartete Ausgabe enthält: de_DE.utf8 LC_ALL wird nicht dauerhaft gesetzt. Programme erhalten die gewünschten Kategorieeinstellungen über LANG oder spezifische LC_-Variablen. Zeitzone einstellen Zeitzone konfigurieren: ln -sfn /usr/share/zoneinfo/Europe/Berlin /etc/localtime echo Europe/Berlin > /etc/timezone Zeitzone prüfen: date In einer chroot-Umgebung stammt die aktuelle Uhrzeit vom Linux-Host. Die eigentliche Netzwerkzeitsynchronisierung erfolgt später auf dem Raspberry Pi. 8. NTP-Zeitsynchronisierung konfigurieren Der Raspberry Pi besitzt normalerweise keine batteriegepufferte Echtzeituhr. Nach einem Neustart kann die Systemzeit deshalb falsch sein. Eine falsche Uhrzeit kann HTTPS-Verbindungen und die Zertifikatsüberprüfung von APT verhindern. Als Zeitdienst wird systemd-timesyncd verwendet. Konfigurationsverzeichnis erstellen: mkdir -p /etc/systemd/timesyncd.conf.d Konfiguration bearbeiten: nano /etc/systemd/timesyncd.conf.d/10-ntp.conf Folgenden Inhalt eintragen: [Time] NTP=162.159.200.1 162.159.200.123 time.cloudflare.com 0.de.pool.ntp.org 1.de.pool.ntp.org PollIntervalMinSec=32 PollIntervalMaxSec=2048 SaveIntervalSec=60 Die ersten beiden Adressen sind NTP-Server von Cloudflare. Sie sind auch ohne DNS-Auflösung erreichbar. Für NTP muss ausgehender UDP-Verkehr auf Port 123 erlaubt sein. Zeitdienst für den Systemstart aktivieren: systemctl enable systemd-timesyncd.service systemd-timesyncd wird beim regulären Systemstart aktiviert. Innerhalb von chroot wird kein laufender Zeitdienst benötigt. Der Dienst speichert regelmäßig einen Zeitstempel, damit die Systemzeit bei späteren Neustarts nicht immer auf einen sehr alten Wert zurückfällt. 9. Netzwerk dauerhaft konfigurieren Die Netzwerkverbindung im Initramfs ist unabhängig von der normalen Debian- Netzwerkkonfiguration. Deshalb muss eth0 auch im installierten Debian-System eingerichtet werden. Netzwerkdatei öffnen: nano /etc/network/interfaces Folgende Konfiguration verwenden: # Loopback auto lo iface lo inet loopback # Ethernet auto eth0 iface eth0 inet static address 10.100.0.61/16 gateway 10.100.0.1 # Weitere Interfaces source /etc/network/interfaces.d/* Die Management-IP liegt zunächst direkt auf eth0. Eine Linux-Bridge für virtuelle Maschinen wird erst nach erfolgreicher Einrichtung des Basissystems konfiguriert. Die gleiche Management-IP darf später nicht gleichzeitig auf eth0 und vmbr0 liegen. Netzwerkdienst aktivieren: systemctl enable networking.service DNS konfigurieren DNS-Konfiguration öffnen: nano /etc/resolv.conf Inhalt: nameserver 1.1.1.1 Diese Konfiguration setzt voraus, dass /etc/resolv.conf als reguläre Datei verwaltet wird und kein anderer Netzwerkdienst ihren Inhalt automatisch ersetzt. Für die Namensauflösung muss DNS über UDP beziehungsweise TCP Port 53 erreichbar sein. 10. Hostname konfigurieren Hostname bearbeiten: nano /etc/hostname Inhalt: darkside Hosts-Datei bearbeiten: nano /etc/hosts Folgende Einträge verwenden: 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback 10.100.0.61 darkside.home.arpa darkside Der Hostname muss auf die tatsächliche Management-IP des Servers auflösbar sein. 11. SSH-Zugang einrichten Root-Passwort setzen: passwd Für den SSH-Zugang wird ein eigener Ed25519-Administrationsschlüssel verwendet. Den öffentlichen Schlüssel auf dem administrierenden Linux-Client erzeugen: ssh-keygen -t ed25519 -a 100 \ -f ~/.ssh/id_pi4_admin \ -C "Pi4 Administration" Den privaten Schlüssel ausschließlich auf dem Linux-Client speichern. Auf dem Raspberry-Pi-Dateisystem: install -d -m 0700 /root/.ssh nano /root/.ssh/authorized_keys Den vollständigen öffentlichen Schlüssel aus id_pi4_admin.pub eintragen. Dateirechte setzen: chmod 0600 /root/.ssh/authorized_keys SSH-Konfiguration erstellen: nano /etc/ssh/sshd_config.d/10-security.conf Inhalt: PermitRootLogin prohibit-password PasswordAuthentication no KbdInteractiveAuthentication no PubkeyAuthentication yes PermitEmptyPasswords no X11Forwarding no MaxAuthTries 3 SSH-Hostkeys erzeugen, falls sie fehlen: ssh-keygen -A SSH-Konfiguration prüfen: sshd -t SSH-Dienst aktivieren: systemctl enable ssh.service 12. Initramfs-Netzwerk Für die LUKS-Entsperrung wird eth0 bereits innerhalb des Initramfs aktiviert. Datei öffnen: nano /etc/initramfs-tools/initramfs.conf Folgende Werte setzen: MODULES=most DEVICE=eth0 Die statische IP-Adresse wird über einen Kernelparameter konfiguriert. Datei öffnen: nano /etc/default/raspi-extra-cmdline Folgende Zeile eintragen: ip=10.100.0.61::10.100.0.1:255.255.0.0:darkside:eth0:none Die Zeile darf keine zusätzlichen Zeilenumbrüche enthalten. 13. Raspberry-Pi-Firmware Firmware-Konfiguration öffnen: nano /etc/default/raspi-firmware Folgende Werte setzen: ROOTPART="/dev/mapper/cryptroot" KERNEL="auto" INITRAMFS="auto" Die bestehende Konfiguration des Firmwarepakets ansonsten beibehalten. Auf einem Raspberry Pi 4 mit USB-SSD können zusätzliche USB-Treiber im Initramfs benötigt werden, insbesondere reset_raspberrypi. Datei öffnen: nano /etc/initramfs-tools/modules Das benötigte Modul ergänzen, sofern es beim installierten Kernel als Modul vorliegt: reset_raspberrypi 14. Dropbear für LUKS konfigurieren Ein separater SSH-Schlüssel wird für die Entsperrung der LUKS-Partition verwendet. Schlüssel auf dem Linux-Client erzeugen: ssh-keygen -t ed25519 -a 100 \ -f ~/.ssh/id_pi4_unlock \ -C "Pi4 LUKS Unlock" Dropbear-Verzeichnis erstellen: install -d -m 0700 /etc/dropbear/initramfs Authorized-Keys-Datei öffnen: nano /etc/dropbear/initramfs/authorized_keys Den öffentlichen Entsperrschlüssel mit folgenden Optionen eintragen: no-port-forwarding,no-agent-forwarding,no-X11-forwarding,command="/bin/cryptroot-unlock" ssh-ed25519 SSH-PUBLIC-KEY SSH-PUBLIC-KEY durch den vollständigen öffentlichen Ed25519-Schlüssel ersetzen. Dateirechte setzen: chmod 0600 /etc/dropbear/initramfs/authorized_keys Dropbear konfigurieren: nano /etc/dropbear/initramfs/dropbear.conf Inhalt: DROPBEAR_OPTIONS="-p 2222 -s -j -k -I 120" Dropbear akzeptiert damit nur Schlüsselauthentifizierung auf Port 2222. Die Hostkeys von Dropbear müssen vor dem ersten Verbindungsaufbau sicher dokumentiert und auf dem SSH-Client verifiziert werden. 15. Initramfs erstellen Installierte Kernel-Version ermitteln: ls /lib/modules Die gewünschte Kernel-Version auswählen und das passende Initramfs erstellen. Beispiel: KVER=$(ls /lib/modules | sort -V | tail -n 1) if [ -f "/boot/initrd.img-$KVER" ]; then update-initramfs -u -k "$KVER" else update-initramfs -c -k "$KVER" fi Boot-Konfiguration prüfen: cat /boot/firmware/config.txt cat /boot/firmware/cmdline.txt cmdline.txt muss auf /dev/mapper/cryptroot verweisen und den statischen ip-Parameter enthalten. Initramfs-Inhalt überprüfen: lsinitramfs "/boot/initrd.img-$KVER" | less Besonders die Cryptsetup-Komponenten, Dropbear, authorized_keys, cryptroot-unlock, USB- und Ethernet-Treiber kontrollieren. 16. Installation abschließen chroot verlassen: exit Dateisysteme kontrollieren: findmnt -R /mnt/Temp/1 Alle Ziel-Mountpoints aushängen: umount -R /mnt/Temp/1 LUKS schließen: cryptsetup close cryptroot Schreibvorgänge abschließen: sync Die USB-SSD ist jetzt für den ersten Boot vorbereitet. 17. LUKS über SSH entsperren Nach dem Start sollte Dropbear im Initramfs auf Port 2222 erreichbar sein. SSH-Verbindung herstellen: ssh -t \ -p 2222 \ -i ~/.ssh/id_pi4_unlock \ root@10.100.0.61 Den SSH-Hostkey mit dem zuvor dokumentierten Fingerprint vergleichen. Anschließend die LUKS-Passphrase eingeben. Nach erfolgreicher Entsperrung startet das normale Debian-System. Reguläre SSH-Verbindung: ssh -i ~/.ssh/id_pi4_admin root@10.100.0.61 18. Ersten Systemstart überprüfen Netzwerk kontrollieren: ip -br address ip route show default Erwartete Netzwerkkonfiguration: eth0 UP 10.100.0.61/16 Namensauflösung prüfen: getent ahostsv4 deb.debian.org Zeitsynchronisierung kontrollieren Systemzeit anzeigen: date timedatectl status Zeitdienst aktivieren: systemctl enable --now systemd-timesyncd Synchronisierungsstatus anzeigen: timedatectl timesync-status timedatectl show -p NTPSynchronized Erwarteter Status nach erfolgreicher Synchronisierung: NTPSynchronized=yes Erst nach erfolgreicher Zeitsynchronisierung Paketdownloads und größere Systemupdates durchführen. 19. Fehlerbehebung: HTTPS-Zertifikate Folgende Fehlermeldung kann auftreten, wenn die Systemzeit falsch ist: SSL connection failed: certificate verify failed Aktuelle Zeit überprüfen: date -u NTP-Dienst kontrollieren: systemctl status systemd-timesyncd --no-pager timedatectl timesync-status Falls NTP noch nicht zur Verfügung steht und die Uhr stark falsch geht, kann die Uhrzeit vorübergehend manuell auf einen vertrauenswürdigen aktuellen UTC-Wert gesetzt werden. Beispiel mit dem aktuellen UTC-Zeitwert des Linux-Clients: date -u -s "JAHR-MONAT-TAG STUNDE:MINUTE:SEKUNDE" Die Platzhalter müssen durch eine tatsächlich aktuelle UTC-Zeit ersetzt werden. Nach Korrektur der Uhrzeit kann APT erneut verwendet werden: apt update Falls der TLS-Fehler weiterhin besteht, anschließend CA-Zertifikate, Paketquellen und mögliche TLS-Interception prüfen. Die HTTPS-Zertifikatsprüfung darf nicht deaktiviert werden. 20. Fehlerbehebung: Locale Bei folgender Meldung fehlt die gewünschte Locale oder die SSH-Umgebung verwendet nicht unterstützte Locale-Werte: setlocale: LC_CTYPE: cannot change locale (de_DE.UTF-8) Verfügbare Locales überprüfen: locale -a Locale-Konfiguration öffnen: nano /etc/locale.gen Folgende Zeile aktivieren: de_DE.UTF-8 UTF-8 Locale neu erzeugen: locale-gen Standardeinstellung aktualisieren: update-locale LANG=de_DE.UTF-8 Anschließend eine neue SSH-Sitzung öffnen. Die setlocale-Warnungen sollten verschwinden. 21. Fehlerbehebung: Netzwerk Falls das Netzwerk im Initramfs funktioniert, aber nach der LUKS-Entsperrung ausfällt, die reguläre Netzwerkkonfiguration prüfen. cat /etc/network/interfaces ip -br address ip route /etc/network/interfaces muss die statische Konfiguration von eth0 enthalten. Bei einem beschädigten oder unvollständigen System kann die verschlüsselte SSD auf einem anderen Linux-PC entschlüsselt und die Konfigurationsdatei repariert werden. 22. Proxmox VE vorbereiten Erst wenn Debian, LUKS, SSH, Netzwerk und Zeitsynchronisierung zuverlässig funktionieren, wird die Virtualisierungsplattform eingerichtet. Proxmox VE 9 stellt ARM64-Pakete bereit. Der Raspberry Pi 4 ist als Plattform jedoch nicht Teil der unterstützten Proxmox-Hardware. Vor einer Installation müssen insbesondere die Paketabhängigkeiten und die Auswirkungen auf den Raspberry-Pi-Kernel geprüft werden. Den funktionierenden Bootkernel, raspi-firmware, cryptsetup-initramfs und dropbear-initramfs nicht unkontrolliert ersetzen oder entfernen. Vor dem Einrichten einer Proxmox-Bridge muss die bisherige Management-IP von eth0 auf vmbr0 umgestellt werden. Dabei darf die IP nicht doppelt vergeben werden. Eine Aufnahme in einen bestehenden Proxmox-Cluster erfolgt erst nach vollständiger Funktionsprüfung. 23. Dokumentation Debian – Raspberry Pi 4 systemd-timesyncd – Konfiguration Debian – locale-gen Cryptsetup – Remote Unlock Cloudflare NTP Proxmox VE Dokumentation