Combien de fois vous êtes-vous retrouvé chez tonton Louis ou beau-père Michel, fiers de leur nouvelle bête de course équipée d'un accès DSL, tétanisé devant un écran bleu pastel arborant en guise de login un jeune en skateboard ou une pièce d'échiquier ? Ne vous êtes-vous pas maudit à ce moment, alors que vous alliez passer le week-end entier à cet endroit, de ne pas avoir pris dans vos bagages un live CD quelconque, un OS muni d'un shell digne de ce nom, ainsi que de tous les outils indispensables à un week-end de repos ? Et vous avez, dans votre poche, cette clé USB, pleine à craquer de mp3 – libres évidemment –, de photos de vacances et autres captures vidéo de la dernière Solutions Linux. Il restait pourtant dans cette clé 64 mégas octets inutilisés, 64 mégas dans lesquels vous auriez pu caser un UNIX minimal, un diamant qui serait muni d'un OpenSSH, d'un Irssi et d'un Links, que vous aurait présenté un Ion 3 à peine configuré.
Voici ce que cet article vous propose : disposer à tout instant du couteau suisse de l'administrateur système UNIX, un NetBSD minimal, mais fonctionnel, qui se logera dans un coin de votre clé USB, sans pour autant la rendre inexploitable par d'autres systèmes. Le but de l'opération sera d'obtenir une clé amorçable, qui n'utilisera pas le système de fichiers de la clé, mais une image brute, générée à l'aide de l'outil
dd(1), qu'un noyau affublé d'un RAMDISK ira mounter comme root filesystem.
Pour construire notre OS minimal, nous utiliserons, sur une machine NetBSD 3.1, des outils présents dans le basesystem, mais également Grub, disponible dans
pkgsrc (
pkgsrc/sysutils/grub). Enfin, Qemu, installable depuis
pkgsrc/emulators/qemu, nous servira à tester nos travaux. Cet article s'appuie sur un projet sur lequel j'ai travaillé en 2006 : the NetBSD LiveKey (http://imil.net/nlk/). J'utiliserai donc tout naturellement quelques scripts écrits pour l'occasion qui nous simplifieront grandement la tâche.
NOTE
Quelques notions des systèmes BSD, et particulièrement NetBSD, sont nécessaires pour la bonne compréhension de cet article. Si toutefois ces notions vous faisaient défaut, vous trouverez probablement de l'aide dans le fabuleux NetBSD Guide à cette adresse http:www.netbsd.org/guide/en/ ou en version française (mais un peu dépassée) à cette adresse : http:www.mclink.it/personal/MG2508/nbsdfra/netbsd.html.
1. Création du noyau
La première étape de notre périple va consister à créer un noyau muni d'un RAMDISK. Pour cela, nous allons compiler un noyau NetBSD de manière habituelle (voir
http://netbsd.org/Documentation/kernel/#how_to_build_a_kernel), en nous assurant que les options suivantes sont bien activées/renseignées :
# Nous allons utiliser UNION filesystem pour mounter
# les partitions "réelles" sur le ramdisk
file-system UNION
# vnd est le device permettant de mounter des images,
# notre root filesystem sera une image
pseudo-device vnd 4
# et pour stocker encore un peu plus de données,
# nous utiliserons une image compressée
options VND_COMPRESSION
# Les directives de création et d'espace nécessaire
# au RAMDISK
options MEMORY_DISK_HOOKS
options MEMORY_DISK_IS_ROOT
options MEMORY_DISK_SERVER=0
options MEMORY_DISK_ROOT_SIZE=32768
options MEMORY_RBFLAGS=0
Procédons donc à la compilation de ce noyau custom (on considère que le fichier de configuration utilisé est
NBUSB) :
# pwd
/usr/src/sys/arch/i386/conf
# config NBUSB
# cd ../compile/NBUSB
# make depend && make
Si tout s'est bien déroulé, vous devriez maintenant disposer d'un noyau nommé
netbsd à cet endroit de l'arborescence.
Il nous faut maintenant affubler ce noyau anormalement gros d'un root filesystem minimal, qui constituera le pivot de notre mini-OS. Afin de simplifier l'opération, nous allons peupler ce RAMDISK de quelques outils compilés statiquement, que nous piocherons dans le répertoire
/rescue de notre NetBSD souche. Pour peupler ce disque d'amorçage du système, nous devons réfléchir aux différentes étapes : 1. obligatoires dans une séquence de boot, 2. dont nous allons avoir besoin dans le cas spécifique qui nous occupe, à savoir, utiliser autre chose que le système de fichiers initial.
Nous savons que le premier processus qui sera appelé est
init(8), classiquement situé dans
/sbin. Créons donc une fausse arborescence munie de cette ébauche d'OS :
# mkdir -p /home/pinpin/nbusb/fakeroot/sbin
# cp /rescue/init /home/pinpin/nbusb/fakeroot/sbin
init(8), sur un système héritier de 4.0BSD, exécute le script
/etc/rc, qui habituellement s'occupe de démarrer différents services à l'aide des divers
/etc/rc.*. Nous allons utiliser
rc(8) de manière beaucoup plus basique. En effet, cet
/etc/rc sera exécuté dans le contexte d'un boot singulier, et c'est à lui que reviendra la charge d'effectuer le pivot entre le RAMDISK et l'image root contenant les moult outils qui motivent cette tâche. Voici un exemple de fichier
fakeroot/etc/rc minimal et commenté :
# debut de /etc/rc
echo "Initialisation du système..."
export PATH=/sbin:/bin:/usr/sbin:/usr/bin
# on exporte la variable qui contient le point
# de montage de la clé
KEYMOUNTPOINT=/mnt
# puis une variable contenant les données utiles
KEYFILESPATH=${KEYMOUNTPOINT}/nbusb
# enfin, le nom de l'image que nous créerons plus tard
IMGNAME=nbusb.zimg
sleep 2 # on attend la fin de l'affichage
echo
echo "--------------------------------------------"
echo " . Stage 2: montage de l'image disque"
echo "--------------------------------------------"
echo
echo "Nous allons monter le système de fichier VFAT."
echo -n "Entrez le device sur lequel se trouve " \
"l'image root (wd0a, wd0e, sd0e...): "
read dev
# 1ere passe, on monte la clé avec le système
# de fichiers VFAT
echo "Montage de /dev/${dev}"
mount_msdos /dev/${dev} ${KEYMOUNTPOINT}
# Nous avons maintenant la main sur le filesystem de la clé,
# nous allons pouvoir créer le device virtuel vnd qui sera
# associé au fichier image
vnconfig -z vnd0 ${KEYFILESPATH}/${IMGNAME}
# /!\ issu de man vnconfig :
#
# -z Assume that regular file is compressed
# disk image in cloop2 format, and
# configures it read-only.
# ^^^^^^^^^
# 2eme passe, nous pouvons maintenant monter / issu
# du device vnd
mount_ffs -o ro,union /dev/vnd0a / >/dev/null 2>&1
# puis on monte le reste du filesystem en Memory
# FileSystem (vnd compressé et en lecture seule)
echo "montages mfs"
mount_mfs -s 262144 swap /tmp
mount_mfs -s 12000 swap /dev
mount_mfs -s 262144 swap /var
mount_mfs -s 131072 swap /etc
mount_mfs -s 262144 swap /home
mount_mfs -s 262144 swap /usr/pkg
sleep 1
echo "Création des devices..."
cd /dev && sh MAKEDEV all
echo
echo "--------------------------------------------"
echo " . Stage 3: multiutilisateur"
echo "--------------------------------------------"
echo
# on appelle maintenant le "vrai" rc
sh /etc/rc
# fin de /etc/rc
Ce
rc fait appel à différents exécutables que nous devons donc copier sur notre clé :
sh (sans lui, point de
rc !) et
sleep dans
fakeroot/bin, puis
mount_msdos,
mount_ffs,
mount_mfs et
vnconfig dans
fakeroot/sbin. Copiez également les bibliothèques desquelles dépendent ces outils, typiquement tout
/lib,
/usr/lib/libc.so* ainsi que
/usr/lib/libutil.so.* et évidemment
/libexec/ld.elf_so.
Maintenant que nous disposons de la structure de fichiers initiale, il nous faut la greffer à notre noyau. Nous allons pour cela utiliser les outils
makefs(8) et
mdsetimage(8). Ces outils servent respectivement à générer une image à partir d'une structure de fichiers et à copier cette image dans le RAMDISK du noyau.
Créons une image de 16 mégaoctets du filesystem basique créé plus haut. Nous choisissons évidemment FFS comme type de système de fichiers :
# makefs -s 16m -t ffs md.img fakeroot
Copions maintenant cette image dans notre RAMDISK :
# mdsetimage netbsd md.img
Afin de ne gaspiller aucun octet, compressons ce noyau :
# gzip -9 netbsd && mv netbsd.gz netbsd
Votre noyau est fin prêt.
2. Création du root filesystem
Muni de son système initial, notre noyau va dérouler,
init(8) va invoquer
rc qui va tenter de monter l'image
nbusb.zimg. Ce fichier image n'est rien de plus qu'un disque virtuel créé à l'aide de
dd(1), que nous allons peupler comme une simple partition.
Créons donc un disque vide de 128 mégaoctets :
# dd if=/dev/zero of=nbusb.img count=262144 bs=512
Associons-le à un device virtuel de type
vnd :
# vnconfig -c -v /dev/vnd0 nbusb.img
On génère, comme pour un véritable disque, un label :
# cat > nbusb.disktab << EOF
miniroot:\
:ty=floppy:se#512:nt#1:rm#3600:ns#262144:nc#1:\
:pa#262144:oa#0:ba#4096:fa#512:ta=4.2BSD:\
:pb#262144:ob#0:\
:pc#262144:oc#0:
EOF
On inscrit ce label :
# disklabel -w -f nbusb.disktab /dev/vnd0 nbusb
Puis, on construit le système de fichiers :
# newfs -m 0 /dev/vnd0a
Il est désormais possible de monter ce disque :
# mount /dev/vnd0a /mnt
Reste à peupler ce disque avec les packages de base de votre choix. Pour cette petite démonstration, nous nous contenterons des sets
base et
etc, que vous pourrez télécharger ici :
ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-3.1/i386/binary/sets/. Remplissons notre faux disque des packages fraîchement récupérés :
# cd /mnt
# tar zxvfp /home/pinpin/tmp/base.tgz
# tar zxvfp /home/pinpin/tmp/etc.tgz
Notre image dispose maintenant d'un système minimal, mais parfaitement fonctionnel. Reste à lui apporter quelques petites modifications afin de le rendre exploitable ; comme placer la variable
rc_configured Ã
YES dans
etc/rc.conf, éventuellement ajouter un utilisateur ou en tout cas s'assurer qu'on pourra passer root. Pourquoi pas spécifier un nom d'hôte dans
/etc/myname ou configurer quelques variables d'environnement dans l’
/etc/profile.
Notre disque créé et peuplé, il nous reste à le compresser afin qu'il occupe le moins de place possible sur notre clé. Ceci est réalisé à l'aide de la commande
vndcompress(1) :
On démonte notre disque virtuel :
# umount /mnt
On le désassocie du device
vnd0 :
# vnconfig -u vnd0
Et on compresse l'image :
# vndcompress nbusb.img nbimg.zimg
Nous avons spécifié dans le fichier
rc du RAMDISK que l'image se situera dans le répertoire
nbusb/ sur la clé au format VFAT. C’est donc dans ce répertoire que nous allons copier notre image :
# mount_msdos /dev/sd0e /mnt
sd0e représente le device associé à la partition VFAT de notre clé :
# mkdir /mnt/nbusb
# cp netbsd /mnt/nbusb
# cp nbusb.zimg /mnt/nbusb
Reste à rendre notre clé amorçable grâce à Grub :
# grub-install --root-directory=/mnt /dev/sd0
Et créer un
menu.lst idoine :
# cat > /mnt/boot/grub/menu.lst << EOF
title NetBSD LiveKey
root (hd0,0)
kernel --type=netbsd /nbusb/netbsd
boot
EOF
C'est terminé !
Vous pouvez maintenant tester votre NetBSD-light grâce, par exemple, à l'excellent Qemu en utilisant la syntaxe suivante :
# qemu /dev/sda
Si tout se passe bien, vous devriez admirer un magnifique menu Grub.

ATTENTION
Pour Qemu, le disque source sera exploité comme un disque IDE. Aussi, lorsque rc demandera quel device utiliser comme root filesystem, c'est bien wd0X (ou X=a, e...) qu'il faudra entrer, a contrario d'une vraie utilisation lors de laquelle le noyau NetBSD associera votre clé à un device de type sdXY.

À la fin de la séquence de boot, vous devriez normalement vous trouver devant un TTY qui vous présente fièrement sa demande de login. Y'a plus qu'à .

3. Au revoir président
L'article se finit ici, mais vous avez certainement compris que c'est également ici que démarrent les insomnies, car il ne tient qu'à vous de créer autant de configurations de NetBSD " embarquées " que vous le souhaitez, de faire le ménage dans le basesystem, de retoucher, réécrire, repenser le
rc basique !
De plus, il reste dans notre image basique plusieurs dizaines de mégas inutilisés. Faites donc une petite sélection de packages (FTP : ftp.netbsd.org/pub/NetBSD/packages/3.0/i386/), puis à l'aide de
pkg_add -p, installez-les dans votre environnement minimal. Attention, l'image compressée est en lecture seule. Il faudra travailler sur l'image décompressée puis regénérer le
.zimg à l'aide de VNDcompress.
Vous trouverez quelques ajouts, ainsi que des scripts automatisant les étapes que nous avons vues à l'adresse suivante :
http://imil.net/nlk/ L’
/etc/rc de ce projet utilise par exemple un autre répertoire sur la clé afin de pouvoir modifier des fichiers de configuration classiques sans devoir reconstruire la clé. Il est également capable d'installer au boot des packages qui se trouvent dans le répertoire
livekey/ et il mounte
/root en lecture écriture sur un répertoire situé sur la clé. Bien des améliorations sont imaginables, et il est sans aucun doute possible d'accélérer entre autres le processus de boot. Et comme d'habitude, commentaires et contributions sont les bienvenus :)
Références
Quelques liens connexes :
Donnez votre avis
Vous devez avoir ouvert une session pour écrire un commentaire.