Journal Création d'un système live-CD basé sur Debian

Posté par  . Licence CC By‑SA.
Étiquettes :
20
14
nov.
2019

Salut.

En début de semaine, je me suis mis en tête de créer ma propre iso bootable, basée
sur Debian Buster tant qu'à faire (parce que c'est le système que je connais le
mieux, et de très loin).
Mon objectif ici est de m'amuser et d'apprendre, donc pas la peine de chercher
une raison pragmatique: si je voulais juste un live, j'irai en chercher un directement.

Au niveau du système, je vais me baser sur:

  • virtualbox pour les essais, config bios, parce que c'est plus facile;
  • [iso|sys]linux(-efi) pour gérer le boot: je n'ai jamais vraiment aimé grub (question de goût), lilo est manifestement obsolète, syslinux supporte pas mal de trucs, dont le démarrage EFI, semble être la référence pour les iso, et je l'utilise sur tous mes systèmes avec grand bonheur: que ce soit du pxe, du boot par BIOS, de l'UEFI, et maintenant de l'iso, j'aime vraiment ce logiciel;
  • runit-init, qui depuis Buster fait partie des alternatives officielles à systemd-sysv et sysvinit-core, bien qu'il ne dispose de quasi aucune intégration, et que franchement, quand il y a des scripts présents, j'ai tendance à les refaire (entre mon NIH et la simplicité de la tâche, dur de résister);
  • busybox, dans un 1er temps ce paquet apportera pas mal de doublons, mais par la suite je vais essayer de supprimer les paquets debian qui apportent des binaires déjà présents dans bb (awk, sed, grep, dash/bash, find, etc). Je sens que ça va pas être simple, mais ça sera fun;

