From a09d509da8e7da03664198ef6c2ba7dad854f900 Mon Sep 17 00:00:00 2001 From: The_miro Date: Fri, 26 Jun 2026 14:25:06 +0200 Subject: [PATCH] fix(installer): address remaining sanity-check issues (LUKS2, lvm2, FIDO2, plymouth) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - arch-autoinstall.sh: use --type luks2 so systemd-cryptenroll can enroll FIDO2 - arch-autoinstall.sh: drop spurious lvm2 initramfs hook (no LVM in use) - arch-autoinstall.sh: mkinitcpio -P (all presets) instead of -p - arch-autoinstall.sh: add rd.luks.options=fido2-device=auto to GRUB cmdline - arch-autoinstall.sh: move pamu2fcfg outside chroot (host udev owns /dev/hidraw*) - generate-answerfile.sh: remove plymouth from core components checklist - tui-install.sh: component dialog list-height 5→4 (plymouth was removed) - tui-install.sh: correct stale comment about word-boundary glob matching Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01MibNTaLZrLnqyAzVCQe1YA --- setup/arch-autoinstall.sh | 51 ++++++++++++++++++++++++------------ setup/generate-answerfile.sh | 3 +-- setup/tui-install.sh | 8 +++--- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/setup/arch-autoinstall.sh b/setup/arch-autoinstall.sh index fdc7c21..fe342f5 100755 --- a/setup/arch-autoinstall.sh +++ b/setup/arch-autoinstall.sh @@ -328,9 +328,9 @@ LUKS_BACKUP_KEY="" # path to key file, set only when encryption is active if [[ "$ENCRYPT_DISK" == "YES" ]]; then echo "Encrypting root partition..." - # -v (verbose) shows progress; luksFormat initialises a LUKS1 container by default - # and prompts for the primary passphrase interactively. - cryptsetup -v luksFormat "$ROOT_PART" + # --type luks2 is required for systemd-cryptenroll (FIDO2 token enrollment). + # -v (verbose) shows progress; prompts for the primary passphrase interactively. + cryptsetup -v luksFormat "$ROOT_PART" --type luks2 # Open the container and expose it as /dev/mapper/cryptroot for formatting. cryptsetup open "$ROOT_PART" cryptroot @@ -508,15 +508,15 @@ echo "%wheel ALL=(ALL:ALL) ALL" >> /etc/sudoers # 2. Password-only LUKS: uses classic `encrypt` hook (no systemd dependency). # 3. Unencrypted: minimal hook set — no encrypt hook needed. if [[ "$ENCRYPT_DISK" == "YES" && "$FIDO_ROOT" == "YES" ]]; then - sed -i 's/^HOOKS=.*/HOOKS=(base udev systemd autodetect microcode modconf kms consolefont block sd-encrypt lvm2 btrfs filesystems keyboard keymap fsck)/' /etc/mkinitcpio.conf + sed -i 's/^HOOKS=.*/HOOKS=(base udev systemd autodetect microcode modconf kms consolefont block sd-encrypt btrfs filesystems keyboard keymap fsck)/' /etc/mkinitcpio.conf elif [[ "$ENCRYPT_DISK" == "YES" ]]; then - sed -i 's/^HOOKS=.*/HOOKS=(base udev autodetect microcode modconf kms consolefont block encrypt lvm2 btrfs filesystems keyboard keymap fsck)/' /etc/mkinitcpio.conf + sed -i 's/^HOOKS=.*/HOOKS=(base udev autodetect microcode modconf kms consolefont block encrypt btrfs filesystems keyboard keymap fsck)/' /etc/mkinitcpio.conf else sed -i 's/^HOOKS=.*/HOOKS=(base udev autodetect microcode modconf kms consolefont block btrfs filesystems keyboard fsck)/' /etc/mkinitcpio.conf fi -# Regenerate the initramfs for the selected kernel preset. -mkinitcpio -p "$KERNEL" +# -P regenerates all installed kernel presets (more thorough than -p ). +mkinitcpio -P ################################################### # GRUB CONFIG @@ -526,8 +526,8 @@ UUID=$(blkid -s UUID -o value "$ROOT_PART") if [[ "$ENCRYPT_DISK" == "YES" ]]; then if [[ "$FIDO_ROOT" == "YES" ]]; then # systemd-cryptsetup syntax: rd.luks.name==. - # The FIDO2 device is auto-detected by systemd-cryptenroll at boot. - KERNEL_CMD="rd.luks.name=${UUID}=cryptroot root=/dev/mapper/cryptroot" + # rd.luks.options=fido2-device=auto tells sd-encrypt to probe for the FIDO2 token. + KERNEL_CMD="rd.luks.name=${UUID}=cryptroot rd.luks.options=fido2-device=auto root=/dev/mapper/cryptroot" else # Classic initramfs encrypt hook syntax: cryptdevice=UUID=:. KERNEL_CMD="cryptdevice=UUID=${UUID}:cryptroot root=/dev/mapper/cryptroot" @@ -547,21 +547,38 @@ grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=M-Archy-G grub-mkconfig -o /boot/grub/grub.cfg ################################################### -# USER FIDO2 LOGIN +# USER FIDO2 LOGIN (directory + PAM only) ################################################### +# Key enrollment runs outside the chroot — pamu2fcfg cannot reach /dev/hidraw* +# from inside because the host's udev owns those device nodes. if [[ "$FIDO_USER" == "YES" ]]; then mkdir -p "/home/$USERNAME/.config/Yubico" - echo "Insert FIDO2 key for user login and touch when prompted..." - # pamu2fcfg registers the FIDO2 key and writes the credential to u2f_keys. - # Running under sudo -u ensures the file is generated with the correct UID context. - sudo -u "$USERNAME" pamu2fcfg -u "$USERNAME" > "/home/$USERNAME/.config/Yubico/u2f_keys" - chown "$USERNAME":"$USERNAME" "/home/$USERNAME/.config/Yubico/u2f_keys" - # Append the PAM rule so pam_u2f is required for system-local-login sessions. - echo "auth required pam_u2f.so" >> /etc/pam.d/system-local-login + chown "$USERNAME:$USERNAME" "/home/$USERNAME/.config/Yubico" + # `cue` prints a prompt so the user knows to touch the key when challenged. + echo "auth required pam_u2f.so cue" >> /etc/pam.d/system-local-login fi CHROOT_EOF +############################################ +# USER FIDO2 ENROLLMENT (outside chroot) +############################################ +# pamu2fcfg must run outside arch-chroot: the host's udev manages /dev/hidraw* +# and the new user has no access to those nodes from inside the chroot. +if [[ "$FIDO_USER" == "YES" ]]; then + echo "Enrolling FIDO2 key for user login (outside chroot)..." + U2F_KEYFILE="/mnt/home/${USERNAME}/.config/Yubico/u2f_keys" + mkdir -p "/mnt/home/${USERNAME}/.config/Yubico" + # Scope the credential to this hostname so it cannot be replayed on another system. + pamu2fcfg -u "$USERNAME" -o "pam://$HOSTNAME" -i "pam://$HOSTNAME" > "$U2F_KEYFILE" + # Query numeric UID/GID from inside the chroot so ownership is correct. + _NEWUID=$(arch-chroot /mnt id -u "$USERNAME" 2>/dev/null || echo "1000") + _NEWGID=$(arch-chroot /mnt id -g "$USERNAME" 2>/dev/null || echo "1000") + chown -R "$_NEWUID:$_NEWGID" "/mnt/home/${USERNAME}/.config/Yubico" + chmod 600 "$U2F_KEYFILE" + echo "FIDO2 key enrolled for $USERNAME." +fi + ############################################ # DOTFILES TUI SETUP (in-chroot, optional) ############################################ diff --git a/setup/generate-answerfile.sh b/setup/generate-answerfile.sh index 2bf878b..96315e8 100644 --- a/setup/generate-answerfile.sh +++ b/setup/generate-answerfile.sh @@ -191,12 +191,11 @@ if [[ "$AF_RUN_TUI" == "true" ]]; then # ── Components ──────────────────────────────────────────────────────────── AF_COMPONENTS=$(dialog --backtitle "$BACKTITLE" \ --title " Select Components " \ - --checklist "Space toggles · Enter confirms · Esc quits" 16 68 5 \ + --checklist "Space toggles · Enter confirms · Esc quits" 16 68 4 \ "pkg" "Package managers yay · nvm · rust" on \ "core" "Core packages 100+ base system packages" on \ "svc" "Core services NetworkManager · cronie · fail2ban" on \ "shell" "Shell setup zsh · nvim · yazi · micro · starship" on \ - "plymouth" "Plymouth boot splash — skull logo + spinner" on \ 3>&1 1>&2 2>&3) || AF_COMPONENTS="" # ── DE ──────────────────────────────────────────────────────────────────── diff --git a/setup/tui-install.sh b/setup/tui-install.sh index 767dbc9..bf1dc61 100755 --- a/setup/tui-install.sh +++ b/setup/tui-install.sh @@ -170,9 +170,9 @@ count_steps() { [[ "$c" == *"shell"* ]] && TOTAL=$(( TOTAL + 1 )) # A non-"none" DE selection always installs exactly one DE module. [[ "$de" != "none" ]] && TOTAL=$(( TOTAL + 1 )) - # Optional app modules: one glob check per app, one increment per match. - # Glob syntax *"tag"* matches if the space-separated SELECTED_APPS string - # contains the tag anywhere — works because tags never share substrings. + # Optional app modules: one word-boundary check per app, one increment per match. + # Padding $a with spaces and matching " tag " prevents partial-name false matches + # (e.g. "plymouth" must not match against "plymouth-custom"). # BEGIN GENERATED MODULES: module-counters [[ " $a " == *" ollama "* ]] && TOTAL=$(( TOTAL + 1 )) [[ " $a " == *" llama-cpp "* ]] && TOTAL=$(( TOTAL + 1 )) @@ -414,7 +414,7 @@ else # Esc / Cancel returns exit code 1; the '|| { ...; exit 0; }' treats that as a clean abort. COMPONENTS=$(dialog --backtitle "$BACKTITLE" \ --title " Select Components " \ - --checklist "Space toggles · Enter confirms · Esc quits" 16 68 5 \ + --checklist "Space toggles · Enter confirms · Esc quits" 16 68 4 \ "pkg" "Package managers yay · nvm · rust" on \ "core" "Core packages 100+ base system packages" on \ "svc" "Core services NetworkManager · cronie · fail2ban" on \