Installation von NixOS auf einer verschlüsselten Partition (LUKS)

Datum

Ich fand die Idee, welche hinter NixOS steht interessant und wollte es von daher auch direkt mit der entsprechenden Sicherheit testen und deshalb sollte die Installation, wie bei anderen Linux-Distros auch, auf einer verschlüsselten Partition stattfinden und beim booten per Passwort entsprechend entschlüsselt werden.
Leider war dieses Vorhaben nicht so leicht wie gedacht, da ich es nicht hinbekommen habe dieses Vorhaben mit GPT/EFI zu realisieren. Es gab auch recht wenig Tutorials zu dieser Thematik welche wirklich geholfen hätten…

Von daher bin ich den (für mich) einfacheren Ansatz gegangen und habe einen „normalen“ MBR mit grub2 verwendet…

Vorbereitungen

Wir beginnen, indem wir die NixOS-LiveCD laden und warten bis wir die root-Shell haben…

Als erstes stellen wir uns mal ein deutsches Tastatur-Layout ein, dass passiert mit

[root@nixos:~]# loadkeys de

Nun müssen wir prüfen ob wir GPT oder MBR verwenden, dazu verwenden wir z.B. gdisk

[root@nixos:~]# gdisk -l /dev/sda
GPT fdisk (gdisk) version 1.0.1

Partition table scan:
  MBR: MBR only
  BSD: not present
  APM: not present
  GPT: not present


***************************************************************
Found invalid GPT and valid MBR; converting MBR to GPT format
in memory. 
***************************************************************

Sollte es bei euch anders aussehen, dann sollte entsprechende Maßnahmen ergriffen um das zu ändern.
Wenn jemand eine praktikable Möglichkeit kennt hierbei EFI zu verwenden, lasst es mich wissen

Erstellen der Partitionen

Nun erstellen wir uns eine 500MB große /boot-Partition und der Rest der Festplatte wird ein LUKS verschlüsseltes physical volume im LVM.
Hierbei kann jeder das Tool seiner Wahl verwenden… üblich sind: gdisk, cfdisk, parted, etc.

Verwendung von gdisk:

[root@nixos:~]# gdisk /dev/sda

o (erstellt eine neue leere Partitions-Tabelle) <— nur für den Fall das es notwendig ist
n (neue Partition hinzufügen, 500M, Typ: ef00 EFI)
n (neue Partition hinzufügen, restlicher Platz, Typ: 8300 Linux LVM)
w (Partitions-Tabelle schreiben und gdisk beenden)

Verschlüsseln der Partition

Nun erstellen wir eine mit LUKS verschlüsselte Partition:

[root@nixos:~]# cryptsetup luksFormat -c aes-xts-plain64 -s 512 -h sha512 -y /dev/sda2

Dieser Befehl erstellt eine verschlüsselte Partition in /dev/sda2. Der Parameter -c bestimmt den Algorithmus, -y lässt cryptsetup das Passwort zweimal abfragen (was in Verbindung mit Key-Files sinnlos wäre) und -s bestimmt die Länge des Schlüssels. luksFormat legt fest, dass der Header nach dem LUKS-Standard erstellt wird. Zur Sicherheitsbestätigung wird die Eingabe von YES gefordert. Also wirklich YES in Großbuchstaben (engl. uppercase) und nicht y, Y oder yes.
Alternativ zu AES ist es möglich, den Verschlüsselungsalgorithmus Twofish oder Serpent zu verwenden. Dazu wird aes-xts-plain64 durch twofish-xts-plain64 bzw. serpent-xts-plain64 ersetzt.

[root@nixos:~]# cryptsetup luksFormat -c aes-xts-plain64 -s 512 -h sha512 -y /dev/sda2
WARNING!
========
This will overwrite data on /dev/sda2 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter passphrase: 
Verify passphrase: 

…und nun entschlüsseln wir das ganze um die Installation fortzuführen…

[root@nixos:~]# cryptsetup luksOpen /dev/sda2 enc-pv
Enter passphrase for /dev/sda2: 

Jetzt erstellen wir 2 logical Volumes, eine 2GB Swap-Partition und der Rest wird zum Root-Dateisystem:

[root@nixos:~]# pvcreate /dev/mapper/enc-pv
  Physical volume "/dev/mapper/enc-pv" successfully created.

[root@nixos:~]# vgcreate vg /dev/mapper/enc-pv
  Volume group "vg" successfully created

[root@nixos:~]# lvcreate -L 2G -n swap vg
  Logical volume "swap" created.