J'ai utilisé ce lien comme base pour l'invocation de xorriso, il en résulte cette commande après quelques modifications (pour essayer de réduire un peu, même si c'est moyennement utile et que j'ai probablement cassé pleins de fonctionnalités de l'iso au passage):

xorriso -as mkisofs \
  -r -V 'CUSTOM_ISO_AMD64' \
  -o custom.iso \
  -J -joliet-long \
  -isohybrid-gpt-basdat \
  -isohybrid-mbr iso_dir/usr/lib/ISOLINUX/isohdpfx.bin \
  -boot-load-size 4 -boot-info-table -eltorito-alt-boot -b usr/lib/ISOLINUX/isolinux.bin \
  -no-emul-boot \
  iso_dir \
  2>&1 | grep -v 'WARNING.*Symlinks'

Contrairement à la méthode indiquée dans le lien, je n'ai utilisé aucune iso pour me fournir des données.

Pour isolinux, il semble qu'il suffise de créer un dossier syslinux a la racine de l'iso. Compte tenu du fait que ce dossier est relativement statique, j'ai préféré le créer à la racine du projet, mon script de build se contente de le copier dans l'iso (après suppression, histoire de pas garder de traces des essais précédents).
Ce dossier doit contenir (dans mon cas, j'utilise le menu vesa, selon la configuration souhaitée, les fichiers nécessaires ne sont pas les mêmes):

  • ldlinux.c32;
  • syslinux.cfg;
  • libcom32.c32;
  • libutil.c32;
  • vesamenu.c32;

Vu que je pars sur un boostrap classique, mon fichier syslinux.cfg ressemble à ça:

prompt 0
timeout 50
default live

ui vesamenu.c32
menu title custom live boot

label live
    linux ../boot/vmlinuz-4.19.0-6-amd64
    initrd ../boot/initrd.img-4.19.0-6-amd64
    append ro root=/dev/sr0

Le /dev/ro est hard-codé, c'est gênant (risque de ne pas retrouver le point de montage s'il y a d'autres CDs de montés, je pense), mais on verra pour améliorer ça plus tard.

Pour installer un système Debian strictement minimal, debootstrap intervient.
Compte tenu de mes choix et habitudes, la commande que j'ai utilisée est celle-ci:

PKG_LIST="${PKG_LIST}isolinux,syslinux-common,syslinux,syslinux-efi,"
PKG_LIST="${PKG_LIST}busybox,"
PKG_LIST="${PKG_LIST}linux-image-amd64,"
PKG_LIST="${PKG_LIST}runit-init,"
PKG_LIST="${PKG_LIST}udhcpc,"
PKG_LIST="${PKG_LIST}lynx,"
PKG_LIST="${PKG_LIST}dialog,"
PKG_LIST="${PKG_LIST}kbd,console-data,"
PKG_LIST="${PKG_LIST}ntpdate,"
PKG_LIST="${PKG_LIST}dropbear-bin"
PKG_LIST="${PKG_LIST}debootstrap"

debootstrap --no-merged-usr --variant=minbase "--include=$PKG_LIST" buster iso_dir

Pour découper:

  • --no-merged-usr: dans le doute, je préfère éviter les liens symboliques, mais je doute que ça change grand chose pour le cas présent;
  • --variant=minbase: en gros, juste le nécessaire pour avoir un apt fonctionnel, je sélectionne le reste moi-même de toute façon;
  • --include=
    • isolinux,syslinux-common,syslinux,syslinux-efi: histoire de pouvoir (re-)construire des systèmes viables depuis le live;
    • busybox: contiens pléthore d'utilitaires tous plus utiles les uns que les autres, même si le build Debian n'inclue pas tout;
    • linux-image-amd64: le live ne démarrera que sur des machines amd64, mais ça doit représenter la plupart des machines type intel de toute façon;
    • runit-init: parce qu'il faut bien un init, sinon on ne va pas aller bien loin;
    • udhcpc: contiens juste les scipts nécessaires afin d'utiliser le client dhcp de busybox sans se prendre la tête, c'est un candidat à la suppression;
    • lynx: un navigateur internet, ça peut toujours servir;
    • dialog: bien pratique pour faire des scripts interactifs, même si je trouve qu'il est franchement pénible à utiliser (impossible de capturer les valeurs saisies par l'utilisateur dans une variable, il faut passer par un temporaire)…
    • kbd,console-data: histoire de pouvoir sélectionner un clavier autre que qwerty;
    • ntpdate: mettre à l'heure le système, peut servir;
    • dropbear-bin: contiens un client et un serveur ssh, même s'il n'implémente pas sftp (pour scp… je ne suis jamais sûr du nom du protocole);
    • debootstrap: histoire de pouvoir bootstrapper une machine, tant qu'à faire;
  • buster: la version de Debian voulue;
  • iso_dir: le dossier qui va contenir l'install;
  • $MIRROR: un éventuel mirroir, peut servir si un apt-cacher traîne sur le lan;

Après un 1er essai, on a une iso, qui boot dans Virtualbox, même si le système est évidemment incomplet:

  • password de l'utilisateur root non défini et pas d'autres utilisateurs;
  • pas de réseau (genre, même pas de localhost): les paquets de gestion réseau traditionnels de Debian n'ont pas été installés;
  • pas de getty. Je m'attendais à des dysfonctionnements de ce côté vu que le dossier service se situe dans /etc et est en lecture seule, mais je ne pensais pas que ça gèlerai les gettys pour autant.
  • un hostname qui correspond à la machine qui a construit l'iso;
  • "quelques" warnings, causés par le fait que Debian n'est pas faite pour fonctionner sur un système en lecture seule (mais ça, ça peut s'arranger)…
  • probablement d'autres problèmes que l'on rencontrera plus tard;

Le plus facile, c'est la configuration de l'hostname: il suffit de créer un fichier iso_dir/etc/hostname, dans mon cas je vais mettre une valeur bidon: foobar.

Pour pouvoir utiliser le système cible, on va devoir monter un système de fichiers en RAM, histoire que le /var puisse être peuplé, /var qui contiendra notamment les dossiers dans lesquels runit supervisera les éléments du système.

Runit fonctionne avec un dossier /etc/runit qui contiens 3 fichiers exécutables, on va utiliser ceux de Debian que l'on modifiera juste assez pour avoir un truc simple qui marche:

  • 1: script qui initialise le système;
  • 2: script qui lance le superviseur runsvdir, principalement;
  • 3: script qui éteint le système proprement;

