summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-01-20 13:48:18 -0600
committerCraig Jennings <c@cjennings.net>2026-01-20 13:48:18 -0600
commitb91beda6f56a0da95db8a41f0123abe82acdfeb4 (patch)
tree1b4f2631347f941b4bbb469ffaa6a93311c3394c
parenta21f2007a11000b578596057048616a50ed0431e (diff)
fix(archsetup): prevent ZFS boot failures and add validation tests
- Skip udev→systemd hook change on ZFS systems (ZFS hook is busybox-based) - Add nvme to MODULES for NVMe systems (ensures devices ready for ZFS import) - Add random.trust_cpu=off to suppress AMD RDSEED warnings - Add has_nvme_drives() detection function New validation tests: - validate_terminus_font: check package installed via pacman - validate_mkinitcpio_hooks: verify ZFS uses udev not systemd - validate_initramfs_consolefont: check font in initramfs - validate_nvme_module: check nvme in MODULES for NVMe systems
-rwxr-xr-xarchsetup30
-rw-r--r--scripts/testing/lib/validation.sh69
2 files changed, 95 insertions, 4 deletions
diff --git a/archsetup b/archsetup
index 275068d..16d7cc9 100755
--- a/archsetup
+++ b/archsetup
@@ -383,6 +383,12 @@ is_encrypted_root() {
return 1
}
+# NVMe Detection
+has_nvme_drives() {
+ # Returns 0 (true) if system has NVMe drives
+ ls /dev/nvme* &>/dev/null
+}
+
# Automatic Login Configuration
configure_autologin() {
local do_autologin=false
@@ -1564,6 +1570,17 @@ supplemental_software() {
boot_ux() {
action="Boot UX" && display "title" "$action"
+ # Add nvme module for early loading on NVMe systems
+ # Ensures NVMe devices are available when ZFS/other hooks try to access them
+ if has_nvme_drives; then
+ action="adding nvme to mkinitcpio MODULES for early loading" && display "task" "$action"
+ if grep -q "^MODULES=()" /etc/mkinitcpio.conf; then
+ sed -i 's/^MODULES=()/MODULES=(nvme)/' /etc/mkinitcpio.conf
+ elif grep -q "^MODULES=(" /etc/mkinitcpio.conf && ! grep -q "nvme" /etc/mkinitcpio.conf; then
+ sed -i '/^MODULES=(/ s/)/ nvme)/' /etc/mkinitcpio.conf
+ fi
+ fi
+
action="removing distro and date/time from initial screen" && display "task" "$action"
(cat /dev/null >/etc/issue) || error "error" "$action" "$?"
@@ -1578,9 +1595,13 @@ boot_ux() {
echo "FONT=ter-132n" >> /etc/vconsole.conf
fi
- action="delegating fsck messages from udev to systemd" && display "task" "$action"
- sed -i '/^HOOKS=/ s/\budev\b/systemd/' /etc/mkinitcpio.conf || error "error" "$action" "$?"
- mkinitcpio -P >> "$logfile" 2>&1 || error "error" "running mkinitcpio -P to silence fsck messages" "$?"
+ # Only switch to systemd hook for non-ZFS systems
+ # ZFS initramfs hook is busybox-based and incompatible with systemd hook
+ if ! is_zfs_root; then
+ action="delegating fsck messages from udev to systemd" && display "task" "$action"
+ sed -i '/^HOOKS=/ s/\budev\b/systemd/' /etc/mkinitcpio.conf || error "error" "$action" "$?"
+ mkinitcpio -P >> "$logfile" 2>&1 || error "error" "running mkinitcpio -P to silence fsck messages" "$?"
+ fi
action="configuring quiet fsck output" && display "task" "$action"
mkdir -p /etc/systemd/system/systemd-fsck-root.service.d
@@ -1613,6 +1634,7 @@ EOF
# GRUB: reset timeouts, adjust log levels, larger menu for HiDPI screens, and show splashscreen
# Note: nvme.noacpi=1 disables NVMe ACPI power management to prevent freezes on some drives.
# Safe to keep on newer drives (minor power cost), remove if battery life is critical.
+ # Note: random.trust_cpu=off disables trusting CPU for RNG (avoids AMD RDSEED warnings).
action="configuring boot menu for silence and bootsplash" && display "task" "$action"
if [ -f /etc/default/grub ]; then
action="resetting timeouts and adjusting log levels on grub boot" && display "task" "$action"
@@ -1621,7 +1643,7 @@ EOF
sed -i 's/.*GRUB_TERMINAL_OUTPUT=console/GRUB_TERMINAL_OUTPUT=gfxterm/' /etc/default/grub
sed -i 's/.*GRUB_GFXMODE=auto/GRUB_GFXMODE=1024x768/' /etc/default/grub
sed -i "s/.*GRUB_RECORDFAIL_TIMEOUT=.*/GRUB_RECORDFAIL_TIMEOUT=2/g" /etc/default/grub
- sed -i "s/.*GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"rw loglevel=2 rd.systemd.show_status=auto rd.udev.log_level=2 nvme.noacpi=1 mem_sleep_default=deep nowatchdog quiet splash\"/g" /etc/default/grub
+ sed -i "s/.*GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"rw loglevel=2 rd.systemd.show_status=auto rd.udev.log_level=2 nvme.noacpi=1 mem_sleep_default=deep nowatchdog random.trust_cpu=off quiet splash\"/g" /etc/default/grub
grub-mkconfig -o /boot/grub/grub.cfg >> "$logfile" 2>&1 || error "error" "generating grub config" "$?"
fi
}
diff --git a/scripts/testing/lib/validation.sh b/scripts/testing/lib/validation.sh
index a2e375c..280f435 100644
--- a/scripts/testing/lib/validation.sh
+++ b/scripts/testing/lib/validation.sh
@@ -294,6 +294,12 @@ run_all_validations() {
validate_boot_config
validate_autologin_config
+ # Boot & Initramfs (critical for ZFS systems)
+ validate_terminus_font
+ validate_mkinitcpio_hooks
+ validate_initramfs_consolefont
+ validate_nvme_module
+
# Archsetup Specific
validate_archsetup_log
validate_state_markers
@@ -764,6 +770,69 @@ validate_boot_config() {
fi
}
+validate_terminus_font() {
+ step "Checking terminus-font installation"
+ if ssh_cmd "pacman -Q terminus-font" &>> "$LOGFILE"; then
+ validation_pass "terminus-font package installed"
+ else
+ validation_fail "terminus-font package not installed"
+ attribute_issue "terminus-font not installed via pacman" "archsetup"
+ fi
+}
+
+validate_mkinitcpio_hooks() {
+ step "Checking mkinitcpio HOOKS configuration"
+ local hooks=$(ssh_cmd "grep '^HOOKS=' /etc/mkinitcpio.conf")
+ local is_zfs=$(ssh_cmd "findmnt -n -o FSTYPE / 2>/dev/null")
+
+ if [ "$is_zfs" = "zfs" ]; then
+ # ZFS system: must use udev, not systemd
+ if echo "$hooks" | grep -q '\budev\b'; then
+ validation_pass "ZFS system uses udev hook (correct)"
+ elif echo "$hooks" | grep -q '\bsystemd\b'; then
+ validation_fail "ZFS system uses systemd hook (will break boot)"
+ attribute_issue "mkinitcpio uses systemd hook on ZFS system" "archsetup"
+ else
+ validation_warn "Could not determine init hook type"
+ fi
+ else
+ # Non-ZFS: systemd hook is fine
+ if echo "$hooks" | grep -q '\bsystemd\b'; then
+ validation_pass "Non-ZFS system uses systemd hook"
+ elif echo "$hooks" | grep -q '\budev\b'; then
+ validation_pass "Non-ZFS system uses udev hook"
+ fi
+ fi
+}
+
+validate_initramfs_consolefont() {
+ step "Checking console font in initramfs"
+ local font_in_initramfs=$(ssh_cmd "lsinitcpio /boot/initramfs-linux*.img 2>/dev/null | grep -c 'consolefont.psf\\|ter-'")
+
+ if [ "${font_in_initramfs:-0}" -gt 0 ]; then
+ validation_pass "Console font included in initramfs"
+ else
+ validation_warn "Console font may not be in initramfs"
+ fi
+}
+
+validate_nvme_module() {
+ step "Checking NVMe module configuration"
+ local has_nvme=$(ssh_cmd "ls /dev/nvme* 2>/dev/null | head -1")
+
+ if [ -n "$has_nvme" ]; then
+ # System has NVMe drives
+ local modules=$(ssh_cmd "grep '^MODULES=' /etc/mkinitcpio.conf")
+ if echo "$modules" | grep -q 'nvme'; then
+ validation_pass "NVMe module in mkinitcpio MODULES"
+ else
+ validation_warn "NVMe system but nvme not in MODULES (may cause slow boot)"
+ fi
+ else
+ info "No NVMe drives detected"
+ fi
+}
+
validate_autologin_config() {
step "Checking autologin configuration"
if ssh_cmd "test -f /etc/systemd/system/getty@tty1.service.d/autologin.conf" &>> "$LOGFILE"; then