diff options
| author | Craig Jennings <c@cjennings.net> | 2026-04-27 13:20:30 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-04-27 13:20:30 -0500 |
| commit | 6dcdf180289823fceda376c67af9d4ea659463a8 (patch) | |
| tree | 28ddf17a13f70c7a05abe9a196888f3f66512a2a | |
| parent | 26f3f823ac17940a1b0153619f6140f45d856e33 (diff) | |
| download | archangel-6dcdf180289823fceda376c67af9d4ea659463a8.tar.gz archangel-6dcdf180289823fceda376c67af9d4ea659463a8.zip | |
refactor: extract MNTPOINT constant for the install chroot mount point
Last on the tech-debt drain. The installer hardcoded /mnt at 50+ sites: pacstrap, arch-chroot, mount/umount, fstab writes, and every host-side write into the chroot's /etc, /usr, /var, /boot, /tmp. Same magic-string smell as /mnt/efi but at much larger scale.
Add MNTPOINT="/mnt" to lib/common.sh next to EFI_DIR. Replace literal /mnt/... with $MNTPOINT/... across installer/archangel, installer/lib/btrfs.sh, and installer/lib/common.sh. Replace bare /mnt (mount target, arch-chroot root, umount target, install_dropin parameter) with $MNTPOINT. EFI_DIR's own definition becomes EFI_DIR="$MNTPOINT/efi" for the natural composition.
Folded in the related ticket: /mnt${chroot_efi_dir} in btrfs.sh:install_grub_all_efi becomes ${MNTPOINT}${chroot_efi_dir}. Was filed as a separate item but the ticket said it should ship with the MNTPOINT extraction, since the composition pattern is unusual and easy to miss in a global sed.
Three /mnt references kept literal in comments where the comment describes the string concept rather than the mount point ("Remove /mnt prefix - config is used inside chroot where root is /", etc.). Substituting to $MNTPOINT in those comments would obscure the documentation.
Bats: 146 → 147. One new test in test_common.bats pins MNTPOINT="/mnt". Lint clean (one shellcheck SC2295 warning fixed by quoting the parameter expansion: ${isp_firmware#"$MNTPOINT"}). VM verification deferred to a single full make test-install run after all three tech-debt commits land.
| -rwxr-xr-x | installer/archangel | 130 | ||||
| -rw-r--r-- | installer/lib/btrfs.sh | 128 | ||||
| -rw-r--r-- | installer/lib/common.sh | 10 | ||||
| -rw-r--r-- | testing-strategy.org | 2 | ||||
| -rw-r--r-- | tests/unit/test_common.bats | 4 |
5 files changed, 143 insertions, 131 deletions
diff --git a/installer/archangel b/installer/archangel index 479b53a..107f03d 100755 --- a/installer/archangel +++ b/installer/archangel @@ -627,7 +627,7 @@ create_zfs_pool() { -O relatime=on \ -O xattr=sa \ -O mountpoint=none \ - -R /mnt \ + -R $MNTPOINT \ "$POOL_NAME" $pool_config else echo "$ZFS_PASSPHRASE" | zpool create -f \ @@ -645,7 +645,7 @@ create_zfs_pool() { -O keyformat=passphrase \ -O keylocation=prompt \ -O mountpoint=none \ - -R /mnt \ + -R $MNTPOINT \ "$POOL_NAME" $pool_config fi @@ -691,12 +691,12 @@ create_datasets() { # /var/tmp - ZFS-backed, persists across reboots, excluded from snapshots zfs create -o mountpoint=/var/tmp -o com.sun:auto-snapshot=false "$POOL_NAME/var/tmp" - chmod 1777 /mnt/var/tmp + chmod 1777 $MNTPOINT/var/tmp # /tmp - tmpfs via fstab (not ZFS: ZFS statx() returns ENOLINK on # systemd PrivateTmp paths, breaking systemd-tmpfiles-clean every boot) - mkdir -p /mnt/tmp - chmod 1777 /mnt/tmp + mkdir -p $MNTPOINT/tmp + chmod 1777 $MNTPOINT/tmp info "Datasets created:" zfs list -r "$POOL_NAME" -o name,mountpoint,compression @@ -741,7 +741,7 @@ EOF || error "Unknown filesystem: $FILESYSTEM" # Use yes to auto-select defaults for provider prompts - yes "" | pacstrap -K /mnt "${packages[@]}" + yes "" | pacstrap -K $MNTPOINT "${packages[@]}" info "Base system installed." } @@ -751,30 +751,30 @@ configure_system() { # fstab (EFI + tmpfs /tmp; /boot is on ZFS root) info "Generating fstab..." - echo "# /efi - EFI System Partition (ZFSBootMenu binary)" > /mnt/etc/fstab - echo "UUID=$(blkid -s UUID -o value "${EFI_PARTS[0]}") /efi vfat defaults,noatime 0 2" >> /mnt/etc/fstab - echo "" >> /mnt/etc/fstab - echo "# /tmp - tmpfs (avoids ZFS statx ENOLINK on systemd PrivateTmp paths)" >> /mnt/etc/fstab - echo "tmpfs /tmp tmpfs defaults,nosuid,nodev,mode=1777 0 0" >> /mnt/etc/fstab + echo "# /efi - EFI System Partition (ZFSBootMenu binary)" > $MNTPOINT/etc/fstab + echo "UUID=$(blkid -s UUID -o value "${EFI_PARTS[0]}") /efi vfat defaults,noatime 0 2" >> $MNTPOINT/etc/fstab + echo "" >> $MNTPOINT/etc/fstab + echo "# /tmp - tmpfs (avoids ZFS statx ENOLINK on systemd PrivateTmp paths)" >> $MNTPOINT/etc/fstab + echo "tmpfs /tmp tmpfs defaults,nosuid,nodev,mode=1777 0 0" >> $MNTPOINT/etc/fstab # Timezone info "Setting timezone to $TIMEZONE..." - arch-chroot /mnt ln -sf "/usr/share/zoneinfo/$TIMEZONE" /etc/localtime - arch-chroot /mnt hwclock --systohc + arch-chroot $MNTPOINT ln -sf "/usr/share/zoneinfo/$TIMEZONE" /etc/localtime + arch-chroot $MNTPOINT hwclock --systohc # Locale info "Configuring locale..." - echo "$LOCALE UTF-8" >> /mnt/etc/locale.gen - arch-chroot /mnt locale-gen - echo "LANG=$LOCALE" > /mnt/etc/locale.conf + echo "$LOCALE UTF-8" >> $MNTPOINT/etc/locale.gen + arch-chroot $MNTPOINT locale-gen + echo "LANG=$LOCALE" > $MNTPOINT/etc/locale.conf # Keymap - echo "KEYMAP=$KEYMAP" > /mnt/etc/vconsole.conf + echo "KEYMAP=$KEYMAP" > $MNTPOINT/etc/vconsole.conf # Hostname info "Setting hostname to $HOSTNAME..." - echo "$HOSTNAME" > /mnt/etc/hostname - cat > /mnt/etc/hosts << EOF + echo "$HOSTNAME" > $MNTPOINT/etc/hostname + cat > $MNTPOINT/etc/hosts << EOF 127.0.0.1 localhost ::1 localhost 127.0.1.1 $HOSTNAME.localdomain $HOSTNAME @@ -782,7 +782,7 @@ EOF # Add archzfs repo (SigLevel=Never — same rationale as install_base) info "Adding archzfs repository..." - cat >> /mnt/etc/pacman.conf << 'EOF' + cat >> $MNTPOINT/etc/pacman.conf << 'EOF' [archzfs] Server = https://github.com/archzfs/archzfs/releases/download/experimental @@ -794,21 +794,21 @@ EOF # get created in tmpfs then hidden when ZFS mounts over it. # Solution: Make journal-flush wait for zfs-mount, and enable persistent storage. info "Configuring journald for ZFS..." - mkdir -p /mnt/etc/systemd/journald.conf.d - cat > /mnt/etc/systemd/journald.conf.d/persistent.conf << 'EOF' + mkdir -p $MNTPOINT/etc/systemd/journald.conf.d + cat > $MNTPOINT/etc/systemd/journald.conf.d/persistent.conf << 'EOF' [Journal] Storage=persistent EOF - mkdir -p /mnt/etc/systemd/system/systemd-journal-flush.service.d - cat > /mnt/etc/systemd/system/systemd-journal-flush.service.d/zfs.conf << 'EOF' + mkdir -p $MNTPOINT/etc/systemd/system/systemd-journal-flush.service.d + cat > $MNTPOINT/etc/systemd/system/systemd-journal-flush.service.d/zfs.conf << 'EOF' [Unit] After=zfs-mount.service EOF # Set root password info "Setting root password..." - echo "root:$ROOT_PASSWORD" | arch-chroot /mnt chpasswd + echo "root:$ROOT_PASSWORD" | arch-chroot $MNTPOINT chpasswd } configure_wifi() { @@ -817,9 +817,9 @@ configure_wifi() { # Copy NetworkManager connection from live environment if [[ -d /etc/NetworkManager/system-connections ]]; then - mkdir -p /mnt/etc/NetworkManager/system-connections - cp /etc/NetworkManager/system-connections/* /mnt/etc/NetworkManager/system-connections/ 2>/dev/null || true - chmod 600 /mnt/etc/NetworkManager/system-connections/* 2>/dev/null || true + mkdir -p $MNTPOINT/etc/NetworkManager/system-connections + cp /etc/NetworkManager/system-connections/* $MNTPOINT/etc/NetworkManager/system-connections/ 2>/dev/null || true + chmod 600 $MNTPOINT/etc/NetworkManager/system-connections/* 2>/dev/null || true fi info "WiFi configuration copied to installed system." @@ -830,10 +830,10 @@ configure_ssh() { if [[ "$ENABLE_SSH" == "yes" ]]; then step "Configuring SSH" - enable_sshd_root_login /mnt/etc/ssh/sshd_config + enable_sshd_root_login $MNTPOINT/etc/ssh/sshd_config # Enable sshd service - arch-chroot /mnt systemctl enable sshd + arch-chroot $MNTPOINT systemctl enable sshd info "SSH enabled with root password login." warn "Harden SSH after install (key auth, fail2ban)." @@ -845,20 +845,20 @@ configure_ssh() { configure_initramfs() { step "Configuring Initramfs for ZFS" - cp /mnt/etc/mkinitcpio.conf /mnt/etc/mkinitcpio.conf.bak + cp $MNTPOINT/etc/mkinitcpio.conf $MNTPOINT/etc/mkinitcpio.conf.bak # CRITICAL: Remove archiso drop-in that overrides mkinitcpio.conf HOOKS # The archiso.conf contains live ISO-specific hooks that are incompatible with ZFS # If not removed, it overrides our HOOKS setting and breaks boot after kernel updates - if [[ -f /mnt/etc/mkinitcpio.conf.d/archiso.conf ]]; then + if [[ -f $MNTPOINT/etc/mkinitcpio.conf.d/archiso.conf ]]; then info "Removing archiso drop-in config..." - rm -f /mnt/etc/mkinitcpio.conf.d/archiso.conf + rm -f $MNTPOINT/etc/mkinitcpio.conf.d/archiso.conf fi # CRITICAL: Fix linux-lts preset file # The preset from archiso uses archiso-specific config that breaks mkinitcpio -P info "Creating proper linux-lts preset..." - cat > /mnt/etc/mkinitcpio.d/linux-lts.preset << 'PRESET_EOF' + cat > $MNTPOINT/etc/mkinitcpio.d/linux-lts.preset << 'PRESET_EOF' # mkinitcpio preset file for linux-lts PRESETS=(default fallback) @@ -876,13 +876,13 @@ PRESET_EOF # The firmware must be in initramfs since amdgpu loads before root is mounted if lspci | grep -qi "amd.*display\|amd.*vga\|radeon"; then local isp_firmware - isp_firmware=$(ls /mnt/usr/lib/firmware/amdgpu/isp_*.bin.zst 2>/dev/null | head -1) + isp_firmware=$(ls $MNTPOINT/usr/lib/firmware/amdgpu/isp_*.bin.zst 2>/dev/null | head -1) if [[ -n "$isp_firmware" ]]; then # Remove /mnt prefix - config is used inside chroot where root is / - local chroot_path="${isp_firmware#/mnt}" + local chroot_path="${isp_firmware#"$MNTPOINT"}" info "AMD APU detected with ISP firmware - adding to initramfs" - mkdir -p /mnt/etc/mkinitcpio.conf.d - cat > /mnt/etc/mkinitcpio.conf.d/amd-isp.conf << EOF + mkdir -p $MNTPOINT/etc/mkinitcpio.conf.d + cat > $MNTPOINT/etc/mkinitcpio.conf.d/amd-isp.conf << EOF # AMD ISP (Image Signal Processor) firmware for camera support # Loaded early so amdgpu can initialize ISP before root is mounted FILES+=($chroot_path) @@ -899,11 +899,11 @@ EOF # No sed verification needed: a missing HOOKS= line makes mkinitcpio -P # fail loudly downstream, so silent-replace failure can't reach a booted # system. (Audited 2026-04-27 against silent-sed pattern.) - sed -i 's/^HOOKS=.*/HOOKS=(base udev microcode modconf kms keyboard keymap consolefont block zfs filesystems)/' /mnt/etc/mkinitcpio.conf + sed -i 's/^HOOKS=.*/HOOKS=(base udev microcode modconf kms keyboard keymap consolefont block zfs filesystems)/' $MNTPOINT/etc/mkinitcpio.conf # Get the installed kernel version (not the running kernel) local kernel_ver - kernel_ver=$(ls /mnt/usr/lib/modules | grep lts | head -1) + kernel_ver=$(ls $MNTPOINT/usr/lib/modules | grep lts | head -1) if [[ -z "$kernel_ver" ]]; then error "Could not find LTS kernel modules" fi @@ -912,16 +912,16 @@ EOF # Ensure kernel module dependencies are up to date after DKMS build # Must specify kernel version since running kernel differs from installed kernel info "Updating module dependencies..." - arch-chroot /mnt depmod "$kernel_ver" + arch-chroot $MNTPOINT depmod "$kernel_ver" # Verify ZFS module exists - if ! [[ -f "/mnt/usr/lib/modules/$kernel_ver/updates/dkms/zfs.ko.zst" ]]; then + if ! [[ -f "$MNTPOINT/usr/lib/modules/$kernel_ver/updates/dkms/zfs.ko.zst" ]]; then error "ZFS module not found! DKMS build may have failed." fi info "ZFS module verified for kernel $kernel_ver" info "Regenerating initramfs..." - arch-chroot /mnt mkinitcpio -P + arch-chroot $MNTPOINT mkinitcpio -P } configure_zfsbootmenu() { @@ -939,7 +939,7 @@ configure_zfsbootmenu() { host_id=$(hostid) # Copy hostid to installed system (ZFS uses this for pool ownership) - cp /etc/hostid /mnt/etc/hostid + cp /etc/hostid $MNTPOINT/etc/hostid # Create ZFSBootMenu directory on EFI mkdir -p $EFI_DIR/EFI/ZBM @@ -1021,17 +1021,17 @@ configure_zfsbootmenu() { configure_zfs_services() { step "Configuring ZFS Services" - arch-chroot /mnt systemctl enable zfs.target + arch-chroot $MNTPOINT systemctl enable zfs.target # Use zfs-import-scan instead of zfs-import-cache # This is the recommended method - it uses blkid to scan for pools # and doesn't require a cachefile # Note: ZFS package preset enables zfs-import-cache by default, so we must # explicitly disable it before enabling zfs-import-scan - arch-chroot /mnt systemctl disable zfs-import-cache.service - arch-chroot /mnt systemctl enable zfs-import-scan.service - arch-chroot /mnt systemctl enable zfs-mount.service - arch-chroot /mnt systemctl enable zfs-import.target + arch-chroot $MNTPOINT systemctl disable zfs-import-cache.service + arch-chroot $MNTPOINT systemctl enable zfs-import-scan.service + arch-chroot $MNTPOINT systemctl enable zfs-mount.service + arch-chroot $MNTPOINT systemctl enable zfs-import.target # Note: hostid and bootfs are already set by configure_zfsbootmenu() @@ -1039,12 +1039,12 @@ configure_zfs_services() { # Also remove any existing cachefile since zfs-import-scan has a condition # that prevents it from running if /etc/zfs/zpool.cache exists zpool set cachefile=none "$POOL_NAME" - rm -f /mnt/etc/zfs/zpool.cache + rm -f $MNTPOINT/etc/zfs/zpool.cache # Enable other services - arch-chroot /mnt systemctl enable NetworkManager - arch-chroot /mnt systemctl enable avahi-daemon - arch-chroot /mnt systemctl enable sshd + arch-chroot $MNTPOINT systemctl enable NetworkManager + arch-chroot $MNTPOINT systemctl enable avahi-daemon + arch-chroot $MNTPOINT systemctl enable sshd info "ZFS services configured." } @@ -1052,9 +1052,9 @@ configure_zfs_services() { configure_pacman_hook() { step "Configuring Pacman Snapshot Hook" - mkdir -p /mnt/etc/pacman.d/hooks + mkdir -p $MNTPOINT/etc/pacman.d/hooks - cat > /mnt/etc/pacman.d/hooks/zfs-snapshot.hook << EOF + cat > $MNTPOINT/etc/pacman.d/hooks/zfs-snapshot.hook << EOF [Trigger] Operation = Upgrade Operation = Install @@ -1068,7 +1068,7 @@ When = PreTransaction Exec = /usr/local/bin/zfs-pre-snapshot EOF - cat > /mnt/usr/local/bin/zfs-pre-snapshot << 'EOF' + cat > $MNTPOINT/usr/local/bin/zfs-pre-snapshot << 'EOF' #!/bin/bash POOL="zroot" DATASET="$POOL/ROOT/default" @@ -1096,7 +1096,7 @@ else fi EOF - chmod +x /mnt/usr/local/bin/zfs-pre-snapshot + chmod +x $MNTPOINT/usr/local/bin/zfs-pre-snapshot info "Pacman hook configured." } @@ -1105,10 +1105,10 @@ configure_zfs_tools() { step "Installing ZFS Management Tools" # Copy ZFS management scripts - cp /usr/local/bin/zfssnapshot /mnt/usr/local/bin/zfssnapshot - cp /usr/local/bin/zfsrollback /mnt/usr/local/bin/zfsrollback - chmod +x /mnt/usr/local/bin/zfssnapshot - chmod +x /mnt/usr/local/bin/zfsrollback + cp /usr/local/bin/zfssnapshot $MNTPOINT/usr/local/bin/zfssnapshot + cp /usr/local/bin/zfsrollback $MNTPOINT/usr/local/bin/zfsrollback + chmod +x $MNTPOINT/usr/local/bin/zfssnapshot + chmod +x $MNTPOINT/usr/local/bin/zfsrollback info "ZFS management scripts installed: zfssnapshot, zfsrollback" info "Tip: Install sanoid for automated snapshot retention." @@ -1122,7 +1122,7 @@ configure_tmpfiles_private_tmp() { local svc for svc in systemd-tmpfiles-setup systemd-tmpfiles-clean; do - install_dropin "$svc" zfs-private-tmp /mnt << 'EOF' + install_dropin "$svc" zfs-private-tmp $MNTPOINT << 'EOF' # ZFS: statx of sibling services' /var/tmp/systemd-private-*/tmp mounts # returns errno 132. Running in own namespace avoids traversing them. [Service] @@ -1174,7 +1174,7 @@ create_genesis_snapshot() { # Create rollback script in /root info "Installing rollback-to-genesis script..." - cat > /mnt/root/rollback-to-genesis << 'ROLLBACK_EOF' + cat > $MNTPOINT/root/rollback-to-genesis << 'ROLLBACK_EOF' #!/bin/bash # rollback-to-genesis - Roll back all datasets to the genesis snapshot # @@ -1223,7 +1223,7 @@ echo "Rollback complete!" echo "Reboot to complete the process: reboot" ROLLBACK_EOF - chmod +x /mnt/root/rollback-to-genesis + chmod +x $MNTPOINT/root/rollback-to-genesis info "Genesis snapshot created. Rollback script: /root/rollback-to-genesis" } @@ -1264,7 +1264,7 @@ install_failure_cleanup() { case "$FILESYSTEM" in zfs) umount $EFI_DIR 2>/dev/null || true - umount -R /mnt 2>/dev/null || true + umount -R $MNTPOINT 2>/dev/null || true if zpool list "$POOL_NAME" >/dev/null 2>&1; then zpool export "$POOL_NAME" 2>/dev/null \ || zpool export -f "$POOL_NAME" 2>/dev/null \ diff --git a/installer/lib/btrfs.sh b/installer/lib/btrfs.sh index f704fd7..3704c65 100644 --- a/installer/lib/btrfs.sh +++ b/installer/lib/btrfs.sh @@ -87,14 +87,14 @@ setup_luks_testing_keyfile() { warn "This reduces security - for testing only!" # Generate random keyfile - dd if=/dev/urandom of="/mnt${LUKS_KEYFILE}" bs=512 count=4 status=none \ + dd if=/dev/urandom of="$MNTPOINT${LUKS_KEYFILE}" bs=512 count=4 status=none \ || error "Failed to generate keyfile" - chmod 000 "/mnt${LUKS_KEYFILE}" + chmod 000 "$MNTPOINT${LUKS_KEYFILE}" # Add keyfile to each LUKS partition (slot 1, passphrase stays in slot 0) for partition in "${partitions[@]}"; do info "Adding keyfile to $partition..." - echo -n "$passphrase" | cryptsetup luksAddKey "$partition" "/mnt${LUKS_KEYFILE}" -d - \ + echo -n "$passphrase" | cryptsetup luksAddKey "$partition" "$MNTPOINT${LUKS_KEYFILE}" -d - \ || error "Failed to add keyfile to $partition" done @@ -172,7 +172,7 @@ configure_crypttab() { step "Configuring crypttab" - echo "# LUKS encrypted root partitions" > /mnt/etc/crypttab + echo "# LUKS encrypted root partitions" > $MNTPOINT/etc/crypttab # Use keyfile if in testing mode, otherwise prompt for passphrase local key_source="none" @@ -188,7 +188,7 @@ configure_crypttab() { local name="${LUKS_MAPPER_NAME}${i}" [[ $i -eq 0 ]] && name="$LUKS_MAPPER_NAME" - echo "$name UUID=$uuid $key_source luks,discard" >> /mnt/etc/crypttab + echo "$name UUID=$uuid $key_source luks,discard" >> $MNTPOINT/etc/crypttab info "crypttab: $name -> UUID=$uuid" ((++i)) done @@ -200,29 +200,29 @@ configure_luks_initramfs() { step "Configuring Initramfs for LUKS" # Backup original - cp /mnt/etc/mkinitcpio.conf /mnt/etc/mkinitcpio.conf.bak + cp $MNTPOINT/etc/mkinitcpio.conf $MNTPOINT/etc/mkinitcpio.conf.bak # Add encrypt hook before filesystems (configure_btrfs_initramfs overwrites # this with the final hook list, using sd-encrypt for multi-disk setups) # No sed verification needed: a missing HOOKS= line makes mkinitcpio -P # fail loudly downstream. (Audited 2026-04-27 against silent-sed pattern.) sed -i 's/^HOOKS=.*/HOOKS=(base udev microcode modconf kms keyboard keymap consolefont block encrypt filesystems fsck)/' \ - /mnt/etc/mkinitcpio.conf + $MNTPOINT/etc/mkinitcpio.conf # Include keyfile in initramfs for testing mode (unattended boot) if [[ "${TESTING:-}" == "yes" ]]; then info "Testing mode: embedding keyfile in initramfs" - sed -i "s|^FILES=.*|FILES=($LUKS_KEYFILE)|" /mnt/etc/mkinitcpio.conf + sed -i "s|^FILES=.*|FILES=($LUKS_KEYFILE)|" $MNTPOINT/etc/mkinitcpio.conf # If FILES line doesn't exist, add it - if ! grep -q "^FILES=" /mnt/etc/mkinitcpio.conf; then - echo "FILES=($LUKS_KEYFILE)" >> /mnt/etc/mkinitcpio.conf + if ! grep -q "^FILES=" $MNTPOINT/etc/mkinitcpio.conf; then + echo "FILES=($LUKS_KEYFILE)" >> $MNTPOINT/etc/mkinitcpio.conf fi fi # Create crypttab.initramfs for sd-encrypt (used by multi-disk LUKS) # sd-encrypt reads this file to open all LUKS devices during initramfs - if [[ -f /mnt/etc/crypttab ]]; then - cp /mnt/etc/crypttab /mnt/etc/crypttab.initramfs + if [[ -f $MNTPOINT/etc/crypttab ]]; then + cp $MNTPOINT/etc/crypttab $MNTPOINT/etc/crypttab.initramfs info "Created crypttab.initramfs for sd-encrypt." fi @@ -238,7 +238,7 @@ configure_luks_grub() { uuid=$(blkid -s UUID -o value "$partition") # Enable GRUB cryptodisk support (required for encrypted /boot) - echo "GRUB_ENABLE_CRYPTODISK=y" >> /mnt/etc/default/grub + echo "GRUB_ENABLE_CRYPTODISK=y" >> $MNTPOINT/etc/default/grub # Add cryptdevice to GRUB cmdline # For testing mode, also add cryptkey parameter for automated unlock @@ -251,7 +251,7 @@ configure_luks_grub() { prepend_grub_cmdline_linux \ "cryptdevice=UUID=$uuid:$LUKS_MAPPER_NAME:allow-discards ${cryptkey_param}" \ - /mnt/etc/default/grub + $MNTPOINT/etc/default/grub info "GRUB configured with cryptdevice parameter and cryptodisk enabled." } @@ -352,17 +352,17 @@ create_btrfs_subvolumes() { step "Creating Btrfs Subvolumes" # Mount the raw btrfs volume temporarily - mount "$partition" /mnt || error "Failed to mount btrfs volume" + mount "$partition" $MNTPOINT || error "Failed to mount btrfs volume" # Create each subvolume for subvol_spec in "${BTRFS_SUBVOLS[@]}"; do IFS=':' read -r name mountpoint extra <<< "$subvol_spec" info "Creating subvolume: $name -> $mountpoint" - btrfs subvolume create "/mnt/$name" || error "Failed to create subvolume $name" + btrfs subvolume create "$MNTPOINT/$name" || error "Failed to create subvolume $name" done # Unmount raw volume - umount /mnt + umount $MNTPOINT info "Created ${#BTRFS_SUBVOLS[@]} subvolumes." } @@ -377,8 +377,8 @@ mount_btrfs_subvolumes() { step "Mounting Btrfs Subvolumes" # Mount root subvolume first - info "Mounting @ -> /mnt" - mount -o "subvol=@,$BTRFS_OPTS" "$partition" /mnt || error "Failed to mount root subvolume" + info "Mounting @ -> $MNTPOINT" + mount -o "subvol=@,$BTRFS_OPTS" "$partition" $MNTPOINT || error "Failed to mount root subvolume" # Create mount points and mount remaining subvolumes for subvol_spec in "${BTRFS_SUBVOLS[@]}"; do @@ -407,13 +407,13 @@ mount_btrfs_subvolumes() { fi fi - info "Mounting $name -> /mnt$mountpoint" - mkdir -p "/mnt$mountpoint" - mount -o "$opts" "$partition" "/mnt$mountpoint" || error "Failed to mount $name" + info "Mounting $name -> $MNTPOINT$mountpoint" + mkdir -p "$MNTPOINT$mountpoint" + mount -o "$opts" "$partition" "$MNTPOINT$mountpoint" || error "Failed to mount $name" done # Set permissions on tmp directories - chmod 1777 /mnt/tmp /mnt/var/tmp + chmod 1777 $MNTPOINT/tmp $MNTPOINT/var/tmp info "All subvolumes mounted." } @@ -432,7 +432,7 @@ generate_btrfs_fstab() { uuid=$(blkid -s UUID -o value "$partition") # Start with header - cat > /mnt/etc/fstab << EOF + cat > $MNTPOINT/etc/fstab << EOF # /etc/fstab - Btrfs subvolume mounts # IMPORTANT: Using subvol= NOT subvolid= for snapshot compatibility # Generated by archangel installer @@ -460,15 +460,15 @@ EOF fi fi - echo "UUID=$uuid $mountpoint btrfs $opts 0 0" >> /mnt/etc/fstab + echo "UUID=$uuid $mountpoint btrfs $opts 0 0" >> $MNTPOINT/etc/fstab done # Add EFI partition local efi_uuid efi_uuid=$(blkid -s UUID -o value "$efi_partition") - echo "" >> /mnt/etc/fstab - echo "# EFI System Partition" >> /mnt/etc/fstab - echo "UUID=$efi_uuid /efi vfat defaults,noatime 0 2" >> /mnt/etc/fstab + echo "" >> $MNTPOINT/etc/fstab + echo "# EFI System Partition" >> $MNTPOINT/etc/fstab + echo "UUID=$efi_uuid /efi vfat defaults,noatime 0 2" >> $MNTPOINT/etc/fstab info "fstab generated with ${#BTRFS_SUBVOLS[@]} btrfs mounts + EFI" } @@ -528,8 +528,8 @@ configure_snapper() { echo 'grub-mkconfig -o /efi/grub/grub.cfg' echo '' echo 'echo "Snapper configuration complete!"' - } > /mnt/usr/local/bin/snapper-firstboot - chmod +x /mnt/usr/local/bin/snapper-firstboot + } > $MNTPOINT/usr/local/bin/snapper-firstboot + chmod +x $MNTPOINT/usr/local/bin/snapper-firstboot # Create systemd service for firstboot { @@ -547,14 +547,14 @@ configure_snapper() { echo '' echo '[Install]' echo 'WantedBy=multi-user.target' - } > /mnt/etc/systemd/system/snapper-firstboot.service + } > $MNTPOINT/etc/systemd/system/snapper-firstboot.service # Enable the firstboot service - arch-chroot /mnt systemctl enable snapper-firstboot.service + arch-chroot $MNTPOINT systemctl enable snapper-firstboot.service # Enable snapper timers - arch-chroot /mnt systemctl enable snapper-timeline.timer - arch-chroot /mnt systemctl enable snapper-cleanup.timer + arch-chroot $MNTPOINT systemctl enable snapper-timeline.timer + arch-chroot $MNTPOINT systemctl enable snapper-cleanup.timer info "Snapper firstboot service configured." info "Snapper will be fully configured on first boot." @@ -575,7 +575,7 @@ configure_grub() { # Configure GRUB defaults for btrfs info "Setting GRUB configuration..." - cat > /mnt/etc/default/grub << 'EOF' + cat > $MNTPOINT/etc/default/grub << 'EOF' # GRUB configuration for btrfs root with snapshots GRUB_DEFAULT=0 GRUB_TIMEOUT=5 @@ -596,9 +596,9 @@ EOF # Add LUKS encryption settings if enabled if [[ "$NO_ENCRYPT" != "yes" && -n "$LUKS_PASSPHRASE" ]]; then - echo "" >> /mnt/etc/default/grub - echo "# LUKS encryption support" >> /mnt/etc/default/grub - echo "GRUB_ENABLE_CRYPTODISK=y" >> /mnt/etc/default/grub + echo "" >> $MNTPOINT/etc/default/grub + echo "# LUKS encryption support" >> $MNTPOINT/etc/default/grub + echo "GRUB_ENABLE_CRYPTODISK=y" >> $MNTPOINT/etc/default/grub # For multi-disk LUKS, sd-encrypt reads crypttab.initramfs — no cmdline params needed # For single-disk LUKS, the encrypt hook needs cryptdevice= on the cmdline @@ -618,7 +618,7 @@ EOF fi prepend_grub_cmdline_linux \ "cryptdevice=UUID=$uuid:$LUKS_MAPPER_NAME:allow-discards ${cryptkey_param}" \ - /mnt/etc/default/grub + $MNTPOINT/etc/default/grub info "Added cryptdevice parameter for LUKS partition." fi else @@ -632,17 +632,17 @@ EOF # Install GRUB with boot-directory on EFI partition info "Installing GRUB to EFI partition..." - arch-chroot /mnt grub-install --target=x86_64-efi --efi-directory=/efi \ + arch-chroot $MNTPOINT grub-install --target=x86_64-efi --efi-directory=/efi \ --bootloader-id=GRUB --boot-directory=/efi \ || error "GRUB installation failed" # Create symlink BEFORE grub-mkconfig (grub-btrfs expects /boot/grub) - rm -rf /mnt/boot/grub 2>/dev/null || true - arch-chroot /mnt ln -sfn /efi/grub /boot/grub + rm -rf $MNTPOINT/boot/grub 2>/dev/null || true + arch-chroot $MNTPOINT ln -sfn /efi/grub /boot/grub # Generate GRUB config (uses /boot/grub symlink -> /efi/grub) info "Generating GRUB configuration..." - arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg \ + arch-chroot $MNTPOINT grub-mkconfig -o /boot/grub/grub.cfg \ || error "Failed to generate GRUB config" # Sync to ensure grub.cfg is written to FAT32 EFI partition @@ -650,7 +650,7 @@ EOF # Enable grub-btrfsd for automatic snapshot menu updates info "Enabling grub-btrfs daemon..." - arch-chroot /mnt systemctl enable grub-btrfsd + arch-chroot $MNTPOINT systemctl enable grub-btrfsd info "GRUB configured with btrfs snapshot support." } @@ -682,13 +682,13 @@ install_grub_all_efi() { mkdir -p "$mount_point" mount "$efi_part" "$mount_point" || { warn "Failed to mount $efi_part"; ((++i)); continue; } # Also create the directory in chroot for grub-install - mkdir -p "/mnt${chroot_efi_dir}" - mount --bind "$mount_point" "/mnt${chroot_efi_dir}" + mkdir -p "${MNTPOINT}${chroot_efi_dir}" + mount --bind "$mount_point" "${MNTPOINT}${chroot_efi_dir}" fi fi info "Installing GRUB to $efi_part ($bootloader_id)..." - arch-chroot /mnt grub-install --target=x86_64-efi \ + arch-chroot $MNTPOINT grub-install --target=x86_64-efi \ --efi-directory="$chroot_efi_dir" \ --bootloader-id="$bootloader_id" \ --boot-directory=/efi \ @@ -750,12 +750,12 @@ sync_grub() { sync_grub ' - echo "$script_content" > /mnt/usr/local/bin/grub-sync-efi - chmod +x /mnt/usr/local/bin/grub-sync-efi + echo "$script_content" > $MNTPOINT/usr/local/bin/grub-sync-efi + chmod +x $MNTPOINT/usr/local/bin/grub-sync-efi # Create pacman hook - mkdir -p /mnt/etc/pacman.d/hooks - cat > /mnt/etc/pacman.d/hooks/99-grub-sync-efi.hook << 'HOOKEOF' + mkdir -p $MNTPOINT/etc/pacman.d/hooks + cat > $MNTPOINT/etc/pacman.d/hooks/99-grub-sync-efi.hook << 'HOOKEOF' [Trigger] Type = Package Operation = Upgrade @@ -805,8 +805,8 @@ configure_btrfs_services() { step "Configuring System Services" # Enable standard services - arch-chroot /mnt systemctl enable NetworkManager - arch-chroot /mnt systemctl enable avahi-daemon + arch-chroot $MNTPOINT systemctl enable NetworkManager + arch-chroot $MNTPOINT systemctl enable avahi-daemon # Snapper timers (already enabled in configure_snapper) @@ -823,17 +823,17 @@ configure_btrfs_initramfs() { step "Configuring Initramfs for Btrfs" # Backup original - cp /mnt/etc/mkinitcpio.conf /mnt/etc/mkinitcpio.conf.bak + cp $MNTPOINT/etc/mkinitcpio.conf $MNTPOINT/etc/mkinitcpio.conf.bak # Remove archiso drop-in if present - if [[ -f /mnt/etc/mkinitcpio.conf.d/archiso.conf ]]; then + if [[ -f $MNTPOINT/etc/mkinitcpio.conf.d/archiso.conf ]]; then info "Removing archiso drop-in config..." - rm -f /mnt/etc/mkinitcpio.conf.d/archiso.conf + rm -f $MNTPOINT/etc/mkinitcpio.conf.d/archiso.conf fi # Create proper linux-lts preset info "Creating linux-lts preset..." - cat > /mnt/etc/mkinitcpio.d/linux-lts.preset << 'EOF' + cat > $MNTPOINT/etc/mkinitcpio.d/linux-lts.preset << 'EOF' # mkinitcpio preset file for linux-lts PRESETS=(default fallback) @@ -860,22 +860,22 @@ EOF # The traditional encrypt hook only supports a single cryptdevice info "Multi-device LUKS: using sd-encrypt for multi-device LUKS unlock" sed -i "s/^HOOKS=.*/HOOKS=(base systemd microcode modconf kms keyboard sd-vconsole block sd-encrypt btrfs filesystems fsck)/" \ - /mnt/etc/mkinitcpio.conf + $MNTPOINT/etc/mkinitcpio.conf elif [[ $num_disks -gt 1 ]]; then info "Multi-device btrfs: adding btrfs hook for device assembly" sed -i "s/^HOOKS=.*/HOOKS=(base udev microcode modconf kms keyboard keymap consolefont block btrfs filesystems fsck)/" \ - /mnt/etc/mkinitcpio.conf + $MNTPOINT/etc/mkinitcpio.conf elif [[ "$luks_enabled" == "yes" ]]; then sed -i "s/^HOOKS=.*/HOOKS=(base udev microcode modconf kms keyboard keymap consolefont block encrypt filesystems fsck)/" \ - /mnt/etc/mkinitcpio.conf + $MNTPOINT/etc/mkinitcpio.conf else sed -i "s/^HOOKS=.*/HOOKS=(base udev microcode modconf kms keyboard keymap consolefont block filesystems fsck)/" \ - /mnt/etc/mkinitcpio.conf + $MNTPOINT/etc/mkinitcpio.conf fi # Regenerate initramfs info "Regenerating initramfs..." - arch-chroot /mnt mkinitcpio -P + arch-chroot $MNTPOINT mkinitcpio -P info "Initramfs configured for btrfs." } @@ -900,11 +900,11 @@ btrfs_cleanup() { for ((i=${#BTRFS_SUBVOLS[@]}-1; i>=0; i--)); do IFS=':' read -r name mountpoint extra <<< "${BTRFS_SUBVOLS[$i]}" [[ "$name" == "@" ]] && continue - umount "/mnt$mountpoint" 2>/dev/null || true + umount "$MNTPOINT$mountpoint" 2>/dev/null || true done # Unmount root last - umount /mnt 2>/dev/null || true + umount $MNTPOINT 2>/dev/null || true info "Btrfs cleanup complete." } diff --git a/installer/lib/common.sh b/installer/lib/common.sh index dfeb245..e5f7246 100644 --- a/installer/lib/common.sh +++ b/installer/lib/common.sh @@ -6,11 +6,19 @@ # Path Constants ############################# +# Mount point for the install chroot's root. Sub-paths compose with +# $MNTPOINT/etc/... (the host paths the installer writes into during +# pacstrap and config). Bare $MNTPOINT works since `/` isn't an +# identifier character; use ${MNTPOINT}${chroot_efi_dir} when the +# next character would otherwise be parsed as part of the variable +# name. +MNTPOINT="/mnt" + # Mount point for the primary EFI partition during install. Sub-paths # compose with ${EFI_DIR}/...; secondary EFI partitions in multi-disk # layouts use ${EFI_DIR}${i} (no trailing slash, so the index appends # cleanly). -EFI_DIR="/mnt/efi" +EFI_DIR="$MNTPOINT/efi" ############################# # Output Functions diff --git a/testing-strategy.org b/testing-strategy.org index 6078631..f618bd1 100644 --- a/testing-strategy.org +++ b/testing-strategy.org @@ -61,7 +61,7 @@ Current coverage lives in =tests/unit/=: | File | What it covers | |------+----------------| -| =test_common.bats= | =command_exists=, =require_command=, =info=/=warn=/=error=, =enable_color=, =log=, =prompt_password=, =pacstrap_packages=, =install_dropin=, =parse_efibootmgr_*=, =EFI_DIR=, =enable_sshd_root_login=, =prepend_grub_cmdline_linux= | +| =test_common.bats= | =command_exists=, =require_command=, =info=/=warn=/=error=, =enable_color=, =log=, =prompt_password=, =pacstrap_packages=, =install_dropin=, =parse_efibootmgr_*=, =EFI_DIR=, =MNTPOINT=, =enable_sshd_root_login=, =prepend_grub_cmdline_linux= | | =test_config.bats= | =parse_args=, =load_config=, =validate_config=, =validate_filesystem=, =check_config=, default values pinned in config.sh | | =test_raid.bats= | =raid_valid_levels_for_count=, =raid_is_valid=, =raid_usable_bytes=, =raid_fault_tolerance= | | =test_disk.bats= | =get_efi_partition=, =get_root_partition=, =partition_disks= (orchestration shape) | diff --git a/tests/unit/test_common.bats b/tests/unit/test_common.bats index 48efd15..abe3938 100644 --- a/tests/unit/test_common.bats +++ b/tests/unit/test_common.bats @@ -333,6 +333,10 @@ Boot0001* ZFSBootMenu" [ "$EFI_DIR" = "/mnt/efi" ] } +@test "MNTPOINT is defined and equals /mnt" { + [ "$MNTPOINT" = "/mnt" ] +} + ############################# # enable_sshd_root_login ############################# |
