d8e67fe861
Update interactive-defaults.ks kickstart file with: - Clarified documentation on LiveOS payload detection and mounting via /run/rootfsbase bind-mount instead of direct liveimg directive - Added comprehensive comments explaining why liveimg directive is intentionally omitted and how anaconda --liveinst handles payload creation - Enhanced XFCE and Hyprland package sets with noto-fonts for proper TTF rendering and additional tools (thunar, hyprlock, grim, slurp, wl-clipboard, playerctl) - Implemented SDDM theme configuration with FWS theme support and accent colors per desktop environment (teal for XFCE, Catppuccin blue for Hyprland, Breeze blue for KDE) - Added GDM (GNOME) configuration via dconf with welcome banner, clock enhancements, and numlock settings - Expanded Waybar configuration installation for Hyprland with config and style files - Added comprehensive documentation for greeter customization and Hyprland VM compatibility - Included details about FWS recap spoke (standalone GUI summary screen) replacing zenity-based pre-install approach
480 lines
26 KiB
Plaintext
480 lines
26 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 : finaliser une install « copie du live » (surtout pas Fedora).
|
|
# ----------------------------------------------------------------------------
|
|
# Anaconda n'a AUCUN backend pacman ; son payload par défaut (DNF) poserait
|
|
# des RPM Fedora. Ici le payload est LiveOS, imposé par « anaconda --liveinst »
|
|
# (cf. bloc « Source d'installation » ci-dessous) : il recopie 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 : le payload LiveOS (surtout pas Fedora/DNF) ------
|
|
# AUCUNE directive de payload ici, et c'est VOULU. liveinst lance
|
|
# « anaconda --liveinst » et anaconda.py teste opts.liveinst AVANT le type du
|
|
# payload DBus → il crée TOUJOURS un payload LiveOS et IGNORE tout payload du
|
|
# kickstart (un « liveimg » ici serait du code mort — vérifié dans
|
|
# pyanaconda/anaconda.py, propriété payload, et reproduit hors VM).
|
|
#
|
|
# Le payload LiveOS détecte l'image live via /dev/mapper/live-base ou
|
|
# /run/rootfsbase (chemins Fedora/dracut, absents d'archiso → c'était le crash
|
|
# « SourceSetupError: No Live OS image found! » au démarrage). Le .xinitrc du
|
|
# live bind-monte donc /run/archiso/airootfs (squashfs FWS, ro) sur
|
|
# /run/rootfsbase AVANT de lancer liveinst : Anaconda monte le loop device et
|
|
# rsync son contenu vers la cible = le système installé EST une copie du live,
|
|
# puis on finalise en %post (grub, mkinitcpio, bureau, matériel).
|
|
# DNF/libdnf5 n'est jamais importé : le module DNF n'est chargé QUE si le
|
|
# payload actif est DNF (import lazy dans modules/payloads/payload/factory.py).
|
|
|
|
# --- 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 LiveOS n'installe aucun paquet
|
|
# (il copie une image). Toute installation de paquets se fait en %post.
|
|
|
|
# --- Récapitulatif avant installation : PAGE GUI dédiée (pas de %pre-install) -
|
|
# L'écran « RÉCAPITULATIF AVANT INSTALLATION » est une standalone spoke
|
|
# Anaconda (overlay airootfs : pyanaconda/ui/gui/spokes/fws_recap.py,
|
|
# postForHub=SummaryHub, priority -10) intercalée ENTRE le hub et l'écran de
|
|
# progression : l'utilisateur clique « Commencer l'installation », voit le
|
|
# récap (bureau choisi, hostname, disques, GPU, réseau — AUCUNE écriture
|
|
# disque à ce stade), et l'installation ne démarre qu'à son clic « Lancer
|
|
# l'installation ». L'ancien récap zenity en %pre-install a été abandonné :
|
|
# le module scripts tourne avec LC_ALL=C et un env X incertain (zenity 4
|
|
# refuse les libellés UTF-8 en locale C → rc=255 pris pour « Annuler » →
|
|
# poweroff en plein install au 1er test réel).
|
|
|
|
|
|
# ============================================================================
|
|
# %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
|
|
|
|
# --- 3bis) Clavier (X11) + LOCALE --------------------------------------------
|
|
# CLAVIER : Anaconda passe par localed et n'écrit pas fiablement la disposition X
|
|
# sur la CIBLE → SDDM / sessions X en QWERTY US. On CALCULE la disposition CHOISIE
|
|
# (kickstart généré, sinon dérivée de la locale via langtable) en XL/XV, réutilisés
|
|
# plus bas (00-keyboard.conf pour SDDM/X ET la config Hyprland qui a son propre
|
|
# kb_layout). LOCALE : le locale choisi (ex. fr_CH.UTF-8) doit être GÉNÉRÉ —
|
|
# Anaconda vient de Fedora (locales pré-générées) et ne lance pas locale-gen →
|
|
# sans ça LANG casse et tout retombe en C.
|
|
XL=""; XV=""
|
|
XKB="$(sed -n "s/.*--xlayouts=//p" /root/anaconda-ks.cfg 2>/dev/null | head -1)"
|
|
XKB="${XKB#[\'\"]}"; XKB="${XKB%%[\'\"]*}"; XKB="${XKB%%,*}" # 1re dispo, ex. « ch (fr) »
|
|
if [ -z "$XKB" ]; then
|
|
_loc="$(. /etc/locale.conf 2>/dev/null; printf '%s' "${LANG%%.*}")" # fr_CH
|
|
_lng="${_loc%%_*}"; _terr="${_loc#*_}"; [ "$_terr" = "$_loc" ] && _terr=""
|
|
[ -n "$_terr" ] && XKB="$(python3 -c "import langtable; k=langtable.list_keyboards(languageId='$_lng', territoryId='$_terr'); print(k[0] if k else '')" 2>/dev/null)"
|
|
fi
|
|
if [ -n "$XKB" ]; then
|
|
XL="${XKB%%(*}"; XL="${XL%% *}" # ch
|
|
case "$XKB" in *'('*')') XV="${XKB#*(}"; XV="${XV%)}" ;; *) XV="" ;; esac # fr
|
|
install -d /etc/X11/xorg.conf.d
|
|
cat > /etc/X11/xorg.conf.d/00-keyboard.conf <<KBEOF
|
|
Section "InputClass"
|
|
Identifier "system-keyboard"
|
|
MatchIsKeyboard "on"
|
|
Option "XkbLayout" "$XL"
|
|
Option "XkbVariant" "$XV"
|
|
EndSection
|
|
KBEOF
|
|
fi
|
|
|
|
FWSLANG="$(. /etc/locale.conf 2>/dev/null; printf '%s' "${LANG:-}")"
|
|
if [ -n "$FWSLANG" ]; then
|
|
_cs="${FWSLANG##*.}"; [ "$_cs" = "$FWSLANG" ] && _cs="UTF-8"
|
|
grep -qE "^[[:space:]]*${FWSLANG}[[:space:]]+${_cs}\b" /etc/locale.gen 2>/dev/null \
|
|
|| printf '%s %s\n' "$FWSLANG" "$_cs" >> /etc/locale.gen
|
|
locale-gen || echo "[FWS] locale-gen a échoué pour $FWSLANG"
|
|
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" ;;
|
|
# noto-fonts : KDE l'a via plasma-meta et GNOME a cantarell, mais XFCE et
|
|
# Hyprland ne garantissent AUCUNE police TTF → greeter SDDM/apps illisibles.
|
|
# Hyprland : la stack des raccourcis FWS (mêmes touches que la config
|
|
# i3/sway maison) — thunar (Super+E), hyprlock (Super+L), grim+slurp+
|
|
# wl-clipboard (captures), playerctl (touches multimédia).
|
|
xfce) PKGS="xfce4 xfce4-goodies sddm noto-fonts"; DM="sddm" ;;
|
|
hyprland) PKGS="hyprland kitty wofi waybar sddm noto-fonts thunar hyprlock grim slurp wl-clipboard playerctl"; 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
|
|
# SDDM (KDE / XFCE / Hyprland) : pavé numérique + écran de connexion FWS.
|
|
# Le thème « fws » (livré par l'airootfs → recopié par le payload dans
|
|
# /usr/share/sddm/themes/fws) est en pur QtQuick/Controls Basic :
|
|
# qt6-declarative, dépendance de sddm, suffit → même écran soigné pour
|
|
# les 3 DE SANS paquet de thème supplémentaire (Breeze n'existe qu'avec
|
|
# plasma). Accent adapté au bureau via theme.conf.user (mécanisme de
|
|
# surcharge standard de SDDM, lu par-dessus theme.conf du thème).
|
|
if [ "$DM" = "sddm" ]; then
|
|
install -d /etc/sddm.conf.d
|
|
cat > /etc/sddm.conf.d/10-fws.conf <<'SDDMEOF'
|
|
[General]
|
|
Numlock=on
|
|
|
|
[Theme]
|
|
Current=fws
|
|
SDDMEOF
|
|
case "$DESK" in
|
|
xfce) _ACCENT="#16a085" ;; # sarcelle (assorti à XFCE)
|
|
hyprland) _ACCENT="#89b4fa" ;; # bleu Catppuccin (assorti à Hyprland)
|
|
*) _ACCENT="#3daee9" ;; # bleu Breeze (KDE, défaut)
|
|
esac
|
|
if [ -d /usr/share/sddm/themes/fws ]; then
|
|
printf '[General]\naccent=%s\n' "$_ACCENT" \
|
|
> /usr/share/sddm/themes/fws/theme.conf.user
|
|
else
|
|
echo "[FWS] thème SDDM fws introuvable — thème par défaut conservé"
|
|
sed -i '/^Current=fws$/d' /etc/sddm.conf.d/10-fws.conf
|
|
fi
|
|
fi
|
|
# GDM (GNOME) : « la même chose » autant que possible — le greeter de
|
|
# GDM EST GNOME Shell, il ne se thème pas comme SDDM. On passe par
|
|
# dconf (base système « gdm ») : bannière d'accueil FWS, horloge avec
|
|
# date complète, pavé numérique allumé — même confort qu'avec SDDM.
|
|
if [ "$DM" = "gdm" ]; then
|
|
install -d /etc/dconf/profile /etc/dconf/db/gdm.d
|
|
cat > /etc/dconf/profile/gdm <<'GDMEOF'
|
|
user-db:user
|
|
system-db:gdm
|
|
file-db:/usr/share/gdm/greeter-dconf-defaults
|
|
GDMEOF
|
|
cat > /etc/dconf/db/gdm.d/10-fws <<'GDMEOF'
|
|
[org/gnome/login-screen]
|
|
banner-message-enable=true
|
|
banner-message-text='Bienvenue sur FWS'
|
|
|
|
[org/gnome/desktop/interface]
|
|
clock-show-date=true
|
|
clock-show-weekday=true
|
|
|
|
[org/gnome/desktop/peripherals/keyboard]
|
|
numlock-state=true
|
|
remember-numlock-state=false
|
|
GDMEOF
|
|
dconf update || echo "[FWS] dconf update a échoué (bannière GDM à refaire)"
|
|
fi
|
|
# Hyprland en VM : sur GPU virtuel (VMware/VirtualBox) le compositeur
|
|
# crashe au lancement → SDDM « remet au login ». On le lance via un
|
|
# wrapper qui force le rendu LOGICIEL UNIQUEMENT en VM (systemd-detect-virt)
|
|
# ; sur un vrai GPU le rendu matériel est conservé.
|
|
if [ "$DESK" = "hyprland" ]; then
|
|
cat > /usr/local/bin/fws-hyprland <<'HYEOF'
|
|
#!/bin/sh
|
|
if systemd-detect-virt --quiet 2>/dev/null; then
|
|
# GPU virtuel (VMware vmwgfx…) : on FORCE le chemin d'affichage 100% logiciel.
|
|
# La PIÈCE MAÎTRESSE est MESA_LOADER_DRIVER_OVERRIDE=kms_swrast : elle force
|
|
# Mesa à allouer le GBM/EGL via kms_swrast (rendu logiciel dans les « dumb
|
|
# buffers » KMS) AU LIEU du pilote vmwgfx (qui ne fournit pas le GBM dont
|
|
# aquamarine a besoin → « CBackend::create() failed »). + llvmpipe pour le GL.
|
|
export MESA_LOADER_DRIVER_OVERRIDE=kms_swrast
|
|
export GALLIUM_DRIVER=llvmpipe LIBGL_ALWAYS_SOFTWARE=1
|
|
export WLR_RENDERER_ALLOW_SOFTWARE=1 WLR_NO_HARDWARE_CURSORS=1
|
|
export AQ_NO_ATOMIC=1
|
|
fi
|
|
exec Hyprland "$@"
|
|
HYEOF
|
|
chmod 755 /usr/local/bin/fws-hyprland
|
|
if [ -f /usr/share/wayland-sessions/hyprland.desktop ]; then
|
|
sed -i 's|^Exec=.*|Exec=/usr/local/bin/fws-hyprland|' \
|
|
/usr/share/wayland-sessions/hyprland.desktop
|
|
fi
|
|
fi
|
|
else
|
|
echo "[FWS] Bureau '$DESK' non installé (réseau ?) — à refaire après le 1er boot."
|
|
fi
|
|
fi
|
|
|
|
# --- 4quater) ADN FWS : détection matériel + drivers + stack « Windows » ------
|
|
# Script dédié (NON bloquant ; réseau requis) : drivers GPU détectés via lspci +
|
|
# outils invité VM, son/micro/casque (PipeWire), Bluetooth, Podman, et — si un
|
|
# bureau est choisi — Steam, Wine, VR (Monado/SteamVR), winboat-bin (apps
|
|
# Windows). C'est le cœur « remplacement de Windows » de FWS.
|
|
if [ -x /usr/local/bin/fws-setup-hardware ]; then
|
|
/usr/local/bin/fws-setup-hardware "$DESK" || true
|
|
fi
|
|
|
|
# --- Config Hyprland (si choisi) : clavier + apps + waybar -------------------
|
|
# Hyprland (Wayland) NE lit PAS /etc/X11/xorg.conf.d/00-keyboard.conf : sa
|
|
# disposition est dans SA config (input { kb_layout }). Sans config il démarre nu
|
|
# (QWERTY US, aucune touche utile). On déploie une config FWS (template +
|
|
# clavier XL/XV injecté) dans /etc/skel ET le home de chaque utilisateur déjà
|
|
# créé par Anaconda (le %post tourne APRÈS la création de l'utilisateur).
|
|
if [ "$DESK" = "hyprland" ] && [ -f /usr/local/share/fws/hyprland.conf.tmpl ]; then
|
|
sed -e "s/__KB_LAYOUT__/${XL:-us}/" -e "s/__KB_VARIANT__/${XV}/" \
|
|
/usr/local/share/fws/hyprland.conf.tmpl > /tmp/fws-hyprland.conf
|
|
install -Dm644 /tmp/fws-hyprland.conf /etc/skel/.config/hypr/hyprland.conf
|
|
# Waybar FWS : barre assortie + bouton « ⌨ Raccourcis » (fws-hypr-keys,
|
|
# aussi sur SUPER+K) qui liste les binds RÉELS chargés par Hyprland
|
|
# (hyprctl binds -j) — les descriptions viennent des bindd de la config.
|
|
install -Dm644 /usr/local/share/fws/waybar-config.json /etc/skel/.config/waybar/config
|
|
install -Dm644 /usr/local/share/fws/waybar-style.css /etc/skel/.config/waybar/style.css
|
|
while IFS=: read -r _u _x _uid _g _gec _home _sh; do
|
|
[ "$_uid" -ge 1000 ] && [ "$_uid" -le 60000 ] && [ -d "$_home" ] || continue
|
|
install -Dm644 /tmp/fws-hyprland.conf "$_home/.config/hypr/hyprland.conf"
|
|
install -Dm644 /usr/local/share/fws/waybar-config.json "$_home/.config/waybar/config"
|
|
install -Dm644 /usr/local/share/fws/waybar-style.css "$_home/.config/waybar/style.css"
|
|
chown "$_u": "$_home/.config" 2>/dev/null || true
|
|
chown -R "$_u": "$_home/.config/hypr" "$_home/.config/waybar" 2>/dev/null || true
|
|
done < /etc/passwd
|
|
rm -f /tmp/fws-hyprland.conf
|
|
fi
|
|
|
|
# --- 4bis) Sudo : l'utilisateur créé doit pouvoir administrer -----------------
|
|
# Arch laisse « %wheel » COMMENTÉ dans sudoers → même un membre de wheel ne peut
|
|
# pas sudo. On active le groupe wheel (drop-in) ET on y ajoute tous les
|
|
# utilisateurs HUMAINS (UID 1000-60000) créés par Anaconda → ils sont sudoers.
|
|
install -d -m 750 /etc/sudoers.d
|
|
printf '%%wheel ALL=(ALL:ALL) ALL\n' > /etc/sudoers.d/10-fws-wheel
|
|
chmod 440 /etc/sudoers.d/10-fws-wheel
|
|
while IFS=: read -r _u _x _uid _rest; do
|
|
if [ "$_uid" -ge 1000 ] && [ "$_uid" -le 60000 ]; then
|
|
usermod -aG wheel "$_u" 2>/dev/null || true
|
|
fi
|
|
done < /etc/passwd
|
|
|
|
# --- 4ter) Branding FWS sur le système installé -------------------------------
|
|
# Le hook os-release du build n'est PAS sur la cible et « pacman -S » a pu
|
|
# remettre l'os-release d'Arch → d'où « Arch Linux » au menu GRUB, le logo Arch
|
|
# sur l'écran de connexion (GDM lit os-release LOGO) et le nom « Arch ». On FORCE
|
|
# donc l'os-release FWS (+ lsb-release + GRUB_DISTRIBUTOR), on RÉGÉNÈRE le menu
|
|
# GRUB (10_linux lit le NAME d'os-release), et on retire le motd « live ».
|
|
if [ -f /usr/local/share/fws/os-release ]; then
|
|
cp -f /usr/local/share/fws/os-release /usr/lib/os-release
|
|
ln -sf ../usr/lib/os-release /etc/os-release
|
|
fi
|
|
if [ -f /etc/lsb-release ]; then
|
|
sed -i 's/^DISTRIB_ID=.*/DISTRIB_ID=FWS/; s/^DISTRIB_DESCRIPTION=.*/DISTRIB_DESCRIPTION="FWS Linux"/' \
|
|
/etc/lsb-release
|
|
fi
|
|
if grep -q '^GRUB_DISTRIBUTOR=' /etc/default/grub 2>/dev/null; then
|
|
sed -i 's/^GRUB_DISTRIBUTOR=.*/GRUB_DISTRIBUTOR="FWS"/' /etc/default/grub
|
|
else
|
|
echo 'GRUB_DISTRIBUTOR="FWS"' >> /etc/default/grub
|
|
fi
|
|
grub-mkconfig -o /boot/grub/grub.cfg 2>/dev/null || true
|
|
# motd « live » (texte inadapté + codes ANSI bruts affichés crus par GDM).
|
|
rm -f /etc/motd
|
|
|
|
# --- 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) DNS du système installé : NetworkManager + systemd-resolved ----------
|
|
# Le live utilise systemd-resolved (/etc/resolv.conf → stub 127.0.0.53). L'ANCIEN
|
|
# « rm /etc/resolv.conf » comptait sur NM pour recréer le fichier — MAIS avec
|
|
# systemd-resolved actif, NM ne réécrit PAS resolv.conf (il pousse les DNS vers
|
|
# resolved). Sans le lien, la résolution est MORTE → « Limited Connectivity » /
|
|
# Firefox « Server Not Found » (le réseau marche, le DNS non). Fix robuste :
|
|
# - resolv.conf → stub systemd-resolved,
|
|
# - service systemd-resolved activé,
|
|
# - on FORCE NM à utiliser resolved (dns=systemd-resolved) → il lui fournit les
|
|
# DNS DHCP, la résolution marche dès le 1er boot.
|
|
rm -f /tmp/fws-desktop 2>/dev/null || true
|
|
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
|
|
systemctl enable systemd-resolved.service 2>/dev/null || true
|
|
install -d /etc/NetworkManager/conf.d
|
|
printf '[main]\ndns=systemd-resolved\n' > /etc/NetworkManager/conf.d/dns.conf
|
|
%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
|