[root@nixos:~]# lvcreate -l '100%FREE' -n root vg
  Logical volume "root" created.

Anschließend bringen wir das noch in das richtige Format (FAT für /boot und ext4 für das Root-Dateisystem:

[root@nixos:~]# mkfs.fat /dev/sda1
mkfs.fat 4.1 (2017-01-24)

[root@nixos:~]# mkfs.ext4 -L root /dev/vg/root
mke2fs 1.43.4 (31-Jan-2017)
Creating filesystem with 1443840 4k blocks and 361440 inodes
Filesystem UUID: c15fe8a3-c040-429c-af22-5d75cde0460a
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912, 819200, 884736

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (16384 blocks): done
Writing superblocks and filesystem accounting information: done 

Und nun noch den Swap einrichten mit:

[root@nixos:~]# mkswap -L swap /dev/vg/swap
Setting up swapspace version 1, size = 2 GiB (2147479552 bytes)
LABEL=swap, UUID=5b3635fc-66ae-41d5-ba04-913691af647e

Um NixOS auf unser Dateisystem zu bekommen mounten wir es unter /mnt und die Boot-Partition entsprechend unter /mnt/boot:

[root@nixos:~]# mount /dev/vg/root /mnt
[root@nixos:~]# mkdir /mnt/boot
[root@nixos:~]# mount /dev/sda1 /mnt/boot
[root@nixos:~]# swapon /dev/vg/swap

Konfiguration

Der Clou an NixOS ist ja die zentrale Konfigurationsdatei configuration.nix und diese lassen wir uns mit folgendem Befehl erstellen.

[root@nixos:~]# nixos-generate-config --root /mnt
writing /mnt/etc/nixos/hardware-configuration.nix...
writing /mnt/etc/nixos/configuration.nix...

In der hardware-configuration.nix sollten die entsprechenden UUIDs bereits erkannt und eingetragen sein, so das wir uns nur um die configuration.nix kümmern brauchen.

Hierbei ist es wichtig zu wissen, dass NixOS quasi eine eigene Sprache mit entsprechender Syntax entwickelt hat, in der man so ziemlich alles einstellen kann. Dabei sind die meisten Punkte selbsterklärend.

Eine recht simple Konfiguration (ohne XServer) sieht z.B. wie folgt aus:

 { config, pkgs, ... }:

{
  imports =
      ./hardware-configuration.nix
    ];
  boot.loader.grub.enable = true;
  boot.loader.grub.version = 2;
  boot.loader.grub.device = "/dev/sda";
  boot.initrd.luks.devices = [
    {
      name = "root";
      device = "/dev/disk/by-uuid/7b090eb0-7784-45d1-a88b-33535031ef82";
      preLVM = true;
      allowDiscards = true;
    }
  ];

  i18n = {
    consoleKeyMap = "de";
    defaultLocale = "de_DE.UTF-8";
  };
  time.timeZone = "Europe/Berlin";
  environment.systemPackages = with pkgs; [
     wget vim networkmanager
  ];
  services.openssh.enable = true;
}

Um herauszufinden welche UUID für das LUKS-Device einzusetzen ist, verwendet man:

[root@nixos:~]# blkid | grep LUKS
/dev/sda2: UUID="7b090eb0-7784-45d1-a88b-33535031ef82" TYPE="crypto_LUKS" PARTUUID="35a00ded-02"

Um gleich nach der Installation einen entsprechenden Benutzer zu haben fügt man folgenden Abschnitt in die configuration.nix ein:

  # Define a user account. Don't forget to set a password with ‘passwd’.
  users.extraUsers.rasputin = {
     isNormalUser = true;
     uid = 1000;
  };

Hierbei könnte man noch extra Optionen angeben wie z.B. spezielle Gruppen zu denen der neue Benutzer automatisch hinzugefügt werden soll:

  # Define a user account. Don't forget to set a password with ‘passwd’.
  users.extraUsers.rasputin = {
     isNormalUser = true;
     uid = 1000;
     extraGroups = [ "wheel" ];
  };

Wie der Kommentar bereits mitteilt, sollte noch per passwd ein entsprechendes Passwort vergeben werden.

Installation

Nachdem alles in der configuration.nix eingetragen und abgespeichert ist, wird die Installation mit folgendem Befehl gestartet:

[root@nixos:~]# nixos-install

und nach erfolgreicher Installation kann man per reboot in das neue System wechseln.

Autor
Kategorien Betriebssysteme, Linux

PRTG Map