Fix non-interactive install and fstab setup

This commit is contained in:
Stefan Strobl 2025-12-25 10:31:30 +01:00
parent 8cc60e3dae
commit 89c88c8a2e
3 changed files with 66 additions and 48 deletions

View File

@ -66,6 +66,7 @@ format_filesystems() {
mkdir -p "$temp_mount"
# Ensure cleanup on error
# shellcheck disable=SC2329
cleanup_temp_mount() {
if mountpoint -q "$temp_mount" 2>/dev/null; then
umount "$temp_mount" || log_warn "Failed to unmount temp mount: $temp_mount"

View File

@ -77,8 +77,8 @@ packages_install() {
log_info "Installing ${#all_packages[@]} packages (this may take several minutes)..."
# Ensure repository is accessible and synchronized
# Use chroot to install packages into target system
if ! chroot "$MOUNT_ROOT" xbps-install -Syu "${all_packages[@]}"; then
# Install directly into the target root to avoid missing tooling inside chroot
if ! xbps-install -Sy -R "$MOUNT_ROOT" -y "${all_packages[@]}"; then
die "Package installation failed. Check network connectivity and repository status."
fi
@ -88,7 +88,7 @@ packages_install() {
log_info "Verifying package installation..."
local critical_packages=("base-system" "linux" "grub" "cryptsetup")
for pkg in "${critical_packages[@]}"; do
if ! chroot "$MOUNT_ROOT" xbps-query "$pkg" >/dev/null 2>&1; then
if ! xbps-query -R "$MOUNT_ROOT" "$pkg" >/dev/null 2>&1; then
die "Critical package not found: $pkg"
fi
done

View File

@ -65,6 +65,7 @@ postinstall_unbind_mounts() {
postinstall_run() {
: "${ROOT_PART:?Root partition is required}"
: "${ESP_PART:?ESP partition is required}"
: "${CRYPT_NAME:?Crypt mapping name is required}"
: "${MOUNT_ROOT:?Mount root is required}"
: "${FS_TYPE:?Filesystem type is required}"
@ -72,15 +73,17 @@ postinstall_run() {
: "${HOSTNAME:?Hostname is required}"
local luks_uuid
local root_uuid
local esp_uuid
luks_uuid="$(cryptsetup luksUUID "$ROOT_PART")"
root_uuid="$(blkid -s UUID -o value "/dev/mapper/${CRYPT_NAME}")"
esp_uuid="$(blkid -s UUID -o value "$ESP_PART")"
log_info "Post-install: configuring target system in chroot"
postinstall_bind_mounts
trap postinstall_unbind_mounts EXIT
LUKS_UUID="$luks_uuid" ROOT_UUID="$root_uuid" FS_TYPE="$FS_TYPE" SWAP_SIZE="$SWAP_SIZE" HOSTNAME="$HOSTNAME" \
LUKS_UUID="$luks_uuid" ROOT_UUID="$root_uuid" ESP_UUID="$esp_uuid" FS_TYPE="$FS_TYPE" SWAP_SIZE="$SWAP_SIZE" HOSTNAME="$HOSTNAME" \
chroot "$MOUNT_ROOT" /bin/bash -s <<'EOS'
set -euo pipefail
@ -107,6 +110,63 @@ else
printf 'add_dracutmodules+=" crypt "\n' > /etc/dracut.conf.d/10-crypt.conf
fi
update_fstab_entry() {
local mount_point="$1"
local fs_type="$2"
local options="$3"
local uuid="$4"
if [[ -z "$uuid" ]]; then
echo "Missing UUID for $mount_point" >&2
exit 1
fi
local line="UUID=$uuid $mount_point $fs_type $options 0 0"
if awk -v mp="$mount_point" '$2==mp {found=1} END {exit found?0:1}' /etc/fstab; then
awk -v mp="$mount_point" -v line="$line" 'BEGIN{OFS=" "} $2==mp {$0=line} {print}' /etc/fstab > /etc/fstab.tmp
mv /etc/fstab.tmp /etc/fstab
else
printf '%s\n' "$line" >> /etc/fstab
fi
}
create_swapfile() {
local swap_size="$1"
# Try fallocate first, fall back to dd if it fails
if ! fallocate -l "$swap_size" /swap/swapfile 2>/dev/null; then
echo "fallocate failed, using dd as fallback..."
local size_num
local size_unit
local bs="1M"
local count
size_num="${swap_size%%[^0-9.]*}"
size_unit="${swap_size##*[0-9.]}"
case "$size_unit" in
GiB|G|GB) count=$(awk "BEGIN {print int($size_num * 1024)}") ;;
MiB|M|MB|"") count=$(awk "BEGIN {print int($size_num)}") ;;
*) echo "Warning: unknown size unit, assuming MiB"; count=$(awk "BEGIN {print int($size_num)}") ;;
esac
dd if=/dev/zero of=/swap/swapfile bs="$bs" count="$count" status=progress
fi
}
touch /etc/fstab
update_fstab_entry /boot/efi vfat "defaults" "$ESP_UUID"
if [[ "$FS_TYPE" == "btrfs" ]]; then
update_fstab_entry / "btrfs" "defaults,subvol=@" "$ROOT_UUID"
update_fstab_entry /home "btrfs" "defaults,subvol=@home" "$ROOT_UUID"
update_fstab_entry /var "btrfs" "defaults,subvol=@var" "$ROOT_UUID"
update_fstab_entry /var/log "btrfs" "defaults,subvol=@log" "$ROOT_UUID"
update_fstab_entry /.snapshots "btrfs" "defaults,subvol=@snapshots" "$ROOT_UUID"
update_fstab_entry /swap "btrfs" "defaults,subvol=@swap" "$ROOT_UUID"
else
update_fstab_entry / "ext4" "defaults" "$ROOT_UUID"
fi
# Prepare a swap file inside the encrypted root if enabled.
if [[ "$SWAP_SIZE" != "0" ]]; then
mkdir -p /swap
@ -119,25 +179,7 @@ if [[ "$SWAP_SIZE" != "0" ]]; then
fi
fi
# Try fallocate first, fall back to dd if it fails
if ! fallocate -l "$SWAP_SIZE" /swap/swapfile 2>/dev/null; then
echo "fallocate failed, using dd as fallback..."
# Extract numeric size and unit for dd
local size_num="${SWAP_SIZE%%[^0-9.]*}"
local size_unit="${SWAP_SIZE##*[0-9]}"
local bs="1M"
local count="$size_num"
# Convert to MB count for dd
case "$size_unit" in
GiB|G|GB) count=$(awk "BEGIN {print int($size_num * 1024)}") ;;
MiB|M|MB) count=$(awk "BEGIN {print int($size_num)}") ;;
*) echo "Warning: unknown size unit, assuming MiB"; count="$size_num" ;;
esac
dd if=/dev/zero of=/swap/swapfile bs="$bs" count="$count" status=progress
fi
create_swapfile "$SWAP_SIZE"
chmod 600 /swap/swapfile
mkswap /swap/swapfile
if ! grep -q '^/swap/swapfile' /etc/fstab; then
@ -145,31 +187,6 @@ if [[ "$SWAP_SIZE" != "0" ]]; then
fi
fi
# Ensure btrfs subvolumes are reflected in /etc/fstab.
if [[ "$FS_TYPE" == "btrfs" ]]; then
touch /etc/fstab
update_fstab_entry() {
local mount_point="$1"
local options="$2"
local line="UUID=$ROOT_UUID $mount_point btrfs $options 0 0"
if awk -v mp="$mount_point" '$2==mp {found=1} END {exit found?0:1}' /etc/fstab; then
awk -v mp="$mount_point" -v line="$line" 'BEGIN{OFS=" "} $2==mp {$0=line} {print}' /etc/fstab > /etc/fstab.tmp
mv /etc/fstab.tmp /etc/fstab
else
printf '%s\n' "$line" >> /etc/fstab
fi
}
update_fstab_entry / "defaults,subvol=@"
update_fstab_entry /home "defaults,subvol=@home"
update_fstab_entry /var "defaults,subvol=@var"
update_fstab_entry /var/log "defaults,subvol=@log"
update_fstab_entry /.snapshots "defaults,subvol=@snapshots"
update_fstab_entry /swap "defaults,subvol=@swap"
fi
# Ensure GRUB unlocks the encrypted root and passes the LUKS UUID to initramfs.
mkdir -p /etc/default
touch /etc/default/grub