Récemment, j’ai découvert nix : un gestionnaire de paquet atypique mettant l’effort sur la reproductibilité des builds. Contrairement à ceux dont j’ai l’habitude, nix permet d’avoir plusieurs versions d’un même programme ou d’une même bibliothèque en parallèle.

Et il existe nixos, une distribution basée sur nix. Ce billet est un pense-bête pour le moi du futur concernant l’installation de nixos avec des partitions chiffrées.

Le matériel

Il y a quelques temps de cela, de passage dans un magasin de bricolage, je remarque un bac de matériel électronique destiné à la décharge. Et au fond dudit bac, un laptop avec son chargeur 😲 qui a étrangement terminé dans mon sac. Bon, et bien merci à la personne qui a cru bon de jeter son ordinateur juste parce que l’écran était fissuré (refermé sur un stylo ?). Un coup de tournevis plus tard, la base est débarassée de son écran et me voici avec une machine headless pour faire mes tests.

N’hésitez pas à effacer le contenu de vos disques durs avant de vous débarasser de vos vielles machines. Il y avait encore toute la vie de l’ancienne propriétaire sur des partitions non chiffrées.

Bref, voici ce que raconte la machine en question directement depuis l’ISO de nixos :

[nixos@nixos:~]$ nix-shell -p neofetch --run "neofetch --off"
nixos@nixos
-----------
OS: NixOS 22.11.4079.c568239bcc9 (Raccoon) x86_64
Host: Acer ZORO_BH
Kernel: 5.15.110
Uptime: 7 mins
Packages: 335 (nix-system)
Shell: bash 5.1.16
Resolution: 1920x1080
Terminal: /dev/pts/0
CPU: Intel i5-4210U (4) @ 2.700GHz
GPU: Intel Haswell-ULT
GPU: NVIDIA GeForce 920M
Memory: 494MiB / 3851MiB

Pour une machine gratuite, je ne vais pas me plaindre 🤷 Quoi que, allez, la prochaine fois, merci de me laisser un ordinateur avec un SSD 🙏

Le logiciel

Nous sommes le lundi 8 mai 2023 et la version la plus à jour proposée sur la page des téléchargements de nixos est la 22.11.

Comme dit précédemment, cette machine n’a pas/plus d’écran et sera utilisée comme serveur distant. Je prends donc la version Minimal ISO image pour le processeur x86_64 qui l’équipe.

Cette image est assez petite pour tenir sur une clé USB de 1Go. Ça tombe bien, j’en ai une qui traîne quelque part 👌

dd if=${ISO PATH} of=${USB PATH} bs=4M conv=fsync status=progress

Plus qu’à démarrer sur ladite clé pour se retrouver dans une console avec l’utilisateur nixos. Cet utilisateur n’a pas de mot de passe et fait partie du groupe wheel : il peut donc utiliser sudo 💪

Partitions

Il est temps de créer les partitions sur le disque dur. Pour savoir lequel viser, il suffit d’utiliser lsblk ou fdisk -l. Pour ma part, il s’agit de /dev/sda.

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

Welcome to fdisk (util-linux 2.38.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): g
Created a new GPT disklabel (GUID: 77F5FB82-E975-0445-A972-A718837C60E4).

Command (m for help): n
Partition number (1-128, default 1):
First sector (2048-1953525134, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-1953525134, default 1953523711): +1G

Created a new partition 1 of type 'Linux filesystem' and of size 1 GiB.

Command (m for help): t
Selected partition 1
Partition type or alias (type L to list all): 1
Changed type of partition 'Linux filesystem' to 'EFI System'.

Command (m for help): n
Partition number (2-128, default 2):
First sector (2099200-1953525134, default 2099200):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2099200-1953525134, default 1953523711):

Created a new partition 2 of type 'Linux filesystem' and of size 930.5 GiB.

Command (m for help): t
Partition number (1,2, default 2):
Partition type or alias (type L to list all): 43

