7daca57714
Implement a new Anaconda spoke that allows users to select their preferred desktop environment (CLI, GNOME, KDE Plasma, Hyprland, or XFCE) during installation. The spoke: - Displays radio buttons for five desktop choices with CLI as the default - Persists the selection to /tmp/fws-desktop for the kickstart %post script - Supports revisiting the spoke and resuming previous selections - Includes a GTK UI definition file (glade) with translatable labels - Integrates as a SoftwareCategory spoke in the Anaconda installer The implementation leverages Anaconda's runtime spoke discovery mechanism via the airootfs overlay, avoiding the need to rebuild the anaconda package.
258 lines
14 KiB
Plaintext
258 lines
14 KiB
Plaintext
# ============================================================================
|
|
# FWS — interactive-defaults.ks
|
|
#
|
|
# Kickstart de base, lu AUTOMATIQUEMENT par Anaconda quand l'install est
|
|
# lancée en mode interactif (chemin fixe codé en dur dans Anaconda :
|
|
# /usr/share/anaconda/interactive-defaults.ks). Aucun inst.ks= n'est requis.
|
|
#
|
|
# RÔLE : empêcher Anaconda d'installer Fedora.
|
|
# ----------------------------------------------------------------------------
|
|
# Sans payload défini, Anaconda utilise DNF → des RPM depuis les dépôts
|
|
# Fedora = il installe Fedora. Anaconda n'a AUCUN backend pacman. La seule
|
|
# façon de poser FWS/Arch est le payload « liveimg » : il recopie une image
|
|
# de système de fichiers (ici le squashfs du live = FWS) sur le disque, puis
|
|
# on finalise nous-mêmes (grub, mkinitcpio, bureau) en %post. C'est le modèle
|
|
# « Sabayon » : le système installé EST une copie du live.
|
|
#
|
|
# L'utilisateur garde la main dans le GUI sur tout ce qui N'EST PAS fixé ici :
|
|
# partitionnement, fuseau, clavier, langue, création d'utilisateur, mot de
|
|
# passe root, etc.
|
|
# ============================================================================
|
|
|
|
# --- Source d'installation : l'image du live (FWS), surtout pas Fedora -------
|
|
# Squashfs archiso sur le média booté :
|
|
# /run/archiso/bootmnt/<install_dir>/<arch>/airootfs.sfs
|
|
# install_dir=fws, arch=x86_64, airootfs_image_type=squashfs (cf. profiledef.sh).
|
|
# Anaconda loop-monte ce .sfs et rsync son contenu vers la cible.
|
|
#
|
|
# ⚠ À VALIDER sur ISO réelle : certaines versions d'Anaconda attendent une
|
|
# structure « LiveOS/rootfs.img » à l'intérieur du squashfs (format Fedora
|
|
# Live) et non un squashfs « plat » comme celui d'archiso. Si l'install
|
|
# échoue à monter la source, basculer sur un tarball de rootfs dédié :
|
|
# liveimg --url=file:///run/archiso/bootmnt/fws/x86_64/fws-rootfs.tar.gz
|
|
# (un build-rootfs.sh produirait alors ce tar via pacstrap).
|
|
liveimg --url=file:///run/archiso/bootmnt/fws/x86_64/airootfs.sfs
|
|
|
|
# --- Disque : repartir d'un disque PROPRE, même s'il a déjà servi ------------
|
|
# Sans ça, une réinstallation sur un disque déjà partitionné (typiquement une
|
|
# install FWS précédente : partitions + VG LVM « anaconda_archiso ») pose deux
|
|
# problèmes : le partitionnement auto n'a plus d'espace libre, et blivet
|
|
# rescanne/auto-active un LVM existant au boot du live → l'installateur se
|
|
# comporte mal voire plante au 2e passage (alors qu'un disque vierge passe).
|
|
# zerombr : réinitialise toute table de partitions invalide
|
|
# (répond « oui » au lieu de bloquer sur un disque
|
|
# non reconnu).
|
|
# clearpart --all : supprime TOUTES les partitions de TOUS les disques.
|
|
# --initlabel : réécrit une étiquette de disque neuve.
|
|
# --disklabel=msdos : force une table MBR (et non GPT). CRUCIAL en BIOS :
|
|
# en BIOS+GPT, GRUB i386-pc exige une partition « BIOS
|
|
# Boot » (~1 Mo, type EF02) pour embarquer core.img,
|
|
# qu'Anaconda NE crée PAS avec « bootloader --disabled
|
|
# » → « this GPT partition label contains no BIOS Boot
|
|
# Partition; embedding won't be possible » →
|
|
# grub-install échoue. En MBR, core.img se loge dans
|
|
# l'espace post-MBR, aucune partition dédiée requise.
|
|
# ⚠ Ce choix vise le BIOS (cas VMware actuel). Pour l'UEFI il faudra du GPT
|
|
# (+ ESP) — à rendre dépendant du firmware (%pre) le jour où on cible l'UEFI.
|
|
# L'utilisateur garde la main dans le GUI (il peut repasser en manuel), mais le
|
|
# DÉFAUT est désormais un disque net → réinstall fiable à chaque fois.
|
|
# ⚠ VM mono-disque : « --all » efface le seul disque, c'est voulu. Sur une
|
|
# machine multi-disques il faudrait cibler avec « --drives=sda ».
|
|
zerombr
|
|
clearpart --all --initlabel --disklabel=msdos
|
|
|
|
# --- Bootloader : géré à la main en %post ------------------------------------
|
|
# Anaconda lancerait « grub2-install » / « grub2-mkconfig » (binaires Fedora,
|
|
# préfixe grub2-) qui n'existent pas dans un rootfs Arch (lequel fournit
|
|
# grub-install / grub-mkconfig). On désactive donc l'étape native d'Anaconda.
|
|
# L'ESP (UEFI) ou la partition bios_boot (BIOS/GPT) reste créée par le
|
|
# partitionnement (auto ou manuel) car la plateforme l'impose.
|
|
bootloader --disabled
|
|
|
|
# Pas de section %packages : le payload liveimg n'installe aucun paquet
|
|
# (il copie une image). Toute installation de paquets se fait en %post.
|
|
|
|
|
|
# ============================================================================
|
|
# %post --nochroot — s'exécute dans le LIVE, la cible montée sous /mnt/sysroot
|
|
# But : déposer dans la cible ce dont le %post chrooté aura besoin (DNS pour
|
|
# pacman, choix de bureau écrit par l'addon de sélection).
|
|
# ============================================================================
|
|
%post --nochroot --log=/tmp/fws-post-nochroot.log
|
|
set -x
|
|
|
|
# Selon la version d'Anaconda la cible est sous /mnt/sysroot (récent) ou
|
|
# /mnt/sysimage (ancien).
|
|
SYSROOT=/mnt/sysroot
|
|
[ -d "$SYSROOT" ] || SYSROOT=/mnt/sysimage
|
|
|
|
# DNS pour que « pacman -S <bureau> » fonctionne dans le chroot.
|
|
cp -f /etc/resolv.conf "$SYSROOT/etc/resolv.conf" 2>/dev/null || true
|
|
|
|
# --- Hostname : valeur saisie dans le champ « Nom de machine » du spoke User --
|
|
# Anaconda ne capte PAS le hostname du spoke Réseau (→ /etc/hostname vide). On a
|
|
# donc ajouté un champ Hostname au spoke Utilisateur (cf. patch du paquet
|
|
# anaconda) : user.py écrit la valeur dans /tmp/fws-hostname (live). On la
|
|
# nettoie (caractères de hostname valides) et on l'écrit dans la cible ; défaut
|
|
# « fws » si vide/absent → plus jamais de hostname vide ni « archiso ».
|
|
HN=""
|
|
[ -f /tmp/fws-hostname ] && HN="$(tr -cd 'a-zA-Z0-9._-' < /tmp/fws-hostname)"
|
|
[ -n "$HN" ] || HN="fws"
|
|
echo "$HN" > "$SYSROOT/etc/hostname"
|
|
|
|
# Choix du bureau (écrit par l'addon « Choix du bureau », à venir ; valeur lue
|
|
# par le %post chrooté ci-dessous). « cli » par défaut si absent.
|
|
if [ -f /tmp/fws-desktop ]; then
|
|
cp -f /tmp/fws-desktop "$SYSROOT/tmp/fws-desktop" 2>/dev/null || true
|
|
fi
|
|
|
|
# --- Noyau : archiso RETIRE /boot/vmlinuz-linux du squashfs ------------------
|
|
# mkarchiso boote le noyau depuis l'ISO et l'EXCLUT de l'airootfs squashfs (gain
|
|
# de place). Conséquence : le payload LiveOS recopie un rootfs SANS noyau →
|
|
# « mkinitcpio: /boot/vmlinuz-linux must be readable » puis aucun OS à booter
|
|
# (« Operating System not found »). On récupère donc le noyau depuis le média
|
|
# booté (/run/archiso/bootmnt/<install_dir>/boot/<arch>/vmlinuz-linux) et on le
|
|
# dépose dans la cible. Les modules (/usr/lib/modules) sont, eux, dans le
|
|
# squashfs → déjà recopiés. Avec le noyau présent, le %post chrooté peut bâtir
|
|
# l'initramfs (mkinitcpio) et GRUB trouve de quoi booter.
|
|
SRC_KERN="$(find /run/archiso/bootmnt -name 'vmlinuz-linux' 2>/dev/null | head -1)"
|
|
if [ -n "$SRC_KERN" ]; then
|
|
cp -f "$SRC_KERN" "$SYSROOT/boot/vmlinuz-linux"
|
|
else
|
|
echo "[FWS] AVERTISSEMENT : noyau vmlinuz-linux introuvable sur le média"
|
|
fi
|
|
%end
|
|
|
|
|
|
# ============================================================================
|
|
# %post (chroot) — DANS le rootfs FWS recopié. pacman, grub-install,
|
|
# mkinitcpio existent ici : ce sont les outils Arch de l'image copiée.
|
|
# Log persistant : /var/log/fws-post.log sur le système installé.
|
|
# ============================================================================
|
|
%post --log=/var/log/fws-post.log
|
|
set -x
|
|
|
|
# --- 1) Purge des résidus « live » (modèle Sabayon = live copié tel quel) ----
|
|
# Ce qui est propre au live casserait ou pollue le système installé.
|
|
rm -f /etc/mkinitcpio.conf.d/archiso.conf
|
|
rm -f /etc/systemd/system/getty@tty1.service.d/autologin.conf
|
|
for svc in choose-mirror.service pacman-init.service \
|
|
livecd-talk.service livecd-alsa-unmuter.service \
|
|
etc-pacman.d-gnupg.mount; do
|
|
rm -f "/etc/systemd/system/$svc"
|
|
rm -f /etc/systemd/system/*.target.wants/"$svc"
|
|
done
|
|
# cloud-init (présent dans l'airootfs archiso) : inutile sur un poste installé.
|
|
rm -f /etc/systemd/system/cloud-init.target.wants/* 2>/dev/null || true
|
|
# Hooks initramfs archiso, s'ils ont été recopiés en tant que paquet.
|
|
if pacman -Q mkinitcpio-archiso &>/dev/null; then
|
|
pacman -Rns --noconfirm mkinitcpio-archiso || true
|
|
fi
|
|
|
|
# --- 2) initramfs propre (preset Arch standard, sans archiso) ----------------
|
|
# Le live fournit un preset 'archiso' (/etc/mkinitcpio.d/linux.preset qui pointe
|
|
# vers conf.d/archiso.conf + hooks archiso) → inadapté à un disque normal. On
|
|
# pose un preset Arch standard (config par défaut /etc/mkinitcpio.conf).
|
|
cat > /etc/mkinitcpio.d/linux.preset <<'PRESET'
|
|
ALL_kver="/boot/vmlinuz-linux"
|
|
PRESETS=('default' 'fallback')
|
|
default_image="/boot/initramfs-linux.img"
|
|
fallback_image="/boot/initramfs-linux-fallback.img"
|
|
fallback_options="-S autodetect"
|
|
PRESET
|
|
# Le partitionnement auto d'Anaconda met « / » sur LVM (/dev/mapper/...-root).
|
|
# Sans le hook 'lvm2' dans l'initramfs, le VG n'est pas activé au boot → la
|
|
# racine est introuvable → kernel panic. On l'insère avant 'filesystems' s'il
|
|
# manque (inoffensif si la racine n'est finalement pas sur LVM).
|
|
if ! grep -qE '^HOOKS=.*\blvm2\b' /etc/mkinitcpio.conf; then
|
|
sed -i -E 's/^(HOOKS=\(.*)\bfilesystems\b/\1lvm2 filesystems/' /etc/mkinitcpio.conf
|
|
fi
|
|
mkinitcpio -P || echo "[FWS] AVERTISSEMENT : mkinitcpio a échoué"
|
|
|
|
# --- 3) GRUB installé à la main (cf. bootloader --disabled) ------------------
|
|
install_grub() {
|
|
if [ -d /sys/firmware/efi ]; then
|
|
# UEFI. efibootmgr crée l'entrée NVRAM « FWS », mais il peut MANQUER de
|
|
# l'airootfs et son install dépend du réseau → on ne BLOQUE pas dessus.
|
|
pacman -Q efibootmgr &>/dev/null || pacman -Sy --noconfirm efibootmgr || true
|
|
# (a) Entrée NVRAM dédiée (best effort, si efibootmgr dispo) :
|
|
grub-install --target=x86_64-efi --efi-directory=/boot/efi \
|
|
--bootloader-id=FWS --recheck || true
|
|
# (b) Chemin de SECOURS EFI/BOOT/BOOTX64.EFI (--removable) : boote SANS
|
|
# aucune entrée NVRAM. INDISPENSABLE en VM / sans réseau / firmware
|
|
# qui « oublie » l'entrée — c'est lui qui garantit le 1er boot UEFI.
|
|
grub-install --target=x86_64-efi --efi-directory=/boot/efi \
|
|
--bootloader-id=FWS --removable --recheck
|
|
else
|
|
# BIOS : installer GRUB dans le MBR du DISQUE physique (PAS une partition)
|
|
# portant « / », même quand « / » est sur du LVM (chaîne
|
|
# LV → PV partition → disque). « lsblk -s » descend vers le physique ; on
|
|
# prend la ligne de type « disk ». ATTENTION : « lsblk -s » dessine un
|
|
# ARBRE → les caractères de branche (└─) se collent au chemin (on
|
|
# obtenait disk='-/dev/sda' → « grub-install: cannot find a GRUB drive
|
|
# for `-/dev/sda' »). On EXTRAIT donc le chemin propre avec grep.
|
|
local rootsrc disk
|
|
rootsrc="$(findmnt -no SOURCE / 2>/dev/null)"
|
|
disk="$(lsblk -spno NAME,TYPE "$rootsrc" 2>/dev/null \
|
|
| awk '$2=="disk"{print $1; exit}' | grep -oE '/dev/[a-z0-9]+')"
|
|
[ -n "$disk" ] || { echo "[FWS] Disque BIOS introuvable pour '$rootsrc'"; return 1; }
|
|
grub-install --target=i386-pc --recheck "$disk"
|
|
fi
|
|
}
|
|
if install_grub; then
|
|
grub-mkconfig -o /boot/grub/grub.cfg || echo "[FWS] grub-mkconfig a échoué"
|
|
else
|
|
echo "[FWS] AVERTISSEMENT : grub-install a échoué — bootloader à refaire à la main"
|
|
fi
|
|
|
|
# --- 4) Bureau choisi : pacman -S du DE (non bloquant si pas de réseau) -------
|
|
DESK="cli"
|
|
[ -f /tmp/fws-desktop ] && DESK="$(tr -d '[:space:]' < /tmp/fws-desktop)"
|
|
DM=""
|
|
case "$DESK" in
|
|
kde) PKGS="plasma-meta sddm konsole dolphin"; DM="sddm" ;;
|
|
gnome) PKGS="gnome gdm"; DM="gdm" ;;
|
|
xfce) PKGS="xfce4 xfce4-goodies lightdm lightdm-gtk-greeter"; DM="lightdm" ;;
|
|
hyprland) PKGS="hyprland kitty wofi waybar sddm"; DM="sddm" ;;
|
|
cli|*) PKGS="" ;;
|
|
esac
|
|
# Navigateur de base ajouté DÈS QU'un bureau est choisi (jamais en CLI).
|
|
[ -n "$PKGS" ] && PKGS="$PKGS firefox"
|
|
if [ -n "$PKGS" ]; then
|
|
pacman-key --init &>/dev/null || true
|
|
pacman-key --populate archlinux &>/dev/null || true
|
|
if pacman -Sy --noconfirm $PKGS; then
|
|
[ -n "$DM" ] && systemctl enable "$DM" || true
|
|
systemctl set-default graphical.target || true
|
|
else
|
|
echo "[FWS] Bureau '$DESK' non installé (réseau ?) — à refaire après le 1er boot."
|
|
fi
|
|
fi
|
|
|
|
# --- 5) Sécurité : verrouiller root s'il est resté SANS mot de passe ----------
|
|
# L'airootfs live a souvent un root sans mot de passe ; si l'utilisateur n'en a
|
|
# pas défini dans le GUI, on verrouille plutôt que de laisser le compte ouvert.
|
|
if passwd -S root 2>/dev/null | grep -qE '\bNP\b'; then
|
|
passwd -l root || true
|
|
fi
|
|
|
|
# --- 6) Le resolv.conf du live ne doit pas rester figé -----------------------
|
|
# NetworkManager (activé sur le système installé) régénère /etc/resolv.conf.
|
|
rm -f /tmp/fws-desktop /etc/resolv.conf 2>/dev/null || true
|
|
%end
|
|
|
|
|
|
# ============================================================================
|
|
# %post --nochroot (FINAL) — exfiltre le log du %post chrooté vers le LIVE.
|
|
# À ce stade la cible est ENCORE montée sous /mnt/sysroot (l'unmount n'a pas
|
|
# encore eu lieu). On copie /var/log/fws-post.log (résultat de grub-install /
|
|
# mkinitcpio) vers le live /tmp pour que le harnais de debug (.xinitrc)
|
|
# l'affiche SANS avoir à remonter le disque démonté — c'est ce log qui dit si
|
|
# le disque va booter.
|
|
# ============================================================================
|
|
%post --nochroot
|
|
SYSROOT=/mnt/sysroot
|
|
[ -d "$SYSROOT" ] || SYSROOT=/mnt/sysimage
|
|
cp -f "$SYSROOT/var/log/fws-post.log" /tmp/fws-post-chroot.log 2>/dev/null || true
|
|
%end
|