IN PROGRESS
La distribution GNU/Linux Debian permet une installation automatique
non assistée en utilisant un fichier de préconfiguration
preseed.cfg
.
preseed.cfg
contient les réponses pré-remplies aux questions posées
lors d'une installation interactive classique.
La méthode décrite ci-dessous crée un CD d'installation automatisée.
Une procédure similaire d'installation par le réseau fera l'objet d'un document dédié.
Lors de l'installation un système d'exploitation minimal est chargé en mémoire.
Ce système d'exploitation minimal a pour seule fonction d'installer sur le disque dur de l'ordinateur le système d'exploitation final.
La procédure d'installation interactive requiert la présence d'un administrateur du début à la fin et l'absence d'une réponse à une question suspend l'installation.
La présence physique d'un administrateur pour superviser cette opération n'est pas toujours possible et la fréquence à laquelle cette procédure doit être réalisée peut contrarier la faisabilité d'un projet.
Le fichier preseed.cfg
contient un ensemble d'instructions pour les
différents composants de l'installateur.
Un exemple de fichier preseed.cfg
est fourni par Debian à
cette
adresse et mérite d'être examiné.
Quand le programme installateur debian rencontre un fichier
preseed.cfg
à la racine du système d'exploitation minimal, il
l'utilisera pour renseigner les composantes d'installation au lieu de
solliciter une interaction.
Le système d'exploitation minimal est modifié pour inclure le
fichier preseed.cfg
à sa racine.
Pour créer cette version automatisée de CD d'installation, il faut se munir des paquets suivants :
# apt-get install bsdtar genisoimage
Un CD d'installation classique est nécessaire. Le netinst de debian peut faire l'affaire pour le test mais cela fonctionne de la même manière pour les autres formats.
# wget debian-9.6.0-amd64-netinst.iso
Extraire le contenu de l'image nous permet d'avoir une copie
modifiable. Le paquet bsdtar
simplifie l'opération.
# mkdir isofiles # bsdtar -C isofiles -xf debian-9.6.0-amd64-netinst.iso
Le contenu du CD d'installation est maintenant disponible à la
modification dans le dossier isofiles
.
initrd.gz
contient le système d'exploitation minimal.
Pour modifier cette archive, il faut la décompresser. Mais d'abord il
faut veiller à autoriser l'écriture dans le dossier contenant
initrd.gz
.
# ls -l isofiles/install.amd/ total 20M dr-xr-xr-x 2 sysadm sysadm 4,0K nov. 10 12:34 gtk dr-xr-xr-x 2 sysadm sysadm 4,0K nov. 10 12:34 xen \o/ -r--r--r-- 1 sysadm sysadm 16M janv. 11 12:34 initrd.gz <------------------- | -r--r--r-- 1 sysadm sysadm 45 nov. 10 12:34 install.bat / \ -r--r--r-- 3 sysadm sysadm 4,1M nov. 10 12:34 vmlinuz # chmod +w -R isofiles/install.amd/ # gunzip isofiles/install.amd/initrd.gz # ls -l isofiles/install.amd/ total 52M drwxr-xr-x 2 sysadm sysadm 4,0K nov. 10 12:34 gtk drwxr-xr-x 2 sysadm sysadm 4,0K nov. 10 12:34 xen -rw-r--r-- 1 sysadm sysadm 48M janv. 11 12:36 initrd -rw-r--r-- 1 sysadm sysadm 45 nov. 10 12:34 install.bat -rw-r--r-- 3 sysadm sysadm 4,1M nov. 10 12:34 vmlinuz
Une fois le fichier preseed.cfg
préparé, il s'agit de l'incorporer
dans l'initrd
. initrd
est une archive qui peut être manipulée avec
la commande cpio
installée par défaut.
<a id=“org8ba0f68”></a>
# ls -F isofiles/ preseed.cfg # echo preseed.cfg | cpio -H newc -o -A -F isofiles/install.amd/initrd [...] # gzip isofiles/install.amd/initrd # chmod -R -w isofiles/install.amd/
Une dernière étape est nécessaire avant la création de l'iso.
L'installateur Debian s'appuie sur un fichier contenant la somme de
contrôle de tous les fichiers contenus dans le CD pour les valider. Ce
fichier est contenu à la racine du cd et est nommé md5sum.txt
Puisque nous avons modifié le fichier initrd.gz
nous devons
recalculer sa somme de contrôle pour la rapporter dans le fichier
md5sum.txt
La commande suivante nous permet reconstruire md5sum.txt
pour tous
les fichiers contenus dans le projet d'iso.
# cd isofiles # md5sum `find -follow -type f` | sudo tee md5sum.txt # cd ..
Ça y est, le dossier isofiles
est fin prêt à être converti en
fichier iso.
Nous utilisons la commande genisoimage pour ce faire avec la syntaxe suivante :
# genisoimage -quiet -r -J -b isolinux/isolinux.bin \ -c isolinux/boot.cat \ -no-emul-boot \ -boot-load-size 4 \ -boot-info-table \ -o DEBIAN-automatique.iso isofiles
La commande crée un fichier DEBIAN-automatique.iso
à partir du
contenu du dossier isofiles
dans lequel nous avons construit un
initrd.gz
avec un preseed.cfg
incorporé.
Il ne reste plus qu'à graver le CD sur un support usb ou disque optique, tester et profiter d'une installation automatisée.
Si celle-ci échoue il faudra modifier le fichier preseed.cfg
et
revenir dans le cycle : incorporation du preseed.cfg
dans
l'initrd.gz
, reconstruction du fichier de sommes de calculs
md5sum.txt
et création de l'iso.
Cette opération peut elle-même être automatisée pour accélérer la procédure. Un exemple est donné en fin d'article.
Un des éléments les plus intéressants dans cette méthode est la
possibilité d'exécuter des commandes juste avant la fin de
l'installation avec la clé preseed/late_command
.
À la fin du preseed.cfg
exemple fourni par Debian, nous pouvons lire
# This command is run just before the install finishes, but when there is # still a usable /target directory. You can chroot to /target and use it # directly, or use the apt-install and in-target commands to easily install # packages and run commands in the target system. # d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
Quelques informations importantes sont données ici :
/target
in-target
de la clé preseed/late_command
permet d'exécuter des commandes en chroot
c'est à dire en considérant le disque dur de l'ordinateur comme racine d'exécution.
Dans l'exemple du pressed.cfg
fourni par Debian, le paquet zsh
est
installé et fera partie du système d'exploitation final. Ensuite, avec
in-target
, la commande de changement de shell de connexion (chsh
-s
) est exécutée avec le disque dur contenant le système
d'exploitation final comme environnement d'exécution.
Après avoir maîtrisé la procédure de modification du système d'exploitation minimal, une customisation plus approfondi du système d'exploitation final est possible.
Rien n'empêche l'ajout d'autres fichiers que le preseed.cfg
dans le
système d'installation initrd.gz
.
Nous pouvons y incorporer, une liste de clés publiques ssh et les injecter dans le système final. Ça nous permettra d'accéder à la machine sans mot de passe.
Nous pouvons également injecter des scripts d'initialisation qui s'exécuteront au premier redémarrage de la machine après la fin de l'installation.
Les exemples donnés ici sont triviaux et ne servent qu'à illustrer la procédure.
De la même manière que nous avons ajouté le fichier preseed.cfg
dans
initrd
, nous allons ajouter un fichier contenant des clés ssh
publiques et nous utilisons preseed/late_command
pour les injecter
dans le système d'exploitation final.
# echo preseed.cfg | cpio -H newc -o -A -F isofiles/install.amd/initrd # echo authorized_keys | cpio -H newc -o -A -F isofiles/install.amd/initrd
Et dans le fichier preseed.cfg
:
# [....] d-i preseed/late_command string \ in-target mkdir /root/.ssh; \ cp /authorized_keys /target/root/.ssh/; \ in-target chmod 700 /root/.ssh; \ in-target chmod 600 /root/.ssh/authorized_keys; \ true;
Même en excluant la nécessité d'interaction lors de la procédure d'installation d'un système d'exploitation, l'opération demeure lourde.
Utiliser un système de virtualisation pour tester immédiatement le résultat est incontournable pour avancer en toute sécurité et pour maîtriser rapidement la procédure.
Ci-dessous un script qui fait usage de libvirt
pour tester l'iso
« preseedé ». Une introduction à libvirt
est accessible à cette page.
#!/bin/bash ########################################################################################## # This script help on testing preseed.cfg for automatic unattended debian install # # # # The script needs genisoimage, bsdtar, syslinux-utils installed on your system # ########################################################################################## MAKE_VM="$1" # calling this script with `vm' as argument launch the installation # with the preseeded iso on a virsh domain # OPDIR="$( cd "$(dirname "$0")" ; pwd -P )"/ ORIGIN_ISO="$(basename "/home/aziz/debian-9.6.0-amd64-netinst.iso")" TARGET_VM=sarahdeb # the name of the vm to create DISC_SIZE=8 RAM_SIZE=512 CPU=1 PROVISION_FILES="postinstall.sh preseed.cfg rc.local authorized_keys" # files injected into the install process RESULT_ISO=sarahdeb-${ORIGIN_ISO} # 'generated iso name' will be 'origin iso name' prefixed with 'preseed-' ORIGIN_ISO_PATH="/home/aziz/debian-9.6.0-amd64-netinst.iso" RESULT_ISO_PATH=${OPDIR}${RESULT_ISO} EXTRACTED_ISO_DIR=${ORIGIN_ISO/\.iso/} EXTRACTED_ISO_PATH=/tmp/${EXTRACTED_ISO_DIR}/ # The path to directory containing extracted iso files INSTALLAMD_DIR=install.amd/ INSTALLAMD_PATH=${EXTRACTED_ISO_PATH}${INSTALLAMD_DIR} INITRDGZ_FILE=initrd.gz INITRD_FILE=initrd INITRDGZ_PATH=${INSTALLAMD_PATH}${INITRDGZ_FILE} # path to initrd.gz INITRD_PATH=${INSTALLAMD_PATH}${INITRD_FILE} LIST_RUNNING_VM_COMMAND="virsh -c qemu:///system list --state-running --name" LIST_ALL_VM_COMMAND="virsh -c qemu:///system list --all --name" function check_deps(){ dpkg-query -l bsdtar &> /dev/null ; if [ ! $? == "0" ];then sudo apt-get install -y bsdtar fi dpkg-query -l genisoimage &> /dev/null ; if [ ! $? == "0" ];then sudo apt-get install -y genisoimage fi } check_deps || exit 2; function purge_vm(){ # before beginning the vm will be deleted for i in $(eval $LIST_RUNNING_VM_COMMAND); do if [ $i == $TARGET_VM ];then virsh -c qemu:///system destroy $TARGET_VM break; fi done for i in $(eval $LIST_ALL_VM_COMMAND); do if [ $i == $TARGET_VM ];then virsh -c qemu:///system undefine $TARGET_VM --remove-all-storage break; fi done } function extract_iso(){ cd $OPDIR mkdir $EXTRACTED_ISO_PATH bsdtar -C $EXTRACTED_ISO_PATH -xf $ORIGIN_ISO_PATH } function unlock (){ chmod +w -R $1; } # to make a dir writable function ziplock(){ chmod -w -R $1; } # to revert to readonly function reuse_extracted_iso_path(){ # if an iso has been already extracted # just pick the initrd.gz file from a temporary mount # instead of extracting tempdir=$(mktemp -d) sudo mount -o loop $ORIGIN_ISO_PATH $tempdir unlock $INSTALLAMD_PATH rm $INITRDGZ_PATH cp $tempdir/${INSTALLAMD_DIR}${INITRDGZ_FILE} $INITRDGZ_PATH ziplock $INSTALLAMD_PATH sudo umount $tempdir rm -rf $tempdir } function rewrite_initrd(){ # Usage: rewrite_initrd file1 file2 # inject space separated list of files into initrd # then gzip initrd to_inject="$@" unlock $INSTALLAMD_PATH gunzip $INITRDGZ_PATH cd $OPDIR for file in $to_inject; do echo Adding $file to initrd echo $file | cpio -H newc -o -A -F $INITRD_PATH done gzip $INITRD_PATH ziplock $INSTALLAMD_PATH } function rewrite_isolinux_cfg() { unlock ${EXTRACTED_ISO_PATH}isolinux FILE=${EXTRACTED_ISO_PATH}isolinux/txt.cfg rm $FILE cat >$FILE <<EOF default install label install menu label ^Install menu default kernel /${INSTALLAMD_DIR}vmlinuz append vga=788 initrd=/${INSTALLAMD_DIR}initrd.gz --- quiet EOF sed -i 's/^timeout.*/timeout 1/' ${EXTRACTED_ISO_PATH}isolinux/isolinux.cfg sed -i 's/^timeout.*/timeout 1/' ${EXTRACTED_ISO_PATH}isolinux/prompt.cfg ziplock ${EXTRACTED_ISO_PATH}isolinux } function rebuild_md5sum_file(){ # The md5sum.txt file must be rebuilt # after changing iso contents cd $EXTRACTED_ISO_PATH md5sum `find -follow -type f` | sudo tee md5sum.txt >/dev/null cd $OPDIR } function geniso(){ # Generating the preseeded iso cd $OPDIR sudo genisoimage -quiet -r -J -b isolinux/isolinux.bin \ -c isolinux/boot.cat \ -no-emul-boot \ -boot-load-size 4 \ -boot-info-table \ -o $RESULT_ISO_PATH $EXTRACTED_ISO_PATH sudo isohybrid $RESULT_ISO_PATH } function install_vm_from_preseed(){ # Creating the vm to test install cd $OPDIR virt-install --connect qemu:///system \ --virt-type kvm \ --os-variant generic \ --os-type linux \ --network network=default \ --name=$TARGET_VM \ --disk size=$DISC_SIZE \ --ram=$RAM_SIZE \ --vcpus=$CPU \ --graphics vnc \ --console pty,target_type=serial \ --cdrom $RESULT_ISO_PATH } function main(){ if [ ! -z $MAKE_VM ]; then purge_vm; fi if [ ! -d $EXTRACTED_ISO_PATH ]; then extract_iso; else reuse_extracted_iso_path; fi rewrite_isolinux_cfg; rewrite_initrd $PROVISION_FILES; rebuild_md5sum_file; geniso; if [ ! -z $MAKE_VM ]; then install_vm_from_preseed; fi } main #purge_vm; function install_vm_from_location(){ cd $OPDIR virt-install --connect qemu:///system \ --virt-type kvm \ --os-variant generic \ --os-type linux \ --network network=default \ --name=$TARGET_VM \ --disk size=$DISC_SIZE \ --ram=$RAM_SIZE \ --vcpus=$CPU \ --graphics vnc \ --console pty,target_type=serial \ --initrd-inject preseed.cfg \ --extra-args "ipv6.disable=1 BOOT_DEBUG=0 DEBIAN_FRONTEND=text console=ttyS0,115200n8" \ --location "http://ftp2.de.debian.org/debian/dists/stretch/main/installer-amd64/" } #install_vm_from_location
######################### # Keyboard and TimeZone # ######################### d-i keyboard-configuration/xkb-keymap select fr(latin9) d-i debian-installer/locale string fr_FR d-i time/zone string Africa/Algiers d-i clock-setup/ntp boolean true d-i clock-setup/utc boolean true ################### # Hardware detect # ################### d-i hw-detect/load_firmware boolean true ################# # User creation # ################# d-i passwd/root-login boolean false d-i passwd/user-fullname string dino d-i passwd/username string dino d-i passwd/user-password-again password dingo d-i passwd/user-password password dingo ################################# # Network and hostname settings # ################################# d-i netcfg/get_hostname string dalton d-i netcfg/hostname string dalton d-i netcfg/choose_interface select auto d-i netcfg/get_domain string d-i netcfg/link_wait_timeout string 5 d-i netcfg/wireless_wep string ######################### # Partitionning section # ######################### d-i partman-auto/method string regular d-i partman-auto/choose_recipe select atomic d-i partman-auto/disk string /dev/sda d-i partman/mount_style select uuid d-i partman/choose_partition select finish d-i partman-partitioning/confirm_write_new_label boolean true d-i partman-lvm/device_remove_lvm boolean true d-i partman-md/confirm boolean true d-i partman-md/device_remove_md boolean true d-i partman/confirm boolean true d-i partman/confirm_nooverwrite boolean true ####################### # Apt mirror settings # ####################### apt-mirror-setup apt-setup/no_mirror boolean true d-i mirror/country string manual d-i mirror/http/directory string /debian d-i mirror/http/hostname string deb.debian.org d-i mirror/http/proxy string d-i mirror/protocol string http d-i mirror/suite string stretch d-i mirror/udeb/suite string stretch d-i apt-setup/contrib boolean true d-i apt-setup/non-free boolean true d-i apt-setup/security_host string security.debian.org d-i apt-setup/services-select multiselect security, updates d-i apt-setup/use_mirror boolean false d-i base-installer/install-recommends boolean true d-i debian-installer/allow_unauthenticated boolean true ############################ # Do not ask about more CD # ############################ apt-cdrom-setup apt-setup/cdrom/set-double boolean false apt-cdrom-setup apt-setup/cdrom/set-first boolean false apt-cdrom-setup apt-setup/cdrom/set-next boolean false ######################### # No popularity contest # ######################### popularity-contest popularity-contest/participate boolean false ####################### # Packages to install # ####################### tasksel tasksel/first multiselect standard d-i pkgsel/include string openssh-server d-i pkgsel/upgrade select none ################ # Grub install # ################ d-i grub-installer/bootdev string default d-i grub-installer/only_debian boolean true d-i grub-installer/with_other_os boolean true ################# # Late commands # ################# d-i preseed/late_command string \ in-target mkdir /home/dino/.ssh; \ cp /authorized_keys /target/home/dino/.ssh/; \ in-target chown -R dino: /home/dino/.ssh; \ in-target chmod 700 /home/dino/.ssh; \ in-target chmod 600 /home/dino/.ssh/authorized_keys; \ true; ############ # Good Bye # ############ d-i finish-install/reboot_in_progress note