Changed type of partition 'Linux filesystem' to 'Linux LVM'.

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

Les lignes importantes sont surlignées. Mais dans l’ensemble :

  1. Formater le disque avec g,
  2. Créer deux partitions avec n,
  3. Leur appliquer les types EFI et LVN avec t, le bon numéro et le bon code.
  4. Écrire les modifications sur le disque avec w.

Au final, le disque est partitionné ainsi :

[root@nixos:~]# fdisk -l /dev/sda
Disk /dev/sda: 931.51 GiB, 1000204886016 bytes, 1953525168 sectors
Disk model: TOSHIBA MQ01ABD1
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 77F5FB82-E975-0445-A972-A718837C60E4

Device       Start        End    Sectors   Size Type
/dev/sda1     2048    2099199    2097152     1G EFI System
/dev/sda2  2099200 1953523711 1951424512 930.5G Linux LVM

Chiffrement

[root@nixos:~]# cryptsetup luksFormat /dev/sda2

WARNING!
========
This will overwrite data on /dev/sda2 irrevocably.

Are you sure? (Type 'yes' in capital letters): YES
Enter passphrase for /dev/sda2:
Verify passphrase:

[root@nixos:~]# cryptsetup open /dev/sda2 nixos
Enter passphrase for /dev/sda2:

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

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

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

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

Formatage

[root@nixos:~]# mkfs.vfat -n boot /dev/sda1
mkfs.fat 4.2 (2021-01-31)

[root@nixos:~]# mkfs.ext4 -L nixos /dev/nixos/root
mke2fs 1.46.5 (30-Dec-2021)
Creating filesystem with 241825792 4k blocks and 60456960 inodes
Filesystem UUID: 85d51c5c-170c-45cf-965e-7d40459365fe
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
        102400000, 214990848

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


[root@nixos:~]# mkswap -L swap /dev/nixos/swap
Setting up swapspace version 1, size = 8 GiB (8589930496 bytes)
LABEL=swap, UUID=0e61b7f6-6968-4a22-b065-aa9979a1597f

[root@nixos:~]# swapon /dev/nixos/swap

Montage des partitions

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

Génération et édition de la configuration

[root@nixos:~]# nixos-generate-config --root /mnt
writing /mnt/etc/nixos/hardware-configuration.nix...
writing /mnt/etc/nixos/configuration.nix...
For more hardware-specific settings, see https://github.com/NixOS/nixos-hardware.
[root@nixos:~]# vim /mnt/etc/nixos/configuration.nix

Il est nécessaire d’indiquer à nixos qu’il faut déchiffrer la partition au démarrage de la machine :

boot.initrd.luks.devices = {
    root = {
        device = "/dev/sda2";
        preLVM = true;
    };
};

Pour le reste, il faut lire chaque bloc, comprendre et modifier en fonction du besoin.

Une note cependant concernant la gestion des utilisateurs : il est possible de stipuler des clés ssh publiques pour permettre la connexion distante sans mot de passe.

users.users.pcoves = {
    isNormalUser = true;
    extraGroups = [ "wheel" ];
    openssh.authorizedKeys.keys = [ ${KEY-0} ... ${KEY-N} ];
};

Je ne renseigne pas de mot de passe dans le fichier de configuration. Je le changerai par la suite grâce au compte root via la commande su.

Installation

[root@nixos:~]# nixos-install

En cas de succès, le mot de passe pour le compte root sera demandé tout à la fin.

[root@nixos:~]# reboot

Conclusion

C’est la première fois que je joue avec LVM sur LUKS. J’avais l’habitude de faire plusieurs partitions LUKS séparées et de réglages complexes pour le déchiffrement. Je dois avouer que la présente solution me semble nettement plus simple et aisée à maintenir.

Plus qu’à intégrer tout ça dans une configuration générique avec home-manager pour la suite.

Resources