Updated install to disk.
This commit is contained in:
+179
-101
@@ -1,30 +1,19 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Stormux Gaming Image Disk Installer
|
# Stormux Gaming Image - Rsync-based Disk Installer
|
||||||
# WARNING: This will completely wipe the selected disk!
|
# Copies the live system to a target disk using rsync
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Function to print messages
|
# Text output functions
|
||||||
print_message() {
|
speak_and_echo() {
|
||||||
echo "$1"
|
echo "$1"
|
||||||
|
spd-say "$1" 2>/dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to get user confirmation
|
error_exit() {
|
||||||
get_confirmation() {
|
speak_and_echo "Error: $1"
|
||||||
local prompt="$1"
|
exit 1
|
||||||
local required_response="$2"
|
|
||||||
local response
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
print_message "$prompt"
|
|
||||||
read -r response
|
|
||||||
if [[ "$response" == "$required_response" ]]; then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
print_message "Response must be exactly: $required_response"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Function to detect available disks
|
# Function to detect available disks
|
||||||
@@ -57,50 +46,42 @@ get_disk_model() {
|
|||||||
lsblk -dpno MODEL "$disk" 2>/dev/null | tr -d ' ' || echo "Unknown"
|
lsblk -dpno MODEL "$disk" 2>/dev/null | tr -d ' ' || echo "Unknown"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if running as root
|
|
||||||
if [[ $EUID -ne 0 ]]; then
|
|
||||||
print_message "This script must be run as root."
|
|
||||||
print_message "Please run: sudo $0"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Welcome message
|
# Welcome message
|
||||||
print_message ""
|
clear
|
||||||
print_message "=== Stormux Gaming Image Installer ==="
|
speak_and_echo "Stormux Gaming Image Disk Installer"
|
||||||
print_message "WARNING: This installer will COMPLETELY WIPE the selected disk!"
|
speak_and_echo "This will install the current live system to a hard disk."
|
||||||
print_message "All data on the target disk will be permanently lost."
|
echo
|
||||||
|
speak_and_echo "WARNING: This will completely erase the target disk!"
|
||||||
|
|
||||||
# Detect available disks
|
# Detect available disks
|
||||||
print_message ""
|
speak_and_echo "Detecting available disks..."
|
||||||
print_message "Detecting available disks..."
|
|
||||||
mapfile -t available_disks < <(detect_disks)
|
mapfile -t available_disks < <(detect_disks)
|
||||||
|
|
||||||
if [[ ${#available_disks[@]} -eq 0 ]]; then
|
if [[ ${#available_disks[@]} -eq 0 ]]; then
|
||||||
print_message "No suitable disks found!"
|
error_exit "No suitable disks found!"
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Display available disks
|
# Display available disks
|
||||||
print_message ""
|
echo
|
||||||
print_message "Available disks:"
|
speak_and_echo "Available disks:"
|
||||||
for i in "${!available_disks[@]}"; do
|
for i in "${!available_disks[@]}"; do
|
||||||
disk="${available_disks[$i]}"
|
disk="${available_disks[$i]}"
|
||||||
size=$(get_disk_size "$disk")
|
size=$(get_disk_size "$disk")
|
||||||
model=$(get_disk_model "$disk")
|
model=$(get_disk_model "$disk")
|
||||||
print_message "$((i+1)). $disk - $size - $model" "$((i+1)). $disk - $size - $model"
|
echo "$((i+1)). $disk - $size - $model"
|
||||||
done
|
done
|
||||||
|
|
||||||
# Get disk selection
|
# Get disk selection
|
||||||
while true; do
|
while true; do
|
||||||
print_message ""
|
echo
|
||||||
print_message "Enter the number of the disk to install to:"
|
speak_and_echo "Enter the number of the disk to install to:"
|
||||||
read -r selection
|
read -r selection
|
||||||
|
|
||||||
if [[ "$selection" =~ ^[0-9]+$ ]] && [[ "$selection" -ge 1 ]] && [[ "$selection" -le ${#available_disks[@]} ]]; then
|
if [[ "$selection" =~ ^[0-9]+$ ]] && [[ "$selection" -ge 1 ]] && [[ "$selection" -le ${#available_disks[@]} ]]; then
|
||||||
selected_disk="${available_disks[$((selection-1))]}"
|
selected_disk="${available_disks[$((selection-1))]}"
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
print_message "Invalid selection. Please enter a number between 1 and ${#available_disks[@]}."
|
speak_and_echo "Invalid selection. Please enter a number between 1 and ${#available_disks[@]}."
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -108,86 +89,183 @@ done
|
|||||||
selected_size=$(get_disk_size "$selected_disk")
|
selected_size=$(get_disk_size "$selected_disk")
|
||||||
selected_model=$(get_disk_model "$selected_disk")
|
selected_model=$(get_disk_model "$selected_disk")
|
||||||
|
|
||||||
print_message ""
|
echo
|
||||||
print_message "FINAL WARNING:"
|
speak_and_echo "FINAL WARNING:"
|
||||||
print_message "You have selected: $selected_disk ($selected_size, $selected_model)"
|
speak_and_echo "You have selected: $selected_disk ($selected_size, $selected_model)"
|
||||||
print_message "ALL DATA ON THIS DISK WILL BE PERMANENTLY DESTROYED!"
|
speak_and_echo "ALL DATA ON THIS DISK WILL BE PERMANENTLY DESTROYED!"
|
||||||
|
echo
|
||||||
|
speak_and_echo "Type 'yes' to continue or any other key to cancel:"
|
||||||
|
read -r CONFIRM
|
||||||
|
|
||||||
get_confirmation "Type 'DESTROY ALL DATA' to continue (case sensitive): " "DESTROY ALL DATA"
|
if [[ "$CONFIRM" != "yes" ]]; then
|
||||||
|
speak_and_echo "Installation cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
print_message ""
|
# Check if we're on UEFI or BIOS
|
||||||
print_message "Starting installation to $selected_disk..."
|
if [[ -d /sys/firmware/efi ]]; then
|
||||||
|
BOOT_MODE="UEFI"
|
||||||
|
speak_and_echo "Detected UEFI boot mode"
|
||||||
|
else
|
||||||
|
BOOT_MODE="BIOS"
|
||||||
|
speak_and_echo "Detected BIOS boot mode"
|
||||||
|
fi
|
||||||
|
|
||||||
|
speak_and_echo "Starting installation to $selected_disk..."
|
||||||
|
|
||||||
# Unmount any existing partitions on the target disk
|
# Unmount any existing partitions on the target disk
|
||||||
print_message "Unmounting any existing partitions..."
|
speak_and_echo "Unmounting any existing partitions..."
|
||||||
umount "${selected_disk}"* 2>/dev/null || true
|
umount "${selected_disk}"* 2>/dev/null || true
|
||||||
|
|
||||||
# Create partition table and partitions
|
# Create partition table
|
||||||
print_message "Creating partition table..."
|
speak_and_echo "Creating partition table..."
|
||||||
parted -s "$selected_disk" mklabel gpt
|
if [[ "$BOOT_MODE" == "UEFI" ]]; then
|
||||||
parted -s "$selected_disk" mkpart primary fat32 1MiB 513MiB
|
# UEFI: GPT with EFI system partition
|
||||||
parted -s "$selected_disk" set 1 esp on
|
parted -s "$selected_disk" mklabel gpt
|
||||||
parted -s "$selected_disk" mkpart primary ext4 513MiB 100%
|
parted -s "$selected_disk" mkpart primary fat32 1MiB 513MiB
|
||||||
|
parted -s "$selected_disk" set 1 esp on
|
||||||
|
parted -s "$selected_disk" mkpart primary ext4 513MiB 100%
|
||||||
|
|
||||||
# Get partition names
|
# Set partition variables
|
||||||
if [[ "$selected_disk" =~ nvme|mmcblk ]]; then
|
if [[ "$selected_disk" =~ nvme|mmcblk ]]; then
|
||||||
boot_partition="${selected_disk}p1"
|
EFI_PART="${selected_disk}p1"
|
||||||
root_partition="${selected_disk}p2"
|
ROOT_PART="${selected_disk}p2"
|
||||||
|
else
|
||||||
|
EFI_PART="${selected_disk}1"
|
||||||
|
ROOT_PART="${selected_disk}2"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
boot_partition="${selected_disk}1"
|
# BIOS: MBR with boot flag
|
||||||
root_partition="${selected_disk}2"
|
parted -s "$selected_disk" mklabel msdos
|
||||||
|
parted -s "$selected_disk" mkpart primary ext4 1MiB 100%
|
||||||
|
parted -s "$selected_disk" set 1 boot on
|
||||||
|
|
||||||
|
# Set partition variables
|
||||||
|
if [[ "$selected_disk" =~ nvme|mmcblk ]]; then
|
||||||
|
ROOT_PART="${selected_disk}p1"
|
||||||
|
else
|
||||||
|
ROOT_PART="${selected_disk}1"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Wait for kernel to recognize partitions
|
||||||
|
sleep 2
|
||||||
|
partprobe "$selected_disk"
|
||||||
|
sleep 2
|
||||||
|
|
||||||
# Format partitions
|
# Format partitions
|
||||||
print_message "Formatting partitions..."
|
speak_and_echo "Formatting partitions..."
|
||||||
mkfs.fat -F32 "$boot_partition"
|
if [[ "$BOOT_MODE" == "UEFI" ]]; then
|
||||||
mkfs.ext4 -F "$root_partition"
|
mkfs.fat -F32 -n "STORMUX-EFI" "$EFI_PART"
|
||||||
|
fi
|
||||||
|
mkfs.ext4 -F -L "STORMUX-ROOT" "$ROOT_PART"
|
||||||
|
|
||||||
# Create mount points and mount
|
# Create mount points
|
||||||
mkdir -p /mnt/stormux-install
|
MOUNT_ROOT="/mnt/install_target"
|
||||||
mount "$root_partition" /mnt/stormux-install
|
mkdir -p "$MOUNT_ROOT"
|
||||||
mkdir -p /mnt/stormux-install/boot
|
|
||||||
mount "$boot_partition" /mnt/stormux-install/boot
|
|
||||||
|
|
||||||
# Copy system files
|
# Mount root partition
|
||||||
print_message "Copying system files... This may take several minutes."
|
speak_and_echo "Mounting partitions..."
|
||||||
if [[ -f /run/archiso/img_dev ]]; then
|
mount "$ROOT_PART" "$MOUNT_ROOT"
|
||||||
# Extract from squashfs
|
|
||||||
unsquashfs -f -d /mnt/stormux-install /run/archiso/sfs/airootfs/airootfs.sfs
|
# Mount EFI partition if UEFI
|
||||||
else
|
if [[ "$BOOT_MODE" == "UEFI" ]]; then
|
||||||
# Fallback: copy from live system
|
mkdir -p "$MOUNT_ROOT/boot/efi"
|
||||||
rsync -aHAXS --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} / /mnt/stormux-install/
|
mount "$EFI_PART" "$MOUNT_ROOT/boot/efi"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Configure for installed system
|
# Copy system using rsync
|
||||||
print_message "Configuring system for installed boot..."
|
speak_and_echo "Copying system files... This may take several minutes."
|
||||||
|
rsync -avx \
|
||||||
|
--exclude=/tmp/* \
|
||||||
|
--exclude=/proc/* \
|
||||||
|
--exclude=/sys/* \
|
||||||
|
--exclude=/dev/* \
|
||||||
|
--exclude=/run/* \
|
||||||
|
--exclude=/var/tmp/* \
|
||||||
|
--exclude=/var/log/journal/* \
|
||||||
|
--exclude=/mnt/* \
|
||||||
|
--exclude=/media/* \
|
||||||
|
--exclude=/lost+found \
|
||||||
|
--exclude=/home/stormux/.cache/* \
|
||||||
|
--exclude=/home/stormux/Downloads/* \
|
||||||
|
/ "$MOUNT_ROOT/"
|
||||||
|
|
||||||
# Remove live-specific files and services
|
# Create necessary directories
|
||||||
rm -f /mnt/stormux-install/etc/systemd/system/multi-user.target.wants/choose-mirror.service
|
speak_and_echo "Creating system directories..."
|
||||||
rm -rf /mnt/stormux-install/etc/systemd/system/etc-pacman.d-gnupg.mount
|
mkdir -p "$MOUNT_ROOT"/{tmp,proc,sys,dev,run,var/tmp,var/log/journal,mnt,media}
|
||||||
|
|
||||||
# Generate fstab
|
# Generate fstab
|
||||||
genfstab -U /mnt/stormux-install >> /mnt/stormux-install/etc/fstab
|
speak_and_echo "Generating fstab..."
|
||||||
|
ROOT_UUID=$(blkid -s UUID -o value "$ROOT_PART")
|
||||||
|
cat > "$MOUNT_ROOT/etc/fstab" << EOF
|
||||||
|
# Static information about the filesystems.
|
||||||
|
# See fstab(5) for details.
|
||||||
|
|
||||||
# Install and configure GRUB
|
# <file system> <dir> <type> <options> <dump> <pass>
|
||||||
print_message "Installing bootloader..."
|
UUID=$ROOT_UUID / ext4 rw,relatime 0 1
|
||||||
arch-chroot /mnt/stormux-install grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=stormux
|
EOF
|
||||||
arch-chroot /mnt/stormux-install grub-mkconfig -o /boot/grub/grub.cfg
|
|
||||||
|
|
||||||
# Set hostname
|
if [[ "$BOOT_MODE" == "UEFI" ]]; then
|
||||||
echo "stormux-gaming" > /mnt/stormux-install/etc/hostname
|
EFI_UUID=$(blkid -s UUID -o value "$EFI_PART")
|
||||||
|
echo "UUID=$EFI_UUID /boot/efi vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 2" >> "$MOUNT_ROOT/etc/fstab"
|
||||||
|
fi
|
||||||
|
|
||||||
# Enable necessary services
|
# Install bootloader
|
||||||
arch-chroot /mnt/stormux-install systemctl enable NetworkManager
|
speak_and_echo "Installing bootloader..."
|
||||||
arch-chroot /mnt/stormux-install systemctl enable pipewire pipewire-pulse
|
arch-chroot "$MOUNT_ROOT" /bin/bash << EOF
|
||||||
arch-chroot /mnt/stormux-install systemctl enable speech-dispatcher
|
# Update package database and install GRUB
|
||||||
arch-chroot /mnt/stormux-install systemctl enable fenrirscreenreader
|
pacman -Sy --noconfirm
|
||||||
|
|
||||||
# Cleanup
|
if [[ "$BOOT_MODE" == "UEFI" ]]; then
|
||||||
umount -R /mnt/stormux-install
|
# UEFI installation
|
||||||
rmdir /mnt/stormux-install
|
pacman -S --needed --noconfirm grub efibootmgr
|
||||||
|
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=Stormux
|
||||||
|
else
|
||||||
|
# BIOS installation
|
||||||
|
pacman -S --needed --noconfirm grub
|
||||||
|
grub-install --target=i386-pc "$selected_disk"
|
||||||
|
fi
|
||||||
|
|
||||||
print_message ""
|
# Generate GRUB configuration with accessibility
|
||||||
print_message "Installation completed successfully!"
|
grub-mkconfig -o /boot/grub/grub.cfg
|
||||||
print_message "You can now reboot and remove the installation media."
|
|
||||||
print_message "The system will boot directly into the Stormux Gaming environment."
|
# Enable accessibility in GRUB by default
|
||||||
|
if ! grep -q "GRUB_CMDLINE_LINUX_DEFAULT.*accessibility=on" /etc/default/grub; then
|
||||||
|
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="/GRUB_CMDLINE_LINUX_DEFAULT="accessibility=on /' /etc/default/grub
|
||||||
|
grub-mkconfig -o /boot/grub/grub.cfg
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Enable essential services
|
||||||
|
systemctl enable NetworkManager
|
||||||
|
systemctl enable pipewire.service
|
||||||
|
systemctl enable pipewire-pulse.service
|
||||||
|
systemctl enable unmute-audio.service
|
||||||
|
systemctl enable shutdown-sound.service
|
||||||
|
systemctl enable fenrirscreenreader-tty.service
|
||||||
|
systemctl disable espeakup.service
|
||||||
|
|
||||||
|
# Set up user services
|
||||||
|
systemctl --global enable pipewire.service
|
||||||
|
systemctl --global enable pipewire-pulse.service
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Remove firstboot marker if it exists
|
||||||
|
rm -f "$MOUNT_ROOT/home/stormux/.firstboot"
|
||||||
|
|
||||||
|
# Clean up mount points
|
||||||
|
speak_and_echo "Cleaning up..."
|
||||||
|
if [[ "$BOOT_MODE" == "UEFI" ]]; then
|
||||||
|
umount "$MOUNT_ROOT/boot/efi"
|
||||||
|
fi
|
||||||
|
umount "$MOUNT_ROOT"
|
||||||
|
rmdir "$MOUNT_ROOT"
|
||||||
|
|
||||||
|
# Success message
|
||||||
|
speak_and_echo "Installation completed successfully!"
|
||||||
|
echo
|
||||||
|
speak_and_echo "The system has been installed to $selected_disk"
|
||||||
|
speak_and_echo "You can now reboot and remove the USB drive."
|
||||||
|
echo
|
||||||
|
speak_and_echo "Press Enter to continue..."
|
||||||
|
read -r
|
||||||
|
|||||||
Reference in New Issue
Block a user