/ Server

Home-Server MKII [3] - Storage

Mit der wichtigste Grund für meinen Server ist mein Speicherplatz-Bedarf. Die 6TB im alten Server reichten einfach nicht mehr aus, also musste deutlich mehr Speicher her - natürlich redundant und verschlüsselt!

Dieses Mal möchte ich etwas tiefere Einblicke in die Konfiguration geben, da ich mir hier viel habe zusammensuchen müssen, doch zuerst wieder einige Infos vorweg.

Die Situation

Momentan habe ich insgesamt 6 HDDs zur Verfügung - zweimal 2TB und viermal 4TB - und der Server bietet acht Slots, also bleiben zwei davon erst einmal frei. Hier kommen später noch zwei 4TB HDDs rein.
Wie bei meinem alten Server sollen die Platten im RAID laufen. Da ich aber flexibel bleiben möchte, kommt auch noch ein LVM zum Einsatz. Es bilden also immer zwei Festplatten ein RAID1-Device und diese dann wiederum die Basis für's LVM. In letztem schlummert dann wiederum der Crypto-Container und darin liegt die XFS-Partition mit meinen Daten.
Da das alles verwirrend klingt, hier wieder das Schema:

Festplatten vorbereiten

Konkret benutze ich drei RAID1 für das Storage-System, deren Festplatten ich im Gehäuse paarweise eingesetzt habe. Daher muss ich beim Einrichten auf die korrekten Laufwerke achten. Daher ist mein erster Schritt die zu den entsprechenden Disk Identifiern gehörenden Gerätedateien zu suchen. Das geht mit recht simpel mit

fdisk -l

Hier wird pro Festplatte in etwa folgendes ausgegeben:

Disk /dev/sde: 3,7 TiB, 4000787030016 bytes, 7814037168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk identifier: E4493D28-1C15-4C87-8443-FCF6C421542F

In diesem Fall hat die HDD mit dem Identifier E4493D28-1C15-4C87-8443-FCF6C421542F die Gerätedatei /dev/sde.

Soweit so gut, bereiten wir die Festplatte für's RAID vor und erstellen als erstes eine leere Partitionstabelle:

sudo parted /dev/sde mklabel gpt

Anschließend wird eine Partition angelegt:

sudo parted -a optimal -- /dev/sde mkpart primary 0% 100%

Und dann wird diese als RAID-Partition markiert:

sudo parted /dev/sde set 1 raid on

Natürlich muss das für jede der Festplatten erledigt werden. Ist das geschehen, können wir endlich das RAID selbst anlegen.

RAID einrichten

Insgesamt werden bei mir drei RAID1 eingerichtet. Da das Device md0 schon für das System-RAID verbraten wurde, mache ich mit den RAIDs md10, md11 und md13 (md steht für mirror device).
(Das Device md12 habe ich übrigens ausgelassen, da ich dieses mit den kommenden beiden 4TB HDDs erstellen will.)

Als Beispiel für die Erstellung des RAID, hier der Befehl für die Platten sde und sdf.

sudo mdadm --create /dev/md10 --auto md --level=1 --raid-devices=2 /dev/sde1 /dev/sdf1

Die anderen beiden RAID md11 und md13 werden dann entsprechend mit den anderen Festplatten erstellt.

LVM

Jetzt kann es mit LVM weitergehen. Den Logical Volume Manager benutze ich, um eine einzige Partition über alle RAID-Devices spannen zu können.
LVM unterscheidet hier zwischen verschiedenen Begriffen.

Physical Extent (PE) ist für meine Zwecke erstmal nicht relevant. Für Neugierige sei ubuntuusers.de empfohlen.

Physical Volume (PV) bezeichnet im konkreten Fall ein einzelnes RAID-Device.

Volume Group (VG) ist eine Art Pool für die PVs.

Logical Volume (LV) stellt das Volume dar, dass hier später den LUKS-Container (Verschlüsselung) beinhalten wird.

Als erstes müssen die Mirror-Devices als PVs angelegt werden, das kann in einem Befehl geschehen:

pvcreate /dev/md10 /dev/md11 /dev/md13

Dann werden die PVs einer neuen VG storage-vg zugeordnet, die dabei erstellt wird:

vgcreate storage-vg /dev/md10 /dev/md11 /dev/md13

Abschließend wird ein LV storage über den gesamten Speicherplatz erstellt:

lvcreate -l +100%FREE -n storage storage-vg

Fertig.

LUKS

LUKS dient dazu, die gesamte Storage-Partition zu verschlüsseln, damit Unbefugte keinen Zugriff auf meine Daten erhalten. Allerdings hat mich die Einrichtung von LUKS wohl am meisten Zeit gekostet, also Step by Step.

