La meilleure façon de comprendre un système d'exploitation reste d'en fabriquer un. Pas une distribution : un Linux minimal, compilé à la main, qui démarre dans une machine virtuelle et sert une page web. Trois articles, et à la fin une image disque de quelques dizaines de mégaoctets dont on connaît chaque fichier.
Ce que l'on construit
Un système composé de trois éléments seulement : un noyau Linux compilé pour l'occasion, un binaire BusyBox statique qui fournit toutes les commandes, et un script /init qui joue le rôle de PID 1. Le tout démarre sous QEMU via GRUB, obtient une adresse en DHCP et répond en HTTP.
C'est l'exercice qui rend concrets tous les concepts du démarrage : ce qui doit être compilé en dur, à quoi sert vraiment l'initramfs, ce que fait le premier processus.
Une arborescence, cinq répertoires
~/rocket-lnx-demo/ ├── src/ sources uniquement (noyau, BusyBox) — aucun binaire ├── build/ artefacts intermédiaires de compilation ├── out/ résultats finaux : vmlinuz, initramfs.img, disk.qcow2 ├── initramfs/ racine de l'initramfs en construction └── mnt/ points de montage temporaires
Cette séparation n'est pas cosmétique : elle garantit qu'on peut tout effacer et recommencer sans se demander ce qui était source et ce qui était produit. Sur un exercice qu'on refait plusieurs fois — et on le refait — c'est ce qui évite les résultats « qui marchent » sans qu'on sache pourquoi.
Compiler le noyau : ce qui n'est pas compilé n'existe pas

Cinq familles d'options suffisent — mais elles doivent être compilées en dur, pas en modules : sans initramfs, personne ne chargerait ces modules.
make defconfig # base saine pour x86_64 make menuconfig # puis on active précisément ce qu'il faut
La règle qui gouverne cette étape : tout ce qui n'est pas compilé n'existe pas. Et comme le premier système n'aura pas d'initramfs pour charger des modules, tout doit être en dur (=y).
- Console série —
CONFIG_SERIAL_8250etCONFIG_SERIAL_8250_CONSOLE. Sans elle, QEMU lancé en-nographicn'affiche rien : la machine démarre peut-être très bien, on ne le saura jamais. C'est l'option qu'on oublie et qui coûte une heure. - Disque VirtIO —
CONFIG_VIRTIO,CONFIG_VIRTIO_PCI,CONFIG_VIRTIO_BLK: c'est ce qui fait apparaître/dev/vda. Sans elles, le noyau démarre et ne voit aucun disque. - Réseau —
CONFIG_VIRTIO_NETetCONFIG_E1000: deux modèles de cartes, pour pouvoir basculer sur une carte émulée classique en cas de doute lors du débogage. - Système de fichiers —
CONFIG_EXT4_FS, faute de quoi la racine ne se monte pas. - devtmpfs et initramfs — pour que
/devse peuple automatiquement et que le noyau accepte une archive initrd.
make -j"$(nproc)" cp arch/x86/boot/bzImage ~/rocket-lnx-demo/out/vmlinuz
Le noyau produit s'appelle bzImage — « big zImage », rien à voir avec bzip2 : c'est simplement le format d'image compressée capable de dépasser les limites de taille du format historique. Renommé vmlinuz, il sera chargé par GRUB.
BusyBox : toutes les commandes en un binaire
Un système a besoin de sh, mount, ls, ip, d'un client DHCP… Les compiler séparément représenterait des centaines de paquets. BusyBox réunit plus de trois cents commandes dans un exécutable unique : le programme regarde sous quel nom il a été appelé et se comporte en conséquence. Chaque commande n'est qu'un lien symbolique vers lui.
Settings ---> [*] Build static binary (no shared libs) Networking Utilities ---> [*] udhcpc [ ] tc
Deux choix méritent explication.
La compilation statique est obligatoire, pas préférable. Un binaire dynamique va chercher sa bibliothèque C au démarrage ; dans un initramfs qui ne contient pas de libc, il échoue immédiatement — et le message d'erreur, à ce stade, est particulièrement peu bavard. Statique, le binaire est autonome : il fonctionne partout.
udhcpc fournit un client DHCP minimal — indispensable pour que le système obtienne une adresse. Quant à tc, il est désactivé volontairement : inutile ici, et connu pour faire échouer les compilations statiques.
Où l'on en est
À l'issue de cette étape, deux fichiers seulement : un noyau et un BusyBox statique. Rien ne démarre encore — il manque un disque, un système de fichiers racine et un premier processus. C'est l'objet de l'article suivant.
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 — vous y êtes
- Fabriquer son Linux (2) : disque, rootfs et PID 1
- Fabriquer son Linux (3) : initramfs, GRUB et premier boot