diff --git a/image-recipe/build-auto-installer-iso.sh b/image-recipe/build-auto-installer-iso.sh index f3286629..51925c88 100755 --- a/image-recipe/build-auto-installer-iso.sh +++ b/image-recipe/build-auto-installer-iso.sh @@ -1417,41 +1417,61 @@ boxline() { cc "${DIM}│${NC} $1${right}${DIM}│${NC}" } +# TUI helpers — Claude Code-inspired status display +STEP=0 +TOTAL_STEPS=7 +step() { + STEP=$((STEP + 1)) + echo "" + cc "${WHITE}[$STEP/$TOTAL_STEPS]${NC} ${DIM}$1${NC}" +} +ok() { cc " ${GREEN}$1${NC}"; } +warn() { cc " ${YELLOW}$1${NC}"; } +fail() { cc " ${RED}$1${NC}"; } +spinner() { + local pid=$1 msg=$2 + local frames='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏' + local i=0 + while kill -0 "$pid" 2>/dev/null; do + printf "\r ${DIM}%s %s${NC}" "${frames:i%10:1}" "$msg" + i=$((i + 1)) + sleep 0.1 + done + printf "\r ${GREEN}✓ %s${NC}\n" "$msg" +} + clear echo "" box boxline "" -boxline "${WHITE}A R C H I P E L A G O${NC}" +boxline "${WHITE}a r c h i p e l a g o${NC}" boxline "${ORANGE}━━━━━━━━━━━━━━━━━━━━━${NC}" -boxline "${DIM}Automatic Installation${NC}" +boxline "${DIM}automatic installation${NC}" boxline "" boxend echo "" # Check required tools are present (should be bundled in ISO) -cc "${DIM}Checking installer tools...${NC}" +step "Checking tools" MISSING="" command -v parted >/dev/null 2>&1 || MISSING="parted $MISSING" command -v mkfs.vfat >/dev/null 2>&1 || MISSING="mkfs.vfat $MISSING" command -v mkfs.ext4 >/dev/null 2>&1 || MISSING="mkfs.ext4 $MISSING" if [ -n "$MISSING" ]; then - echo " Missing tools: $MISSING" - echo " Attempting to install (requires network)..." + warn "Installing missing: $MISSING" if apt-get update -qq >/dev/null 2>&1; then - apt-get install -y -qq parted dosfstools e2fsprogs >/dev/null 2>&1 && echo " ✅ Tools installed" || { - echo -e "${RED}❌ Failed to install required tools. No network?${NC}" - echo " Required: parted, mkfs.vfat, mkfs.ext4" + apt-get install -y -qq parted dosfstools e2fsprogs >/dev/null 2>&1 && ok "Tools installed" || { + fail "Failed to install required tools" exit 1 } else - echo -e "${RED}❌ No network available and tools not bundled.${NC}" + fail "No network available and tools not bundled" exit 1 fi else - echo " ✅ All tools present" + ok "All tools present" fi -echo "" # Find boot media BOOT_MEDIA="" @@ -1477,7 +1497,7 @@ fi BOOT_DEV=$(findmnt -n -o SOURCE "$BOOT_MEDIA" 2>/dev/null | sed 's/[0-9]*$//' | sed 's/p[0-9]*$//') BOOT_DEV_NAME=$(basename "$BOOT_DEV" 2>/dev/null || echo "") -echo -e "${YELLOW}📋 Detecting disks...${NC}" +step "Detecting disks" echo "" # Find internal disk (prefer NVMe, then SATA, skip USB) @@ -1527,16 +1547,14 @@ if [ -z "$TARGET_DISK" ]; then exit 1 fi +ok "$TARGET_DISK ($TARGET_SIZE)" echo "" -cc "${GREEN}target: ${WHITE}$TARGET_DISK ($TARGET_SIZE)${NC}" +hrule echo "" cc "${RED}all data on $TARGET_DISK will be erased${NC}" echo "" -cc "${DIM}Press Enter to install | Ctrl+C to cancel${NC}" +cc "${DIM}press enter to install | ctrl+c to cancel${NC}" read -s - -echo "" -cc "${DIM}Installing Archipelago...${NC}" echo "" # Unmount any existing partitions @@ -1544,7 +1562,7 @@ umount ${TARGET_DISK}* 2>/dev/null || true umount ${TARGET_DISK}p* 2>/dev/null || true # Create partition table — dual BIOS+UEFI boot + LUKS2 encrypted data -echo " [1/7] Creating partitions..." +step "Creating partitions" parted -s "$TARGET_DISK" mklabel gpt # Partition 1: 1MB BIOS boot partition (for legacy BIOS GRUB on GPT disks) parted -s "$TARGET_DISK" mkpart bios_boot 1MiB 2MiB @@ -1573,24 +1591,26 @@ else fi # Format partitions -echo " [2/7] Formatting partitions..." +step "Formatting partitions" # Zero out the BIOS boot partition to prevent FAT-fs read errors during boot dd if=/dev/zero of="$BIOS_PART" bs=1M count=1 2>/dev/null || true mkfs.vfat -F32 -n EFI "$EFI_PART" mkfs.ext4 -F -L archipelago "$ROOT_PART" # Mount root + extract rootfs (need cryptsetup from rootfs for LUKS) -echo " [3/7] Mounting filesystems..." +ok "Partitions created" +echo "" +cc "${DIM}Mounting filesystems...${NC}" mkdir -p /mnt/target mount "$ROOT_PART" /mnt/target mkdir -p /mnt/target/boot/efi mount "$EFI_PART" /mnt/target/boot/efi -echo " [4/7] Installing system (this may take a few minutes)..." +step "Installing system" tar -xf "$ROOTFS_TAR" -C /mnt/target # LUKS2 encryption for data partition -echo " [5/7] Encrypting data partition (LUKS2)..." +step "Encrypting data partition" # Generate random 4KB key file dd if=/dev/urandom of=/mnt/target/root/.luks-archipelago.key bs=4096 count=1 2>/dev/null @@ -1646,7 +1666,7 @@ chown -R 1000:1000 /mnt/target/var/lib/archipelago echo " ✅ Data partition encrypted with LUKS2 ($LUKS_CIPHER)" # Configure auto-unlock via crypttab (key file on root partition) -echo " [6/7] Configuring system..." +step "Configuring system" DATA_UUID=$(blkid -s UUID -o value "$DATA_PART") echo "# LUKS2 encrypted data — auto-unlock with key file" > /mnt/target/etc/crypttab echo "archipelago-data UUID=$DATA_UUID /root/.luks-archipelago.key luks,discard" >> /mnt/target/etc/crypttab @@ -2064,7 +2084,7 @@ KIOSKTOGGLE chmod +x /mnt/target/usr/local/bin/archipelago-kiosk # Install GRUB -echo " [7/7] Installing bootloader..." +step "Installing bootloader" mount --bind /dev /mnt/target/dev mount --bind /dev/pts /mnt/target/dev/pts mount --bind /proc /mnt/target/proc @@ -2196,6 +2216,22 @@ chroot /mnt/target update-initramfs -u -k all 2>&1 | grep -v "Possible missing f chroot /mnt/target update-grub +# CRITICAL: Write EFI grub.cfg that finds the root filesystem and loads the full config. +# grub-install --removable creates a BOOTX64.EFI that looks for grub.cfg on the +# EFI FAT partition (/EFI/BOOT/grub.cfg). This stub must search for the root FS +# and then load the full /boot/grub/grub.cfg from ext4. +ROOT_UUID=$(blkid -s UUID -o value "$ROOT_PART") +if [ -n "$ROOT_UUID" ] && [ -d "/mnt/target/boot/efi/EFI/BOOT" ]; then + cat > /mnt/target/boot/efi/EFI/BOOT/grub.cfg <