Systemd-boot, un autre bootloader🔗

Posted by Médéric Ribreux 🗓 In blog/ Sysadmin/

#dev #system #boot

Introduction

D'une manière générale, j'aime bien systemd. C'est plutôt bien fait et ça a le mérite d'apporter un peu d'unité dans l'administration d'un système. Le reproche que l'on fait, c'est que systemd s'installe un peu partout, dans des rôles qui dépassent celui du système d'initialisation d'un ordinateur.

Néanmoins, ça ne me gène pas. Systemd revisite des programmes ou des concepts, mais souvent c'est fait de telle manière que ça n'est pas compliqué à comprendre et à maîtriser, une fois qu'on a été formé au système d'init. Par exemple, les fichiers de configuration sont souvent proches, leur emplacement aussi, leur découpage et leur répartition également.

Dans les derniers trucs en date que j'ai essayé sur systemd, il y a un bootloader: systemd-boot. Son spectre est assez limité: il gère uniquement les systèmes UEFI sur l'architecture x86_64. Grub, même dans sa version 2, gère encore le mode de boot BIOS (avant UEFI).

J'ai eu besoin de reconfigurer une vieille machine et ça m'a donné l'occasion de tester systemd-boot. J'ai trouvé que son approche était intéressante et je vais vous présenter comment faire pour l'installer sous Debian Bookworm et comment l'utiliser par la suite.

Installation

Sous Debian Bookworm, systemd-boot n'est pas installé par défaut avec systemd, il faut installer le paquet dédié:

# Sous root
apt install systemd-boot

Attention, installer ce paquet installe le bootloader sur votre système et configure le firmware UEFI de la machine d'utiliser cette entrée de bootloader en premier. L'entrée de bootloader de systemd se nomme "Linux Boot Manager". Et malheureusement, si vous avez activé SecureBoot, votre système ne se chargera pas (enfin du moins, pas systemd-boot), car par défaut sous Debian Bookworm, systemd-boot n'est pas signé.

Fonctionnement

Globalement, la commande qui installe le bootloader de systemd-boot se contente de copier le fichier /usr/lib/systemd/boot/efi/systemd-bootx64.efi dans la partition EFI. On le retrouve dans /boot/efi/EFI/systemd/ et sous l'entrée Linux Boot System.

systemd-bootx64 est un exécutable EFI qui fait le job de lancer le système. Concrètement, il va lire la configuration dans la partition EFI, à l'emplacement /boot/efi/loader/. Il lit d'abord tous les fichiers avec une extension .conf, situés dans le répertoire entries puis le fichier de configuration principal qui se nomme loader.conf.

Je vous laisse lire la doc très bien faîte de ces deux fichiers de configuration (via man loader.conf).

Toutefois, je peux vous donner quelques astuces.

Afficher le menu

Par défaut, la configuration Debian par défaut de systemd-boot ne fait pas afficher le menu (ce qui est con). Pour l'activer, il suffit de mettre un timeout dans le fichier loader.conf:

timeout 3

Je mets 3 secondes par défaut, car c'est le temps suffisant pour que je puisse voir le menu apparaitre et interagir dessus, sans prendre des plombes pour le boot par défaut.

Booter sous MS Windows

Si vous souhaitez booter automatiquement sous Windows, vous n'avez pas besoin d'ajouter un fichier d'entrée dans le répertoire entries. systemd-boot recherche en dur le bootloader de Windows et l'insère automatiquement dans sa configuration. Vous pouvez essayer la commande bootctl list et vous verrez une entrée de type Automatic qui se nomme Windows Boot Manager et qui a pour id auto-windows. Donc, pour booter par défaut sous windows, il suffit d'avoir la ligne qui suit dans le fichier loader.conf:

default auto-windows

Assurez-vous de ne pas avoir la variable auto-entries mise à false dans ce fichier, sinon les entrée automatiques ne sont pas générées.

Secure Boot

Comme dit juste au dessus, systemd-boot n'est pas signé. Donc si vous avez activé SecureBoot dans votre BIOS, ça ne chargera pas systemd-boot. Pour cela, il faut signer le programme.

Le projet Debian n'a pas vraiment l'intention de signer systemd-boot par défaut (ce qui est dommage à mon point de vue). Donc on va le faire à leur place, mais avec les outils fournis par Debian.

