Le disque contient un noyau, un rootfs et un PID 1. Reste à fabriquer l'initramfs, à installer un chargeur de démarrage — puis à appuyer sur le bouton et regarder la chaîne complète se dérouler sous les yeux.
Un initramfs écrit à la main
Les distributions génèrent le leur avec des outils qui embarquent des centaines de modules « au cas où ». Ici, on l'écrit : une arborescence minimale, le BusyBox statique, et un script /init d'une trentaine de lignes qui fait exactement quatre choses :
- monter
/proc,/syset/dev; - attendre l'apparition du disque — quelques secondes au plus, car le périphérique VirtIO n'est pas toujours prêt à la milliseconde où le script démarre. Cette attente est le genre de détail qui distingue un initramfs qui fonctionne d'un initramfs qui fonctionne une fois sur deux ;
- monter le vrai système de fichiers racine sur
/new_root, avec une vérification de cohérence — le fichier/initattendu est-il bien là ? — avant d'aller plus loin ; - appeler
switch_root.
L'archive est ensuite produite au format cpio compressé, le seul que le noyau sache lire nativement :
find . | cpio -H newc -o | gzip -9 > ../out/initramfs.img
Le format newc n'est pas facultatif : c'est celui que le noyau attend. Quelques centaines de kilo-octets suffisent — à comparer aux dizaines de mégaoctets d'un initramfs de distribution.
GRUB : une configuration entièrement explicite

Un menu sans détection automatique, un GRUB installé sur le secteur 0 de l'image, et une VM qui démarre en console série.
set timeout=0
set default=0
menuentry "Rocket Linux Demo (final)" {
set root=(hd0,msdos1)
linux /boot/vmlinuz console=ttyS0 root=/dev/vda1 ro loglevel=7
initrd /boot/initramfs.img
}
Chaque ligne est volontairement explicite — aucune détection automatique, ce qui est exactement ce qu'on veut pour comprendre :
set root=(hd0,msdos1)— premier disque BIOS, première partition MBR. On désigne, on ne devine pas ;console=ttyS0— la sortie va sur la console série, donc dans le terminal qui a lancé QEMU. Cela n'a de sens que parce que le support série a été compilé en dur dans le noyau ;root=/dev/vda1— le paramètre que lira l'initramfs pour savoir quoi monter ;ropuisloglevel=7— racine montée en lecture seule au départ, et journalisation maximale : en phase de mise au point, on veut tout voir.
sudo grub-install --target=i386-pc --boot-directory=mnt/boot /dev/nbd0
La cible i386-pc désigne le GRUB pour BIOS — pas l'UEFI. C'est cette commande qui écrit l'étage 1 dans les 446 octets du MBR et installe les étages suivants. La boucle est bouclée avec l'article sur la chaîne de démarrage.
Fermer proprement
sync sudo umount mnt sudo qemu-nbd --disconnect /dev/nbd0
Trois commandes, dans cet ordre, et aucune n'est facultative. Le sync force l'écriture effective des données encore en cache ; le démontage libère le système de fichiers ; la déconnexion NBD rend l'image cohérente. Démarrer une image encore attachée en NBD, c'est la corrompre.
Le premier démarrage
qemu-system-x86_64 -enable-kvm -m 256M -nographic \ -drive file=out/disk.qcow2,format=qcow2,if=virtio \ -netdev user,id=n1,hostfwd=tcp::8080-:80 \ -device virtio-net-pci,netdev=n1
Les options qui comptent : -nographic renvoie la console série dans le terminal — cohérent avec le console=ttyS0 passé au noyau ; if=virtio donne le /dev/vda attendu ; et hostfwd=tcp::8080-:80 redirige le port 8080 de l'hôte vers le port 80 de la machine.
Le déroulé s'affiche alors intégralement : GRUB, la décompression du noyau, l'initramfs, le switch_root, puis le script /init qui obtient une adresse en DHCP et démarre le serveur. 256 Mo de mémoire suffisent largement, et le démarrage se compte en secondes.
La preuve, depuis l'hôte
curl --max-time 3 http://127.0.0.1:8080/ Hello World - Rocket Linux Demo
Cette ligne valide toute la chaîne d'un coup : le MBR, GRUB, un noyau compilé à la main, un initramfs écrit à la main, un switch_root, un PID 1 maison, un client DHCP et un serveur HTTP — le tout dans une image de quelques dizaines de mégaoctets.
Ce que l'exercice apprend
Il ne s'agit pas de remplacer une distribution : personne ne maintiendra un système pareil en production. L'intérêt est ailleurs.
- On comprend enfin pourquoi l'initramfs existe — en s'en passant, puis en en écrivant un.
- On sait ce que fait réellement PID 1, et pourquoi il n'a pas le droit de se terminer.
- On mesure ce qu'apporte une distribution : gestion de paquets, mises à jour de sécurité, pilotes universels, init robuste — tout ce qu'on n'a pas ici.
- Et devant un serveur qui ne démarre plus, on sait à quel étage regarder : la question « GRUB s'affiche-t-il ? » ou « voit-on l'invite initramfs ? » divise immédiatement le problème en deux.
C'est là tout l'intérêt d'un lab : passer une soirée sur un système qui ne sert à rien, pour ne plus jamais être perdu devant un système qui sert à quelque chose.
La page de référence est sur le wiki
Cet article ne remplace pas la documentation : il en reprend le fil et en explique les raisons. Le détail complet — toutes les commandes, tous les scripts, les options de configuration une par une — est publié sur mon wiki :
La série
Deux articles pour comprendre ce qui se passe au démarrage, trois pour fabriquer un système Linux complet à la main :
- Du bouton Power au noyau : la chaîne de démarrage x86
- initramfs et switch_root : le sas de démarrage
- Fabriquer son Linux (1) : noyau et BusyBox
- Fabriquer son Linux (2) : disque, rootfs et PID 1
- Fabriquer son Linux (3) : initramfs, GRUB et premier boot — vous y êtes