55
66set -euo pipefail
77
8+ # Configuration file for installation state
9+ INSTALL_CONFIG_FILE=" /tmp/osvmarchi-install.conf"
10+
11+ # Save installation state
12+ save_install_state () {
13+ local key=" $1 "
14+ local value=" $2 "
15+
16+ # Create config file if it doesn't exist
17+ [[ ! -f " $INSTALL_CONFIG_FILE " ]] && touch " $INSTALL_CONFIG_FILE "
18+
19+ # Remove existing key if present
20+ sed -i " /^${key} =/d" " $INSTALL_CONFIG_FILE "
21+
22+ # Add new key=value
23+ echo " ${key} =${value} " >> " $INSTALL_CONFIG_FILE "
24+ }
25+
26+ # Load installation state
27+ load_install_state () {
28+ local key=" $1 "
29+
30+ if [[ -f " $INSTALL_CONFIG_FILE " ]]; then
31+ grep " ^${key} =" " $INSTALL_CONFIG_FILE " | cut -d' =' -f2-
32+ fi
33+ }
34+
35+ # Clean up configuration
36+ cleanup_install_state () {
37+ [[ -f " $INSTALL_CONFIG_FILE " ]] && rm -f " $INSTALL_CONFIG_FILE "
38+ }
39+
840# Colors for output
941RED=' \033[0;31m'
1042GREEN=' \033[0;32m'
@@ -76,8 +108,21 @@ check_prerequisites() {
76108
77109 if [[ ${# missing_tools[@]} -gt 0 ]]; then
78110 log_error " Missing required tools: ${missing_tools[*]} "
79- log_info " Installing missing tools..."
80- pacman -Sy --noconfirm " ${missing_tools[@]} "
111+ log_warning " The following tools need to be installed: ${missing_tools[*]} "
112+
113+ if gum confirm " Install missing tools now? (Requires internet connection)" ; then
114+ log_info " Installing missing tools..."
115+ if ! pacman -Sy --noconfirm " ${missing_tools[@]} " ; then
116+ log_error " Failed to install required tools"
117+ log_info " Please install manually: pacman -S ${missing_tools[*]} "
118+ exit 1
119+ fi
120+ log_success " Tools installed successfully"
121+ else
122+ log_error " Cannot proceed without required tools"
123+ log_info " Please install manually: pacman -S ${missing_tools[*]} "
124+ exit 1
125+ fi
81126 fi
82127}
83128
@@ -203,8 +248,25 @@ automatic_partition() {
203248 exit 1
204249 fi
205250
206- # Unmount any existing partitions
207- umount " ${disk} " * 2> /dev/null || true
251+ # Safely unmount any existing partitions
252+ log_info " Checking for mounted partitions on $disk ..."
253+ local mounted_parts
254+ mapfile -t mounted_parts < <( findmnt -rno TARGET,SOURCE | grep " ^/.*$disk " | awk ' {print $1}' | sort -r)
255+
256+ if [[ ${# mounted_parts[@]} -gt 0 ]]; then
257+ log_warning " Found mounted partitions, unmounting safely..."
258+ for mount_point in " ${mounted_parts[@]} " ; do
259+ log_info " Unmounting $mount_point "
260+ if ! umount " $mount_point " 2> /dev/null; then
261+ log_warning " Normal unmount failed, forcing unmount of $mount_point "
262+ if ! umount -f " $mount_point " 2> /dev/null; then
263+ log_error " Failed to unmount $mount_point , disk may be busy"
264+ log_info " Please manually unmount all partitions on $disk before continuing"
265+ exit 1
266+ fi
267+ fi
268+ done
269+ fi
208270
209271 # Wipe disk
210272 log_info " Wiping disk $disk ..."
@@ -239,9 +301,9 @@ automatic_partition() {
239301 log_info " Formatting root partition..."
240302 mkfs.ext4 -L " OSVMarchi" " $root_part "
241303
242- # Export partition variables for later use
243- export OSVMARCHI_BOOT_PART= " $boot_part "
244- export OSVMARCHI_ROOT_PART= " $root_part "
304+ # Save partition information to config file
305+ save_install_state " OSVMARCHI_BOOT_PART" " $boot_part "
306+ save_install_state " OSVMARCHI_ROOT_PART" " $root_part "
245307
246308 log_success " Automatic partitioning complete"
247309}
@@ -282,28 +344,107 @@ manual_partition() {
282344 exit 1
283345 fi
284346
285- # Export partition variables for later use
286- export OSVMARCHI_BOOT_PART=" $boot_part "
287- export OSVMARCHI_ROOT_PART=" $root_part "
347+ # Validate EFI System Partition
348+ log_info " Validating EFI System Partition..."
349+ local boot_fstype
350+ boot_fstype=$( lsblk -no FSTYPE " $boot_part " 2> /dev/null || echo " unknown" )
351+
352+ if [[ " $boot_fstype " != " vfat" ]]; then
353+ log_warning " EFI partition ($boot_part ) is not FAT32 (found: $boot_fstype )"
354+ if gum confirm " Format $boot_part as FAT32?" ; then
355+ log_info " Formatting EFI partition as FAT32..."
356+ mkfs.fat -F 32 -n " EFI" " $boot_part "
357+ else
358+ log_error " EFI partition must be FAT32 for UEFI boot"
359+ exit 1
360+ fi
361+ fi
362+
363+ # Check EFI System Partition flag using sgdisk
364+ if command -v sgdisk & > /dev/null; then
365+ local part_num
366+ part_num=$( echo " $boot_part " | grep -o ' [0-9]*$' )
367+ local disk_path
368+ disk_path=$( echo " $boot_part " | sed ' s/[p]*[0-9]*$//' )
369+
370+ if ! sgdisk -i " $part_num " " $disk_path " | grep -q " EF00" ; then
371+ log_warning " EFI partition does not have ESP (EF00) type code"
372+ if gum confirm " Set ESP type code on $boot_part ?" ; then
373+ sgdisk -t " ${part_num} :EF00" " $disk_path "
374+ log_success " ESP type code set"
375+ else
376+ log_warning " Continuing without ESP type code (may cause boot issues)"
377+ fi
378+ fi
379+ fi
380+
381+ # Validate root partition filesystem
382+ log_info " Validating root partition..."
383+ local root_fstype
384+ root_fstype=$( lsblk -no FSTYPE " $root_part " 2> /dev/null || echo " unknown" )
288385
289- log_success " Manual partitioning complete"
290- log_info " Boot partition: $boot_part "
291- log_info " Root partition: $root_part "
386+ if [[ " $root_fstype " == " unknown" || " $root_fstype " == " " ]]; then
387+ log_warning " Root partition ($root_part ) appears unformatted"
388+ local fs_choice
389+ fs_choice=$( echo -e " ext4\nbtrfs" | gum choose --header=" Choose filesystem for root partition:" )
390+
391+ case " $fs_choice " in
392+ " ext4" )
393+ log_info " Formatting root partition as ext4..."
394+ mkfs.ext4 -L " OSVMarchi" " $root_part "
395+ ;;
396+ " btrfs" )
397+ log_info " Formatting root partition as btrfs..."
398+ mkfs.btrfs -L " OSVMarchi" " $root_part "
399+ ;;
400+ esac
401+ elif [[ " $root_fstype " != " ext4" && " $root_fstype " != " btrfs" && " $root_fstype " != " xfs" ]]; then
402+ log_warning " Root partition filesystem ($root_fstype ) may not be suitable"
403+ if ! gum confirm " Continue with $root_fstype filesystem?" ; then
404+ exit 1
405+ fi
406+ fi
407+
408+ # Save partition information to config file
409+ save_install_state " OSVMARCHI_BOOT_PART" " $boot_part "
410+ save_install_state " OSVMARCHI_ROOT_PART" " $root_part "
411+
412+ log_success " Manual partitioning complete and validated"
413+ log_info " Boot partition: $boot_part ($boot_fstype )"
414+ log_info " Root partition: $root_part ($root_fstype )"
292415}
293416
294417# Mount partitions and install base system
295418install_base_system () {
296- local root_part=" $OSVMARCHI_ROOT_PART "
297- local boot_part=" $OSVMARCHI_BOOT_PART "
419+ local root_part
420+ local boot_part
421+
422+ # Load partition information from config
423+ root_part=$( load_install_state " OSVMARCHI_ROOT_PART" )
424+ boot_part=$( load_install_state " OSVMARCHI_BOOT_PART" )
425+
426+ if [[ -z " $root_part " || -z " $boot_part " ]]; then
427+ log_error " Partition information not found in configuration"
428+ exit 1
429+ fi
298430
299431 log_info " Mounting partitions..."
432+ log_info " Root: $root_part -> /mnt"
433+ log_info " Boot: $boot_part -> /mnt/boot"
300434
301435 # Mount root
302- mount " $root_part " /mnt
436+ if ! mount " $root_part " /mnt; then
437+ log_error " Failed to mount root partition $root_part "
438+ exit 1
439+ fi
303440
304441 # Create and mount boot
305442 mkdir -p /mnt/boot
306- mount " $boot_part " /mnt/boot
443+ if ! mount " $boot_part " /mnt/boot; then
444+ log_error " Failed to mount boot partition $boot_part "
445+ umount /mnt 2> /dev/null || true
446+ exit 1
447+ fi
307448
308449 log_info " Installing base Arch Linux system..."
309450
@@ -323,8 +464,17 @@ install_base_system() {
323464configure_base_system () {
324465 log_info " Configuring base system..."
325466
326- # Chroot configuration script
327- cat > /mnt/configure_system.sh << 'EOF '
467+ # Get partition information
468+ local root_part
469+ root_part=$( load_install_state " OSVMARCHI_ROOT_PART" )
470+
471+ if [[ -z " $root_part " ]]; then
472+ log_error " Root partition information not found"
473+ exit 1
474+ fi
475+
476+ # Create configuration script that will run in chroot
477+ cat > /mnt/configure_system.sh << EOF
328478#!/bin/bash
329479set -e
330480
@@ -353,13 +503,16 @@ systemctl enable NetworkManager
353503# Install and configure bootloader (systemd-boot)
354504bootctl install
355505
506+ # Get root partition UUID for bootloader
507+ ROOT_PARTUUID=\$ (blkid -s PARTUUID -o value $root_part )
508+
356509# Create bootloader entry
357510mkdir -p /boot/loader/entries
358511cat > /boot/loader/entries/arch.conf << EOL
359512title OSVMarchi
360513linux /vmlinuz-linux
361514initrd /initramfs-linux.img
362- options root=PARTUUID=$(blkid -s PARTUUID -o value ${OSVMARCHI_ROOT_PART}) rw quiet splash
515+ options root=PARTUUID=\$ ROOT_PARTUUID rw quiet splash
363516EOL
364517
365518cat > /boot/loader/loader.conf << EOL
@@ -371,15 +524,28 @@ EOL
371524
372525# Create user
373526useradd -m -G wheel -s /bin/bash user
374- echo "user:user" | chpasswd
375527
376- # Configure sudo
377- echo "%wheel ALL=(ALL:ALL) ALL" >> /etc/sudoers
528+ # Disable root password and lock account for security
529+ passwd -l root
530+
531+ # Configure sudo using proper sudoers.d approach
532+ cat > /etc/sudoers.d/wheel << EOL
533+ # Allow wheel group to use sudo
534+ %wheel ALL=(ALL:ALL) ALL
535+ EOL
378536
379- # Set root password
380- echo "root:root" | chpasswd
537+ # Set secure permissions on sudoers.d file
538+ chmod 0440 /etc/sudoers.d/wheel
539+
540+ # Force password change on first login for user
541+ chage -d 0 user
542+
543+ # Set a temporary password that must be changed
544+ echo "user:changeme" | chpasswd
381545
382546echo "Base system configuration complete"
547+ echo "SECURITY: User password must be changed on first login"
548+ echo "SECURITY: Root account is locked for security"
383549EOF
384550
385551 # Make script executable and run it
@@ -442,11 +608,22 @@ main() {
442608
443609 # Cleanup
444610 log_info " Cleaning up..."
445- umount -R /mnt
611+
612+ # Safely unmount all mounted filesystems
613+ if mountpoint -q /mnt/boot; then
614+ umount /mnt/boot
615+ fi
616+ if mountpoint -q /mnt; then
617+ umount /mnt
618+ fi
619+
620+ # Clean up temporary configuration
621+ cleanup_install_state
446622
447623 log_success " OSVMarchi installation completed successfully!"
448624 log_info " You can now reboot into your new OSVMarchi system"
449- log_info " Default login: user/user (change password after first login)"
625+ log_warning " IMPORTANT: User password is 'changeme' and MUST be changed on first login"
626+ log_info " Root account is locked for security - use sudo for administrative tasks"
450627
451628 if gum confirm " Reboot now?" ; then
452629 reboot
0 commit comments