Pour comprendre comment ça fonctionne, il faut savoir qu'en fait, Debian installe par défaut le programme shim qui est signé avec la clef de Microsoft. Si vous ne me croyez pas, vérifiez-le par vous-même:

# Sous root
apt install sbsigntool
sbverify /boot/efi/EFI/debian/shimx64.efi
signature 1
image signature issuers:
 - /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Corporation UEFI CA 2011
image signature certificates:
 - subject: /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Windows UEFI Driver Publisher
   issuer:  /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Corporation UEFI CA 2011
 - subject: /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Corporation UEFI CA 2011
   issuer:  /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/CN=Microsoft Corporation Third Party Marketplace Root

Shim est un bootloader un peu spécial, il permet de chainer vers un autre bootloader qui lui même doit être signé avec une clef gérée/acceptée par shim. Cette clef n'est pas forcément celle de Microsoft, elle peut, bien au contraire être celle de votre choix, à partir du moment où vous l'ajoutez à la conf de shim. L'utilitaire pour configurer shim se nomme mokutil du paquet du même nom.

Comme son nom l'indique, mokutil permet de gérer ce qu'on appelle une Machine Owner Key (MOK).

# Sous root
sbsign --key /var/lib/shim-signed/mok/MOK.priv \
  --cert /var/lib/shim-signed/mok/MOK.pem \
  --output /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed \
  /usr/lib/systemd/boot/efi/systemd-bootx64.efi

Pourquoi j'ai indiqué de signer le programme livré par le package systemd-boot-efi ? C'est parce que bootctl install ou update utilise le fichier .signed s'il est présent plutôt que le fichier non signé.

Maintenant, il reste à dire à shim d'utiliser systemd-boot à la place de grub. Et c'est que ça devient crade. shim est codé en interne pour chaîner vers grubx64.efi. Donc, le seul moyen actuel, c'est d'écraser ce fichier avec notre version signée de systemd-boot. Ok, c'est dangereux, car si vous merdez cette étape, par exemple en mettant la version non signée, alors, votre système Debian ne pourra plus booter.

Enfin, il reste à automatiser tout ça. Vous ne voudriez pas voir votre belle config ne pas être mise à jour en cas d'update de systemd-boot. Pour cela, nous allons créer un override du service systemd-boot-update.

Pour cela, il suffit d'éditer la configuration du service avec la commande qui suit:

# Sous root
systemctl edit systemd-boot-update.service

et d'ajouter les lignes qui suivent en haut:

[Service]
ExecStartPost=+/usr/bin/sbsign --key /var/lib/shim-signed/mok/MOK.priv \
  --cert /var/lib/shim-signed/mok/MOK.pem \
  --output /boot/efi/EFI/systemd/systemd-bootx64.efi.signed \
  /usr/lib/system /boot/efi/systemd-bootx64.efi
ExecStartPost=cp /boot/efi/EFI/systemd/systemd-bootx64.efi.signed /boot/efi/EFI/debian/grubx64.efi

Ensuite, il suffit de prendre en compte votre nouveau service:

# Sous root
systemctl daemon-reload
systemctl start systemd-boot-update.service

Normalement, vous devriez voir un fichier /boot/efi/EFI/systemd/systemd-bootx64.efi.signedet il doit être copié pour écraser grubx64.efi.

Conclusions

Bon, systemd-boot a l'avantage d'être assez léger et d'offrir des outils avec un nom standard (bootctl par exemple). Les emplacements de fichiers sont simples à comprendre, la configuration est dans la partition EFI et non éclatée dans /etc/grub.d et /etc/default/grub.

Par contre, systemd-boot sous Debian impose une signature pré-alable alors que grub2 est signé et utilise le shim. Donc systemd-boot avec SecureBoot sous Debian est un poil plus complexe et demande plus d'intervention. Mais il s'agit d'un simple override de 3 lignes, pas la mort non plus.

Si vous êtes satisfait de systemd-boot, après une certaine période sans problème (laissez-vous le temps d'avoir des noyaux mis à jour par exemple), vous pourrez lancer la commande, si vous êtes téméraire:

# Sous root
apt purge grub-common grub2-common grub-efi-amd64-bin grub-efi-amd64-signed grub-efi-amd64