Bevor wir mit der eigentlich Konfiguration anfangen, wird der Anfang der Partition mit Zufallsbytes überschrieben:

sudo dd if=/dev/urandom bs=200M count=1 of=/dev/storage-vg/storage

Dann kann die Partition verschlüsselt werden:

sudo cryptsetup luksFormat -c aes-xts-plain64 -s 512 -h sha512 -y /dev/storage-vg/storage

Wichtig zu beachten ist, dass bei der Sicherheitsfrage auch wirklich YES und nicht nur yes oder y eingegeben wird. Außerdem sollte man sich das eingegeben Password auch merken ;-)

Jetzt kann der Container folgendermaßen also virtuelles Gerät storage geöffnet werden:

sudo cryptsetup luksOpen /dev/storage-vg/storage storage  

Nun steht unsere Partition unter /dev/mapper/storage zur Verfügung und kann mit dem Dateisystem xfs versehen werden:

sudo mkfs.xfs /dev/mapper/storage

Und zu guter Letzt wird das Dateisystem nach /media/storage gemountet:

sudo mount /dev/mapper/storage /media/storage

Sollte hierbei ein Fehler angezeigt werden, muss höchst wahrscheinlich noch der Mount-Point angelegt werden:

sudo mkdir /media/storage

Ausgehängt wird übrigens mit:

sudo umount /media/storage

Und der Container geschlossen per:

sudo cryptsetup luksClose storage

Keyfile

Damit die Storage-Partition nach einem Reboot automatisch gestartet und eingehängt werden kann, müssen noch einige Schritte erledigt werden, beispielsweise sollte die Verschlüsselung per Keyfile geöffnet werden können. Natürlich ist ein Keyfile nicht so sicher, wie ein Passphrase. Allerdings liegt dieses bei mir im ebenfalls verschlüsselten /root-Verzeichnis.

Zuerst muss ein Keyfile erzeugt werden:

sudo tr -dc '0-9a-zA-Z' </dev/urandom | head -c 32 > /root/luks.keyfile

Hierbei wird ein zufälliges, 32-stelliges Passwort in die Datei /root/luks.keyfile geschrieben.

Anschließend kann die Datei in die LUKS-Konfiguration aufgenommen werden:

sudo cryptsetup luksAddKey /dev/storage-vg/storage /root/luks.keyfile

Dabei muss das vorhin vergebene Passwort für den Container eingegeben werden.

Prinzipiell kann ein Container auch nur mit einem Keyfile erstellt werden, ich habe aber aus Backup-Gründen das Keyfile erst später hinzugefügt. So kann ich im Notfall immer noch auf das Passwort zurückgreifen.

Nun kann der LUKS-Container auch folgendermaßen geöffnet werden:

sudo cryptsetup luksOpen /dev/storage-vg/storage storage --key-file /root/luks.keyfile

Autostart

Eigentlich werden Partitionen nach einem Reboot automatisch durch /etc/fstab gemountet und verschlüsselte Partitionen vorher per /etc/crypttab gestartet. Dies führte bei mir allerdings dazu, dass das gesamte System nicht mehr richtig startet.
Grund hierfür ist die Tatsache, dass systemd beim Boot-Vorgang folgende Reihenfolge abarbeitet:

  1. LVM
  2. RAID
  3. LUKS

Da LVM aber auf RAID-Devices zugreifen muss, kann das entsprechende LV nicht rechtzeitig gestartet werden und LUKS bricht beim Versuch den Container zu entschlüsseln, den gesamten Boot-Vorgang ab und versetzt das System in den Emergency-Mode. Also benötige ich eine andere Lösung.
Meine Wahl fiel auf ein Shell-Script, das über rc.local gestartet wird.

Konkrekt habe ich das Script /usr/local/bin/mount-crypto.sh mit folgendem Inhalt erstellt:

#!/bin/bash
device=/dev/storage-vg/storage
mapper=storage
mountpoint=/media/storage
keyfile=/root/luks.keyfile

cryptsetup luksOpen "$device" "$mapper" --key-file "$keyfile"
mount /dev/mapper/"$mapper" "$mountpoint"

Und dieses ausführbar gemacht:

sudo chmod +x /usr/local/bin/mount-crypto.sh

Nun muss noch die folgende Zeile in die Datei /etc/rc.local eingefügt vor

exit 0

werden:

/usr/local/bin/mount-crypto.sh

Fertig!

Nach einem Reboot, wird die Storage-Partition automatisch entschlüsselt und unter /media/storage eingebunden.

In diesem Sinne, bis dann!