You are not logged in.
Hey Folks,
I decided to make my own shell script to semi-automate the installation of Arch. The script works as expected as long as the disk chosen not an nvme drive. Initially when I wrote this I did not account for the fact that nvme drives show up as "/dev/nvme0n1" or a variation of that depending where on the motherboad it is installed. Once you partition that drive your partitions would show up as "/dev/nvme0n1p1" and so on...
I tried to create some logic in the script to append a "p" at the end of the disk name, before the partition number. If the selected disk is nvme but the script fails after I set the EFI and Boot partition sizes just before formatting partitions and setting up LVM. The script seems to assume partition 3 is "/dev/sda3" even though the disk selected was "/dev/nvme0n1" and all printed output shows the base disk is "/dev/nvme0n1"
At this point I cannot tell if the "get_partitions" function is the issue or if I missed calling $PART3 somewhere. (likely tunnel vision on my part from staring at it for so long.) Script is available on github
Full disclosure, I have zero professional training or experience in writing scripts/code I know enough to be dangerous. I did this as a tool for my self and as a learning exorcise. Any insight is highly appreciated.
Link to script: https://github.com/live4thamuzik/archl4tm
*OP Editied to fix typos and add detail about the issue*
Last edited by live4thamuzik (2024-11-23 18:02:07)
Offline
had a thought... does it make more sense to just have a conditional logic for each time I need the script to add the "p" between ${disk} and the partition number versus relying on external variables?
## Global Functions ##
# --- Logging Functions ---
log_output() {
local message="$1"
echo "$(date +"%Y-%m-%d %H:%M:%S") - $message"
}
log_error() {
local message="$1"
local err_code="$2"
echo "$(date +"%Y-%m-%d %H:%M:%S") - Error: $message (exit code: $err_code)" >&2
}
log_debug() {
local message="$1"
echo "$(date +"%Y-%m-%d %H:%M:%S") - Debug: $message" >&2
}
log_info() {
local message="$1"
echo "$(date +"%Y-%m-%d %H:%M:%S") - Info: $message"
}
log_warning() {
local message="$1"
echo "$(date +"%Y-%m-%d %H:%M:%S") - Warning: $message" >&2
}
# --- Input Validation Functions ---
validate_username() {
local username="$1"
if [[ "${username,,}" =~ ^[a-z_]([a-z0-9_-]{0,31}|[a-z0-9_-]{0,30}\$)$ ]]; then
return 0 # True
else
log_error "Invalid username: $username" 1 # Log the error here
return 1 # False
fi
}
validate_hostname() {
local hostname="$1"
if [[ "${hostname,,}" =~ ^[a-z][a-z0-9_.-]{0,62}[a-z0-9]$ ]]; then
return 0 # True
else
log_error "Invalid hostname: $hostname" 1 # Log the error here
return 1 # False
fi
}
validate_disk() {
local disk="$1"
if [ -b "$disk" ]; then
return 0 # True
else
log_error "Invalid disk path: $disk" 1 # Log the error here
return 1 # False
fi
}
# --- Confirmation Function ---
confirm_action() {
local message="$1"
read -r -p "$message (Y/n) " confirm
confirm=${confirm,,} # Convert to lowercase
# Check if confirm is "y" or empty
if [[ "$confirm" == "y" ]] || [[ -z "$confirm" ]]; then
return 0 # True
else
return 1 # False
fi
}
get_disk() {
# List Disks
log_output "Available disks:"
fdisk -l | grep "Disk /" # Only list whole disks
while true; do
read -r -p "Enter the disk to use (e.g., /dev/sda): " disk
if ! validate_disk "$disk"; then # Use the validate_disk function from functions.sh
continue
fi
# Confirm Disk Selection using confirm_action from functions.sh
if confirm_action "You have selected $disk. Is this correct?"; then
export DISK="$disk"
log_output "Disk set to: $DISK"
break
fi
done
}
get_partition_sizes() {
while true; do
read -r -p "Enter EFI partition size (e.g., 2G, 512M): " efi_size
read -r -p "Enter boot partition size (e.g., 5G, 1G): " boot_size
# Basic validation (you might want to add more robust checks)
if [[ "$efi_size" =~ ^[0-9]+(G|M|K)$ ]] && \
[[ "$boot_size" =~ ^[0-9]+(G|M|K)$ ]]; then
export EFI_SIZE="$efi_size"
export BOOT_SIZE="$boot_size"
log_output "EFI partition size: $EFI_SIZE"
log_output "Boot partition size: $BOOT_SIZE"
break
else
log_error "Invalid partition size(s). Please use a format like 2G or 512M." 1
fi
done
}
get_encryption_password() {
while true; do
read -rs -p "Enter encryption password: " password
echo
read -rs -p "Confirm encryption password: " confirm_password
echo
if [[ "$password" != "$confirm_password" ]]; then
log_error "Passwords do not match." 1
continue
fi
export ENCRYPTION_PASSWORD="$password"
log_output "Encryption password set." # Avoid logging the password itself
break
done
}
partition_disk() {
local disk="$1"
local efi_size="$2"
local boot_size="$3"
log_output "Partitioning disk: $disk"
# Create new GPT partition table
if ! sgdisk --zap-all "$disk"; then
log_error "Failed to clear disk" $?
exit 1
fi
# Create EFI partition
if ! sgdisk -n 1:0:+"$efi_size" -t 1:EF00 "$disk"; then
log_error "Failed to create EFI partition" $?
exit 1
fi
# Create boot partition
if ! sgdisk -n 2:0:+"$boot_size" -t 2:8300 "$disk"; then
log_error "Failed to create boot partition" $?
exit 1
fi
# Create LVM partition (using remaining space)
if ! sgdisk -n 3:0:0 -t 3:8E00 "$disk"; then
log_error "Failed to create LVM partition" $?
exit 1
fi
# Print partition table
sgdisk -p "$disk"
# Re-read partition table
partprobe "$disk"
}
setup_lvm() {
local disk="$1"
local password="$2" # Pass the encryption password as an argument
log_output "Setting up LVM on disk: $disk"
# Format EFI partition
if [[ $disk =~ nvme ]]; then
if ! mkfs.fat -F32 "${disk}p1"; then
log_error "Failed to format EFI partition" $?
exit 1
fi
else
if ! mkfs.fat -F32 "${disk}1"; then
log_error "Failed to format EFI partition" $?
exit 1
fi
fi
# Format boot partition
if [[ $disk =~ nvme ]]; then
if ! mkfs.ext4 "${disk}p2"; then
log_error "Failed to format boot partition" $?
exit 1
fi
else
if ! mkfs.ext4 "${disk}2"; then
log_error "Failed to format boot partition" $?
exit 1
fi
fi
# Setup encryption on partition 3 using LUKS
if [[ $disk =~ nvme ]]; then
if ! echo "$password" | cryptsetup luksFormat "${disk}p3"; then
log_error "Failed to format LUKS partition" $?
exit 1
fi
# Open LUKS partition
if ! echo "$password" | cryptsetup open --type luks --batch-mode "${disk}p3" lvm; then
log_error "Failed to open LUKS partition" $?
exit 1
fi
else
if ! echo "$password" | cryptsetup luksFormat "${disk}3"; then
log_error "Failed to format LUKS partition" $?
exit 1
fi
# Open LUKS partition
if ! echo "$password" | cryptsetup open --type luks --batch-mode "${disk}3" lvm; then
log_error "Failed to open LUKS partition" $?
exit 1
fi
fi
# Create physical volume for LVM on partition 3 with data alignment 1m
if ! pvcreate /dev/mapper/lvm; then
log_error "Failed to create physical volume" $?
exit 1
fi
# Create volume group called volgroup0 on partition 3
if ! vgcreate volgroup0 /dev/mapper/lvm; then
log_error "Failed to create volume group" $?
exit 1
fi
# Get logical volume sizes from the user
get_lv_sizes() {
read -r -p "Enter root logical volume size (e.g., 50G, 200G): " root_lv_size
# You might want to add validation here for $root_lv_size
export ROOT_LV_SIZE="$root_lv_size"
log_output "Root logical volume size: $ROOT_LV_SIZE"
}
get_lv_sizes
# Create logical volumes (lv_home will use remaining space)
if ! lvcreate -L "$ROOT_LV_SIZE" volgroup0 -n lv_root || \
! lvcreate -l 100%FREE volgroup0 -n lv_home; then
log_error "Failed to create logical volumes" $?
exit 1
fi
# Load kernel module
modprobe dm_mod
# Scan system for volume groups
vgscan
# Activate volume group
if ! vgchange -ay; then
log_error "Failed to activate volume group" $?
exit 1
fi
# Format and mount root volume
if ! mkfs.ext4 /dev/volgroup0/lv_root; then
log_error "Failed to format root volume" $?
exit 1
fi
if ! mount /dev/volgroup0/lv_root /mnt; then
log_error "Failed to mount root volume" $?
exit 1
fi
# Create /boot directory and mount partition 2
if ! mkdir -p /mnt/boot; then
log_error "Failed to create /boot directory" $?
exit 1
fi
if [[ $disk =~ nvme ]]; then
if ! mount "${disk}p2" /mnt/boot; then
log_error "Failed to mount /boot" $?
exit 1
fi
else
if ! mount "${disk}2" /mnt/boot; then
log_error "Failed to mount /boot" $?
exit 1
fi
fi
# Create /boot/EFI directory and mount partition 1
if ! mkdir -p /mnt/boot/EFI; then
log_error "Failed to create /boot/EFI directory" $?
exit 1
fi
if [[ $disk =~ nvme ]]; then
if ! mount "${disk}p1" /mnt/boot/EFI; then
log_error "Failed to mount /boot/EFI" $?
exit 1
fi
else
if ! mount "${disk}1" /mnt/boot/EFI; then
log_error "Failed to mount /boot/EFI" $?
exit 1
fi
fi
# Format home volume
if ! mkfs.ext4 /dev/volgroup0/lv_home; then
log_error "Failed to format home volume" $?
exit 1
fi
# Create /home directory
if ! mkdir -p /mnt/home; then
log_error "Failed to create /home directory" $?
exit 1
fi
# Mount home volume
if ! mount /dev/volgroup0/lv_home /mnt/home; then
log_error "Failed to mount /home" $?
exit 1
fi
# Ensure /mnt/etc exists
if ! mkdir -p /mnt/etc; then
log_error "Failed to create /mnt/etc directory" $?
exit 1
fi
}
# --- Timezone Selection ---
setup_timezone() {
log_output "Setting up timezone..."
# Function to get a list of timezones
get_timezones() {
local count=1
find /usr/share/zoneinfo -type f | sed 's|/usr/share/zoneinfo/||' | awk -v cnt=$count '{print cnt". "$0; cnt++}'
}
# Collect timezones into an array
mapfile -t timezones < <(get_timezones)
# Check if timezones were collected
if [ ${#timezones[@]} -eq 0 ]; then
log_error "No timezones found. Please check the timezone directory and try again." 1
exit 1
fi
# Constants
PAGE_SIZE=40
COLS=1 # Number of columns to display
NUMBER_WIDTH=4 # Width for number and dot
COLUMN_WIDTH=2 # Width of each column for timezones
# Function to display a page of timezones in columns
display_page() {
local start=$1
local end=$2 # Corrected this line
local count=0
echo "Timezones ($((start + 1)) to $end of ${#timezones[@]}):"
for ((i=start; i<end; i++)); do
# Print timezones in columns with minimized gap
printf "%-${NUMBER_WIDTH}s%-${COLUMN_WIDTH}s" "${timezones[$i]}" ""
count=$((count + 1))
if ((count % COLS == 0)); then
echo
fi
done
}
# Display pages of timezones
total_timezones=${#timezones[@]}
current_page=0
while true; do
start=$((current_page * PAGE_SIZE))
end=$((start + PAGE_SIZE))
if ((end > total_timezones)); then
end=$total_timezones
fi
display_page "$start" "$end"
# Prompt user for selection or continue
read -r -p "Enter the number of your timezone choice from this page, or press Enter to see more timezones: " choice
# Check if user made a choice
if [[ "$choice" =~ ^[0-9]+$ ]]; then
if ((choice >= 1 && choice <= total_timezones)); then
# Extract the selected timezone
selected_timezone=$(echo "${timezones[$((choice-1))]}" | awk '{print $2}')
# Set timezone
ln -sf /usr/share/zoneinfo/"$selected_timezone" /etc/localtime
# Verify timezone setting
log_output "Timezone has been set to $(readlink -f /etc/localtime)"
break # Exit the loop if a valid selection is made
else
echo "Invalid selection. Please enter a valid number from the displayed list."
fi
elif [[ -z "$choice" ]]; then # User pressed Enter, go to the next page
if ((end == total_timezones)); then # If this is the last page, loop back to the beginning
current_page=0
else
current_page=$((current_page + 1))
fi
else
echo "Invalid input. Please enter a number or press Enter to continue."
fi
done
}
configure_pacman() {
log_output "Configuring pacman..."
if ! sed -i "/^#Color/c\Color\nILoveCandy" /etc/pacman.conf || \
! sed -i "/^#VerbosePkgLists/c\VerbosePkgLists" /etc/pacman.conf || \
! sed -i "/^#ParallelDownloads/c\ParallelDownloads = 5" /etc/pacman.conf || \
! sed -i '/^#\[multilib\]/,+1 s/^#//' /etc/pacman.conf; then
log_error "Failed to configure pacman" $?
exit 1
fi
}
install_microcode() {
log_output "Installing microcode..."
proc_type=$(lscpu | grep -oP '^Vendor ID:\s+\K\w+')
if [ "$proc_type" = "GenuineIntel" ]; then
log_output "Installing Intel microcode"
if ! pacman -Sy --noconfirm --needed intel-ucode; then
log_error "Failed to install Intel microcode" $?
exit 1
fi
elif [ "$proc_type" = "AuthenticAMD" ]; then
log_output "Installing AMD microcode"
if ! pacman -Sy --noconfirm --needed amd-ucode; then
log_error "Failed to install AMD microcode" $?
exit 1
fi
fi
}
enable_services() {
log_output "Enabling services..."
if ! systemctl enable NetworkManager.service || \
! systemctl enable fstrim.timer; then
log_error "Failed to enable services" $?
exit 1
fi
}
set_locale() {
log_output "Setting locale..."
if ! sed -i 's/^#en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen || \
! locale-gen || \
! echo 'LANG=en_US.UTF-8' > /etc/locale.conf; then
log_error "Failed to set locale" $?
exit 1
fi
}
update_initramfs() {
log_output "Updating initramfs..."
if ! sed -i 's/^HOOKS\s*=\s*(.*)/HOOKS=(base udev autodetect modconf block encrypt lvm2 filesystems keyboard fsck)/' /etc/mkinitcpio.conf || \
! mkinitcpio -p linux; then
log_error "Failed to update initramfs" $?
exit 1
fi
}
# --- User Input Functions ---
get_username() {
while true; do
read -r -p "Enter a username: " username
if ! validate_username "$username"; then
continue # No need to log here, validate_username already logs
fi
export USERNAME="$username"
log_output "Username set to: $USERNAME"
break
done
}
get_user_password() { # Renamed to avoid conflict with the existing get_password function
while true; do
read -rs -p "Set a password for $USERNAME: " USER_PASSWORD1
echo
read -rs -p "Confirm password: " USER_PASSWORD2
echo
if [[ "$USER_PASSWORD1" != "$USER_PASSWORD2" ]]; then
log_error "Passwords do not match." 1
continue
fi
export USER_PASSWORD="$USER_PASSWORD1"
log_output "Password set for $USERNAME successfully."
break
done
}
get_root_password() {
while true; do
read -rs -p "Set root password: " ROOT_PASSWORD1
echo
read -rs -p "Confirm root password: " ROOT_PASSWORD2
echo
if [[ "$ROOT_PASSWORD1" != "$ROOT_PASSWORD2" ]]; then
log_error "Passwords do not match." 1
continue
fi
export ROOT_PASSWORD="$ROOT_PASSWORD1"
log_output "Root password set successfully."
break
done
}
get_hostname() {
while true; do
read -r -p "Enter a hostname: " hostname
if ! validate_hostname "$hostname"; then
continue
fi
export HOSTNAME="$hostname"
log_output "Hostname set to: $HOSTNAME"
break
done
}
create_user() {
local username="$1"
log_output "Creating user: $username"
if ! useradd -m -G wheel,power,storage,uucp,network -s /bin/bash "$username"; then
log_error "Failed to create user" $?
exit 1
fi
}
set_passwords() {
log_output "Setting passwords..."
# Make sure USERNAME and PASSWORD are exported before calling this function
if ! echo "$USERNAME:$USER_PASSWORD" | chpasswd || \
! echo "root:$ROOT_PASSWORD" | chpasswd; then # Assuming ROOT_PASSWORD is exported
log_error "Failed to set passwords" $?
exit 1
fi
}
set_hostname() {
local hostname="$1"
log_output "Setting hostname: $hostname"
if ! echo "$hostname" > /etc/hostname; then
log_error "Failed to set hostname" $?
exit 1
fi
}
update_sudoers() {
log_output "Updating sudoers..."
if ! cp /etc/sudoers /etc/sudoers.backup || \
! sed -i 's/^# *%wheel ALL=(ALL:ALL) ALL/%wheel ALL=(ALL:ALL) ALL/' /etc/sudoers || \
! echo 'Defaults targetpw' >> /etc/sudoers || \
! visudo -c; then
log_error "Failed to update sudoers" $?
# Restore backup if visudo fails
cp /etc/sudoers.backup /etc/sudoers
exit 1
fi
}
install_grub() {
log_output "Installing GRUB..."
if ! grub-install --target=x86_64-efi --bootloader-id=grub_uefi --recheck; then
log_error "Failed to install GRUB" $?
exit 1
fi
}
configure_grub() {
log_output "Configuring GRUB..."
# Make sure DISK is exported and available in the environment
if [[ $disk =~ nvme ]]; then
if ! sed -i '/^GRUB_DEFAULT=/c\GRUB_DEFAULT=saved' /etc/default/grub || \
! sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet"/c\GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice='"$DISK"'p3:volgroup0 loglevel=3"' /etc/default/grub || \
! sed -i '/^#GRUB_ENABLE_CRYPTODISK=y/c\GRUB_ENABLE_CRYPTODISK=y' /etc/default/grub || \
! sed -i '/^#GRUB_SAVEDEFAULT=true/c\GRUB_SAVEDEFAULT=true' /etc/default/grub || \
! cp /usr/share/locale/en\@quot/LC_MESSAGES/grub.mo /boot/grub/locale.en.mo || \
! grub-mkconfig -o /boot/grub/grub.cfg; then
log_error "Failed to configure GRUB" $?
exit 1
fi
else
if ! sed -i '/^GRUB_DEFAULT=/c\GRUB_DEFAULT=saved' /etc/default/grub || \
! sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet"/c\GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice='"$DISK"'3:volgroup0 loglevel=3"' /etc/default/grub || \
! sed -i '/^#GRUB_ENABLE_CRYPTODISK=y/c\GRUB_ENABLE_CRYPTODISK=y' /etc/default/grub || \
! sed -i '/^#GRUB_SAVEDEFAULT=true/c\GRUB_SAVEDEFAULT=true' /etc/default/grub || \
! cp /usr/share/locale/en\@quot/LC_MESSAGES/grub.mo /boot/grub/locale.en.mo || \
! grub-mkconfig -o /boot/grub/grub.cfg; then
log_error "Failed to configure GRUB" $?
exit 1
fi
}
install_nvidia_drivers() {
log_output "Detecting NVIDIA GPUs..."
# Detect NVIDIA GPUs
readarray -t dGPU < <(lspci -k | grep -E "(VGA|3D)" | grep -i nvidia)
# Check if any NVIDIA GPUs were found
if [ ${#dGPU[@]} -gt 0 ]; then
log_output "NVIDIA GPU(s) detected:"
for gpu in "${dGPU[@]}"; do
log_output " $gpu"
done
log_output "Installing NVIDIA drivers..."
# Install NVIDIA drivers and related packages
if ! pacman -Sy --noconfirm --needed nvidia libglvnd nvidia-utils opencl-nvidia lib32-libglvnd lib32-nvidia-utils lib32-opencl-nvidia nvidia-settings; then
log_error "Failed to install NVIDIA packages" $?
exit 1
fi
# Add NVIDIA modules to initramfs
if ! sed -i '/^MODULES=()/c\MODULES=(nvidia nvidia_modeset nvidia_uvm nvidia_drm)' /etc/mkinitcpio.conf || \
! mkinitcpio -p linux; then
log_error "Failed to update initramfs with NVIDIA modules" $?
exit 1
fi
# Update GRUB configuration with NVIDIA settings
# Make sure DISK is exported and available in the environment
if [[ $disk =~ nvme ]]; then
if ! sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice=\/dev\/'"$DISK"'p3:volgroup0 loglevel=3"/c\GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice=\/dev\/'"$DISK"'p3:volgroup0 nvidia_drm_modeset=1 loglevel=3"' /etc/default/grub || \
! grub-mkconfig -o /boot/grub/grub.cfg; then
log_error "Failed to update GRUB configuration with NVIDIA settings" $?
exit 1
fi
else
fi ! sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice=\/dev\/'"$DISK"'3:volgroup0 loglevel=3"/c\GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice=\/dev\/'"$DISK"'3:volgroup0 nvidia_drm_modeset=1 loglevel=3"' /etc/default/grub || \
! grub-mkconfig -o /boot/grub/grub.cfg; then
log_error "Failed to update GRUB configuration with NVIDIA settings" $?
exit 1
fi
fi
else
log_output "No NVIDIA GPUs detected. Skipping NVIDIA driver installation."
fi
}
install_prerequisites() {
log_output "Installing prerequisite packages..."
if ! pacman -Sy --noconfirm --needed pacman-contrib reflector rsync; then
log_error "Failed to install prerequisite packages" $?
exit 1
fi
}
configure_mirrors() {
log_output "Configuring pacman mirrors for faster downloads..."
if ! cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.backup || \
! reflector -a 48 -f 5 -l 20 --sort rate --save /etc/pacman.d/mirrorlist; then
log_error "Failed to configure pacman mirrors" $?
exit 1
fi
}
install_base_packages() {
log_output "Installing base packages using pacstrap..."
if ! pacstrap -K /mnt base linux linux-firmware linux-headers --noconfirm --needed; then
log_error "Failed to install base packages" $?
exit 1
fi
}
install_additional_packages() {
log_output "Installing additional packages..."
if ! pacman -Sy --noconfirm --needed - < ./pkgs.lst; then
log_error "Failed to install additional packages" $?
exit 1
fi
}
# --- Desktop Environment ---
select_gui() {
log_output "Selecting GUI..."
options=("Server (No GUI)" "GNOME" "KDE Plasma")
select gui_choice in "${options[@]}"; do
case "$gui_choice" in
"GNOME")
export GUI_CHOICE="gnome"
log_output "GNOME selected."
;;
"KDE Plasma")
export GUI_CHOICE="kde"
log_output "KDE Plasma selected."
;;
*)
export GUI_CHOICE="none"
log_output "No GUI selected."
;;
esac
break
done
}
install_gui() {
if [[ "$GUI_CHOICE" == "gnome" ]]; then
log_output "Installing GNOME desktop environment..."
if ! pacman -Sy --noconfirm --needed gnome gnome-extra gnome-tweaks gnome-shell-extensions gnome-browser-connector firefox; then
log_error "Failed to install GNOME packages" $?
exit 1
fi
if ! systemctl enable gdm.service; then
log_error "Failed to enable gdm service" $?
exit 1
fi
log_output "GNOME installed and gdm enabled."
elif [[ "$GUI_CHOICE" == "kde" ]]; then
log_output "Installing KDE Plasma desktop environment..."
if ! pacman -Sy --noconfirm --needed xorg plasma-desktop sddm kde-applications dolphin firefox lxappearance; then
log_error "Failed to install KDE Plasma packages" $?
exit 1
fi
if ! systemctl enable sddm.service; then
log_error "Failed to enable sddm service" $?
exit 1
fi
log_output "KDE Plasma installed and sddm enabled."
else
log_output "No GUI selected. Skipping GUI installation."
fi
}
# --- AUR Helper ---
get_aur_helper() {
log_output "Selecting AUR helper..."
# Ask the user if they want to install an AUR helper
if ! confirm_action "Do you want to install an AUR helper?"; then
log_output "Skipping AUR helper installation."
export AUR_HELPER="none"
return 0
fi
# Ask the user which AUR helper they want
options=("paru" "yay" "none")
select aur_helper in "${options[@]}"; do
case "$aur_helper" in
paru)
export AUR_HELPER="paru"
log_output "paru selected."
;;
yay)
export AUR_HELPER="yay"
log_output "yay selected."
;;
none)
export AUR_HELPER="none"
log_output "No AUR helper selected."
;;
*)
log_output "Invalid option. Skipping AUR helper installation."
export AUR_HELPER="none"
exit 1 # Exit the script if the option is invalid
;;
esac
break
done
}
install_aur_helper() {
log_output "Installing AUR helper..."
# Temporarily allow the user to run sudo without a password
echo "$USERNAME ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
# Switch to the created user
if ! runuser -u "$USERNAME" -- /bin/bash -c "
# Install git if not already installed
if ! pacman -Qi git &> /dev/null; then
if ! sudo pacman -S --noconfirm git; then
log_error \"Failed to install git\" 3
exit 3
fi
fi
# Install the chosen AUR helper
case \"$AUR_HELPER\" in
yay)
mkdir -p tmp
cd tmp && git clone https://aur.archlinux.org/yay.git || { log_error \"Failed to clone yay repository\" 4; exit 4; }
cd yay && makepkg -si --noconfirm -C yay || { log_error \"Failed to build and install yay\" 5; exit 5; }
;;
paru)
mkdir -p tmp
cd tmp && git clone https://aur.archlinux.org/paru.git || { log_error \"Failed to clone paru repository\" 6; exit 6; }
cd paru && makepkg -si --noconfirm -C paru || { log_error \"Failed to build and install paru\" 7; exit 7; }
;;
*)
log_error \"Invalid AUR helper specified\" 8
exit 8
;;
esac
"; then
log_error "Failed to switch to user" 9
return 9
fi
# Remove the temporary sudoers entry
sed -i "/$USERNAME ALL=(ALL) NOPASSWD: ALL/d" /etc/sudoers
log_output "AUR helper installed."
}
# --- Cleanup Function ---
cleanup() {
log_output "Cleaning up..."
# Remove temporary files and directories created during the installation
rm -rf /mnt/global_functions.sh
rm -rf /mnt/chroot.sh
rm -rf /mnt/tmp
# Copy log files to the installed system
cp /var/log/arch_install.log /mnt/var/log/arch_install.log
cp /var/log/arch_install_error.log /mnt/var/log/arch_install_error.log
}
Offline
I only checked the script very quickly but you need to read this:
Para todos todo, para nosotros nada
Offline
I only checked the script very quickly but you need to read this:
Thank you for your response and taking a look for me. I apologize in advance if my question is dumb or elementary to those who are more experienced in Arch than myself... but I don't seem to understand the connection between my use of pacman and my issue. I only ask because your link directly opens to section 3.3 of that article so I assume that something caught your eye regarding my use of pacman. Can you please give me some context? I did read the entire page but don't want to change things blindly without understanding what you're hinting at.
I was able to get Arch installed on baremetal with my script when selecting a NVMe drive using my thought from last night but now I just need to make sure /etc/default/grub is being updated correctly as grub was unable to find /dev/mapper/volgroup0-lv_root. I suspect the conditional logic didn't work right with "sed -i" or I made a typo somewhere.
Offline
Update. After some testing and commenting out the "cleanup" function, and "umount -R /mnt" I found that the cryptdevice was set to "/dev/nvme0n13:volgroup0” rather than "/dev/nvme0n1p3:volgroup0"
I suppose this could be easily avoided by using UUID over absolute path.
Offline
I don't seem to understand the connection between my use of pacman and my issue
I just noticed the script made use of `pacman -Sy` several times, which is thoroughly bad practice. I have no comment about your issue because I posted just before leaving for $DAY_JOB and I didn't have time to read everything (sorry).
Para todos todo, para nosotros nada
Offline
live4thamuzik wrote:I don't seem to understand the connection between my use of pacman and my issue
I just noticed the script made use of `pacman -Sy` several times, which is thoroughly bad practice. I have no comment about your issue because I posted just before leaving for $DAY_JOB and I didn't have time to read everything (sorry).
That makes sense. I will correct the excessive use of pacman -Sy. Thanks again!
UPDATE:
I changed all subordinate pacman -Sy commands to pacman -S. At this time only "install_prerequisites" uses the -Sy flag as it is the very first time pacman is used in the script.
As far as the issue in OP - I looks like my use of the sed -i command to update /etc/default/grub was the reason for the "p" not being added. I adjusted that code from
old
configure_grub() {
log_output "Configuring GRUB..."
# Make sure DISK is exported and available in the environment
if [[ $disk =~ nvme ]]; then
if ! sed -i '/^GRUB_DEFAULT=/c\GRUB_DEFAULT=saved' /etc/default/grub || \
! sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet"/c\GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice='"$DISK"'p3:volgroup0 loglevel=3"' /etc/default/grub || \
! sed -i '/^#GRUB_ENABLE_CRYPTODISK=y/c\GRUB_ENABLE_CRYPTODISK=y' /etc/default/grub || \
! sed -i '/^#GRUB_SAVEDEFAULT=true/c\GRUB_SAVEDEFAULT=true' /etc/default/grub || \
! cp /usr/share/locale/en\@quot/LC_MESSAGES/grub.mo /boot/grub/locale.en.mo || \
! grub-mkconfig -o /boot/grub/grub.cfg; then
log_error "Failed to configure GRUB" $?
exit 1
fi
else
if ! sed -i '/^GRUB_DEFAULT=/c\GRUB_DEFAULT=saved' /etc/default/grub || \
! sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet"/c\GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice='"$DISK"'3:volgroup0 loglevel=3"' /etc/default/grub || \
! sed -i '/^#GRUB_ENABLE_CRYPTODISK=y/c\GRUB_ENABLE_CRYPTODISK=y' /etc/default/grub || \
! sed -i '/^#GRUB_SAVEDEFAULT=true/c\GRUB_SAVEDEFAULT=true' /etc/default/grub || \
! cp /usr/share/locale/en\@quot/LC_MESSAGES/grub.mo /boot/grub/locale.en.mo || \
! grub-mkconfig -o /boot/grub/grub.cfg; then
log_error "Failed to configure GRUB" $?
exit 1
fi
fi
}
install_nvidia_drivers() {
log_output "Detecting NVIDIA GPUs..."
# Detect NVIDIA GPUs
readarray -t dGPU < <(lspci -k | grep -E "(VGA|3D)" | grep -i nvidia)
# Check if any NVIDIA GPUs were found
if [ ${#dGPU[@]} -gt 0 ]; then
log_output "NVIDIA GPU(s) detected:"
for gpu in "${dGPU[@]}"; do
log_output " $gpu"
done
log_output "Installing NVIDIA drivers..."
# Install NVIDIA drivers and related packages
if ! pacman -S --noconfirm --needed nvidia libglvnd nvidia-utils opencl-nvidia lib32-libglvnd lib32-nvidia-utils lib32-opencl-nvidia nvidia-settings; then
log_error "Failed to install NVIDIA packages" $?
exit 1
fi
# Add NVIDIA modules to initramfs
if ! sed -i '/^MODULES=()/c\MODULES=(nvidia nvidia_modeset nvidia_uvm nvidia_drm)' /etc/mkinitcpio.conf || \
! mkinitcpio -p linux; then
log_error "Failed to update initramfs with NVIDIA modules" $?
exit 1
fi
# Update GRUB configuration with NVIDIA settings
if [[ $DISK =~ nvme ]]; then
if ! sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice=\/dev\/'"$DISK"'p3:volgroup0 loglevel=3"/c\GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice=\/dev\/'"$DISK"'p3:volgroup0 nvidia_drm_modeset=1 loglevel=3"' /etc/default/grub || \
! grub-mkconfig -o /boot/grub/grub.cfg; then
log_error "Failed to update GRUB configuration with NVIDIA settings" $?
fi
else
if ! sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice=\/dev\/'"$DISK"'3:volgroup0 loglevel=3"/c\GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice=\/dev\/'"$DISK"'3:volgroup0 nvidia_drm_modeset=1 loglevel=3"' /etc/default/grub || \
! grub-mkconfig -o /boot/grub/grub.cfg; then
log_error "Failed to update GRUB configuration with NVIDIA settings" $?
fi
fi
else
log_output "No NVIDIA GPUs detected. Skipping NVIDIA driver installation."
fi
}
new # The change is subtle but I moved "p3" inside single quotes
configure_grub() {
log_output "Configuring GRUB..."
# Make sure DISK is exported and available in the environment
if [[ $disk =~ nvme ]]; then
if ! sed -i '/^GRUB_DEFAULT=/c\GRUB_DEFAULT=saved' /etc/default/grub || \
! sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet"/c\GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice='"$DISK"p3':volgroup0 loglevel=3"' /etc/default/grub || \
! sed -i '/^#GRUB_ENABLE_CRYPTODISK=y/c\GRUB_ENABLE_CRYPTODISK=y' /etc/default/grub || \
! sed -i '/^#GRUB_SAVEDEFAULT=true/c\GRUB_SAVEDEFAULT=true' /etc/default/grub || \
! cp /usr/share/locale/en\@quot/LC_MESSAGES/grub.mo /boot/grub/locale.en.mo || \
! grub-mkconfig -o /boot/grub/grub.cfg; then
log_error "Failed to configure GRUB" $?
exit 1
fi
else
if ! sed -i '/^GRUB_DEFAULT=/c\GRUB_DEFAULT=saved' /etc/default/grub || \
! sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet"/c\GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice='"$DISK"'3:volgroup0 loglevel=3"' /etc/default/grub || \
! sed -i '/^#GRUB_ENABLE_CRYPTODISK=y/c\GRUB_ENABLE_CRYPTODISK=y' /etc/default/grub || \
! sed -i '/^#GRUB_SAVEDEFAULT=true/c\GRUB_SAVEDEFAULT=true' /etc/default/grub || \
! cp /usr/share/locale/en\@quot/LC_MESSAGES/grub.mo /boot/grub/locale.en.mo || \
! grub-mkconfig -o /boot/grub/grub.cfg; then
log_error "Failed to configure GRUB" $?
exit 1
fi
fi
}
install_nvidia_drivers() {
log_output "Detecting NVIDIA GPUs..."
# Detect NVIDIA GPUs
readarray -t dGPU < <(lspci -k | grep -E "(VGA|3D)" | grep -i nvidia)
# Check if any NVIDIA GPUs were found
if [ ${#dGPU[@]} -gt 0 ]; then
log_output "NVIDIA GPU(s) detected:"
for gpu in "${dGPU[@]}"; do
log_output " $gpu"
done
log_output "Installing NVIDIA drivers..."
# Install NVIDIA drivers and related packages
if ! pacman -S --noconfirm --needed nvidia libglvnd nvidia-utils opencl-nvidia lib32-libglvnd lib32-nvidia-utils lib32-opencl-nvidia nvidia-settings; then
log_error "Failed to install NVIDIA packages" $?
exit 1
fi
# Add NVIDIA modules to initramfs
if ! sed -i '/^MODULES=()/c\MODULES=(nvidia nvidia_modeset nvidia_uvm nvidia_drm)' /etc/mkinitcpio.conf || \
! mkinitcpio -p linux; then
log_error "Failed to update initramfs with NVIDIA modules" $?
exit 1
fi
# Update GRUB configuration with NVIDIA settings
if [[ $DISK =~ nvme ]]; then
if ! sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice=\/dev\/'"$DISK"p3':volgroup0 loglevel=3"/c\GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice=\/dev\/'"$DISK"p3':volgroup0 nvidia_drm_modeset=1 loglevel=3"' /etc/default/grub || \
! grub-mkconfig -o /boot/grub/grub.cfg; then
log_error "Failed to update GRUB configuration with NVIDIA settings" $?
fi
else
if ! sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice=\/dev\/'"$DISK"'3:volgroup0 loglevel=3"/c\GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice=\/dev\/'"$DISK"'3:volgroup0 nvidia_drm_modeset=1 loglevel=3"' /etc/default/grub || \
! grub-mkconfig -o /boot/grub/grub.cfg; then
log_error "Failed to update GRUB configuration with NVIDIA settings" $?
fi
fi
else
log_output "No NVIDIA GPUs detected. Skipping NVIDIA driver installation."
fi
}
I intend to move to using UUID still but it looks like I cannot avoid the use of conditional logic. So i figured it made more sense to resolve the existing issue rather than trying the same logic with blkid to pull the UUID from ${DISK}3 or ${DISK}p3
Last edited by live4thamuzik (2024-11-22 21:23:55)
Offline
Tried to run your latest script . Just downloaded it.
I tried to install on a usb flash drive. /dev/sda
I have no experience with luks. Hope I answered the questions correctly.
I got this error:
warning: rsync-3.3.0-2 is up to date -- skipping
2024-11-22 17:17:16 - Error: Failed to install prerequisite packages (exit code: 0)
I might not be the one to test this.
Online
Tried to run your latest script . Just downloaded it.
I tried to install on a usb flash drive. /dev/sda
I have no experience with luks. Hope I answered the questions correctly.
I got this error:warning: rsync-3.3.0-2 is up to date -- skipping 2024-11-22 17:17:16 - Error: Failed to install prerequisite packages (exit code: 0)
I might not be the one to test this.
Oh, that's interesting! I've never tried to install on a usb stick. I will dig into that when I finish testing the NVMe support. Thank you!
Offline
Sorry for not posting the solution earlier but I solved the problem with GRUB finding the LUKS partition on NVMe drives by reworking the logic a little bit and correcting my sed command.
configure_grub() {
log_output "Configuring GRUB..."
# Make sure DISK is exported and available in the environment
if [[ $DISK == "/dev/nvme"* ]]; then
PART_PREFIX="p"
else
PART_PREFIX=""
fi
if ! sed -i '/^GRUB_DEFAULT=/c\GRUB_DEFAULT=saved' /etc/default/grub || \
! sed -i '/^GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet"/c\GRUB_CMDLINE_LINUX_DEFAULT="quiet cryptdevice='${DISK}${PART_PREFIX}'3:volgroup0 loglevel=3"' /etc/default/grub || \
! sed -i '/^#GRUB_ENABLE_CRYPTODISK=y/c\GRUB_ENABLE_CRYPTODISK=y' /etc/default/grub || \
! sed -i '/^#GRUB_SAVEDEFAULT=true/c\GRUB_SAVEDEFAULT=true' /etc/default/grub || \
! cp /usr/share/locale/en\@quot/LC_MESSAGES/grub.mo /boot/grub/locale.en.mo || \
! grub-mkconfig -o /boot/grub/grub.cfg; then
log_error "Failed to configure GRUB" $?
exit 1
fi
}
I have one more small issue with the script not updating /etc/default/grub after installing nvidia drivers but I'll start a new thread for that if I can't sort it out on my own.
Offline
Why do you (think you) need
pacman -Sy
at all?
CLI Paste | How To Ask Questions
Arch Linux | x86_64 | GPT | EFI boot | refind | stub loader | systemd | LVM2 on LUKS
Lenovo x270 | Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz | Intel Wireless 8265/8275 | US keyboard w/ Euro | 512G NVMe INTEL SSDPEKKF512G7L
Offline
Why do you (think you) need
pacman -Sy
at all?
Well, considering it is an install script and it could be used by anyone that finds it on github... there is a good possibility that they may not be installing from the "latest and greatest" release. So with that in mind, it is a good idea to let pacman reach out to see if there are newer packages.
Secondly, if you read the script, you'd see that /etc/pacman.conf is modified to add in multilib support. Not using pacman -Sy will prevent any 32-bit packages from being found and installed as the repo would not be updated. Also, the script detects if the CPU is AMD or Intel. Pacman will not install the microcode without using the -Sy flag. I tested the script without it and the error explicitly stated to run "pacman -Sy" to install the microcode.
Last edited by live4thamuzik (2024-12-12 03:17:51)
Offline
Use this instead:
pacman -Syu amd-ucode
Para todos todo, para nosotros nada
Offline