Debian a déjà implémenté le support du tradictionnel /etc/fstab dans 1, donc on va se contenter de créer ce fameux fichier (il manque plein de lignes, mais je veux juste un starter pour aujourd'hui):

tmpfs /var tmpfs defaults 0 0

Il faut ensuite modifier 2 afin de définir les répertoires contenant les services à superviser dans un endroit où runit pourra écrire, dans mon cas, j'ai utilisé /var/lib/runit/service.
Pour cela, il suffit de modifier la ligne ou SVDIR est définie (par défaut /etc/service), de créer le-dit dossier (puisque l'on vient tout juste de créer le point de montage /var, celui-ci est vide) et y copier les services dont on à besoin:

...
SVDIR=/var/lib/runit/service
mkdir -p /var/log $SVDIR
find /etc/service/ -type l -execdir cp -r -L -t $SVDIR {} \+
...

À partir de ce point, le système devrais démarrer les getty, mais il sera impossible de se connecter, faute de mot de passe défini.
On modifie donc le script de création d'iso en y ajoutant:

chpasswd -R $PWD/iso_dir <<EOF
root:toor
EOF

La commande chpasswd permets de définir les couples login/password d'un chroot, en texte. Pas sécurisé, certes, mais scriptable très facilement puisque récupère les infos sur stdin.

Juste avant de créer l'iso, on va faire un coup de ménage, quand même, parce que debootstrap a laissé toutes les archives dans le /var de l'iso, pas très utile.
Il y a aussi d'autres données un peu volumineuses liées à apt, et quelques trucs légers liés à dpkg et pam.
Vu que l'idée est d'avoir un truc qui marche dans un premier temps, je fais le bourrin: rm -r iso_dir/var/*.

Une fois l'iso générée, on dispose d'un liveCD de 442Mio (chez moi, mais en vrai j'ai rajouté l'install de debootstrap lors du copiage de mes notes ici) qui démarre, en tout cas sur une VM virtualbox.

Il reste pas mal de boulot pour faire un vrai live CD qui marche et qui s'éteint proprement, peut-être que j'écrirai a ce sujet un autre jour (quand j'aurai assez joué de mon côté).

À titre d'info, voici à quoi ressemble mon script mkiso.sh:

#!/bin/sh

PKG_LIST="${PKG_LIST}isolinux,syslinux-common,syslinux,syslinux-efi,"
PKG_LIST="${PKG_LIST}busybox,"
PKG_LIST="${PKG_LIST}linux-image-amd64,"
PKG_LIST="${PKG_LIST}runit-init,"
PKG_LIST="${PKG_LIST}udhcpc,"
PKG_LIST="${PKG_LIST}lynx,"
PKG_LIST="${PKG_LIST}dialog,"
PKG_LIST="${PKG_LIST}kbd,console-data,"
PKG_LIST="${PKG_LIST}ntpdate,"
PKG_LIST="${PKG_LIST}dropbear-bin"
PKG_LIST="${PKG_LIST}debootstrap"

rm -r iso_dir/*
debootstrap --no-merged-usr --variant=minbase "--include=$PKG_LIST" buster iso_dir

cp -ar syslinux iso_dir
cp -ar etc/* iso_dir/etc

chpasswd -R $(pwd)/iso_dir <<EOF
root:toor
EOF

rm -r iso_dir/var/*

xorriso -as mkisofs \
    -r -V 'CUSTOM_ISO_AMD64' \
    -o custom.iso \
    -J -joliet-long \
    -isohybrid-gpt-basdat \
    -isohybrid-mbr iso_dir/usr/lib/ISOLINUX/isohdpfx.bin \
    -boot-load-size 4 -boot-info-table -eltorito-alt-boot -b usr/lib/ISOLINUX/isolinux.bin \
    -no-emul-boot \
    iso_dir \
    2>&1 | grep -vi 'WARNING.*Symlinks'
  • # Autre piste

    Posté par  (site web personnel) . Évalué à 8.

    La solution que tu proposes est très bas niveau, et tu as du apprendre plein de choses…

    L'autre solution, est de suivre la documentation de debian live qui utilise les même outils que ceux de debian pour faire ses images lives. Des configurations toutes prêtes sont versionnées. Si le but est simplement de proposer le clavier français par défaut lors du démarrage il vaut mieux passer par là !

    • [^] # Re: Autre piste

      Posté par  . Évalué à 4.

      La solution que tu proposes est très bas niveau, et tu as du apprendre plein de choses…

      Ce qui était le but, je l'ai même précisé:

      pas la peine de chercher une raison pragmatique: si je voulais juste un live, j'irai en chercher un directement

      Il y a une tonne de live cd qui traînent, je ne vois pas vraiment de bonne raison de faire ce que j'ai fait si le seul objectif est d'avoir un système live qui juste marche.

      L'autre solution […]

      J'aurai peut-être en effet indiquer ces pointeurs, même si je t'avoue que je n'ai même pas pris la peine de chercher: perso, si je veux un système transportable, je prend un disque externe et j'y installe ma distro. Simple, efficace, souple.

    • [^] # Re: Autre piste

      Posté par  . Évalué à 2.

      Intéressant. Je cherchais exactement ça pour me faire des isos live de debian avec quasiment juste docker dessus. Merci !

  • # rootfs

    Posté par  (site web personnel) . Évalué à 4.

    Qu'est ce qui est inclus dans le initrd avec cette méthode ?
    Il ne serait pas plutôt conseillé de monter le rootfs en RAM pour un live-CD ?

    Le /dev/ro est hard-codé, c'est gênant (risque de ne pas retrouver le point de montage s'il y a d'autres CDs de montés, je pense), mais on verra pour améliorer ça plus tard.

    Avec une étiquette (label ou volume name), /dev/disk/by-label/ ?

    #fstab
    tmpfs /var tmpfs defaults 0 0
    

    Je ne sais ce que Debian a besoin, mais si il suit le FHS, il ne manquerait pas non plus /run et /tmp ?

    • [^] # Re: rootfs

      Posté par  . Évalué à 3.

      Qu'est ce qui est inclus dans le initrd avec cette méthode ?

      Je ne l'ai pas customisé, c'est vraiment comme si j'avais installé Debian sur un CD. Tu as raison, cela fait partie des choses qu'il faudrait faire ensuite, pour avoir vraiment un truc propre, à l'issue de ce journal, l'iso est franchement bancale, elle ne peux même pas s'éteindre proprement :)

      Avec une étiquette (label ou volume name), /dev/disk/by-label/ ?

      Ça réduirait le problème, encore que le risque de collision reste important. L'idéal serait d'utiliser un UUID, mais je n'ai pas regardé comment ça fonctionne avec une iso. Probablement de la même manière qu'une partition normale, pour le coup.

      Je ne sais ce que Debian a besoin, mais si il suit le FHS, il ne manquerait pas non plus /run et /tmp ?

      Il y a aussi probablement le bazar de PAM qu'il faudrait copier avant de monter /var, et au fur et a mesure que j'ajouterais des composants, il y aura de plus en plus de choses à copier. Probablement.

      C'est juste le strict minimum pour que ça marche. Ce que j'ai fait la, c'est un "hello world".

  • # génération de VM

    Posté par  . Évalué à 2.

    Cela me fait penser à ce script qui utilise aussi debootstrap mais pour générer des VM plutot que des isos bootable, peut etre une feature à lui ajouter.
    Sur le gitlab de Debian et Son paquet Debian

    • [^] # Re: génération de VM

      Posté par  . Évalué à 2.

      Je proteste, mon script (et d'autres que j'ai fait, c'est pas la 1ère fois que je joue avec debootstrap) n'a rien à voir, en terme de qualité et finitions, je suis à la ramasse!

      Par contre merci du partage, une fois décortiqué (parce que bon, il est aussi 1000 fois plus verbeux que ce que je fais) y'a moyen d'en tirer pas mal de connaissances!

      Par exemple:

      • au niveau des conventions de codage, j'ai encore tant à apprendre sur le shell (faudrait que je trouve un outil d'analyse statique en vrai);
      • je vois une p'tite for-loop sur une variable STATIC_ETH qui m'intéresse pas mal, sans la copier, je pourrais p'tet y trouver des choses intéressantes;

      peut etre une feature à lui ajouter.

      Avant d'ajouter des features à un truc qui marche, je pense que je ferais mieux de travailler mon truc bancal pour le rendre plus convainquant que ça, j'espère que la communauté de linuxfr m'en voudra pas trop si je me sers encore des journaux pour me servir de notes :)

      • [^] # Re: génération de VM

        Posté par  (site web personnel) . Évalué à 5.

        au niveau des conventions de codage, j'ai encore tant à apprendre sur le shell (faudrait que je trouve un outil d'analyse statique en vrai);

        https://www.shellcheck.net/ ?

        • [^] # Re: génération de VM

          Posté par  . Évalué à 2. Dernière modification le 21 novembre 2019 à 13:22.

          Il faudrait que je revérifie dans les logs de mes repo, me semble que j'avais suivi certains de ses conseils, qui ont cassé certains scripts, tandis que d'autres trucs auraient pu être signalés.
          Peut-être que je me repose sur certains comportements bordeline, aussi, faudrait que je le repasse sur mes scripts les plus "poussés".

    • [^] # Re: génération de VM

      Posté par  . Évalué à 2.

      Je proteste, mon script (et d'autres que j'ai fait, c'est pas la 1ère fois que je joue avec debootstrap) n'a rien à voir, en terme de qualité et finitions, je suis à la ramasse!

      Par contre merci du partage, une fois décortiqué (parce que bon, il est aussi 1000 fois plus verbeux que ce que je fais) y'a moyen d'en tirer pas mal de connaissances!

      Par exemple:

      • au niveau des conventions de codage, j'ai encore tant à apprendre sur le shell (faudrait que je trouve un outil d'analyse statique en vrai);
      • je vois une p'tite for-loop sur une variable STATIC_ETH qui m'intéresse pas mal, sans la copier, je pourrais p'tet y trouver des choses intéressantes;

      peut etre une feature à lui ajouter.

      Avant d'ajouter des features à un truc qui marche, je pense que je ferais mieux de travailler mon truc bancal pour le rendre plus convainquant que ça, j'espère que la communauté de linuxfr m'en voudra pas trop si je me sers encore des journaux pour me servir de notes :)

      • [^] # Re: génération de VM

        Posté par  (site web personnel, Mastodon) . Évalué à 3.

        Avant d'ajouter des features à un truc qui marche, je pense que je ferais mieux de travailler mon truc…

        Ah si, quand même, un truc bien à mettre sur un livecd, c'est memtest86+ dans le Grub. Et dans la même lignée (est-ce dans buzybox ?) on a badblocks. Avec ces deux trucs, on peut plus facilement juger de l'état de santé d'un pécé trouvé dans une poubelle…

        • [^] # Re: génération de VM

          Posté par  . Évalué à 2.

          memtest86+ dans le Grub.

          Marrant, je pensais que c'était un module de syslinux, mais manifestement c'est un binaire à part, qui s'utilise donc peu importe le bootloader.

          (est-ce dans buzybox ?) on a badblocks

          Nope, pas busybox. Celui-la ne sert qu'à remplacer les outils de base du shell. apt-file search badblock | grep -v man semble suggérer e2fsprogs pour le binaire, mtools en aurait une version aussi, et smartmontools en cause. Le dernier me semblerait le plus adapté pour le coup, moins limité à des systèmes de fichier spécifiques.

          • [^] # Re: génération de VM

            Posté par  (site web personnel, Mastodon) . Évalué à 2.

            le plus adapté pour le coup, moins limité à des systèmes de fichier spécifiques.

            Oui mais non. badblocks n'a aucune notion de système de fichier, il est au niveau du raw device ou d'une partie de celui-ci. Il se contente de vérifier en lecture/écriture chaque bloc/secteur du volume.

            • [^] # Re: génération de VM

              Posté par  . Évalué à 2.

              Ah oui, en effet, j'aurai du aller lire la description d'e2fsprogs:

              Ce paquet fournit des programmes […] de systèmes de fichiers basés sur ext2/3/4. Il comprend aussi le programme « badblocks », qui peut être utilisé pour rechercher les mauvais blocs sur un disque ou tout autre périphérique de stockage.

              Merci pour ces précisions.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.