#!/usr/bin/env bash # This script will ask users about their prefrences # like disk, file system, timezone, keyboard layout, # user name, password, etc. # shellcheck disable=SC2207,SC2120 SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" # Set up a config file CONFIG_FILE=$SCRIPT_DIR/setup.conf # Check if file exists and remove it if it does [[ -f "$CONFIG_FILE" ]] && rm -f "$CONFIG_FILE" # Set options in setup.conf set_option() { # Check if option exists if grep -Eq "^${1}.*" "$CONFIG_FILE"; then # delete option if exists sed -i -e "/^${1}.*/d" "$CONFIG_FILE" fi # Else add option echo "${1}=${2}" >> "$CONFIG_FILE" } # Adding global functions and variables to use in this script # Check for root user check_root() { if [[ "$(id -u)" != "0" ]]; then echo -ne "ERROR! This script has to be run under the 'root' user!" exit 1 fi } # Check if distro is arch check_arch() { if [[ ! -e /etc/arch-release ]]; then echo -ne "ERROR! This script has to be run under Arch Linux!" exit 1 fi } # Check for internet connection connection_test() { ping -q -w 1 -c 1 "$(ip r | grep default | awk 'NR==1 {print $3}')" &>/dev/null && return 1 || return 0 } # Check coutry for mirrorlist check_country () { _ISO=$(curl --fail https://ifconfig.co/country-iso) set_option "ISO" "$_ISO" } # Install fonts install_font () { pacman -S --noconfirm --needed terminus-font } # timedatectl set-ntp true set_ntp () { timedatectl set-ntp true } # Check for UEFI efi_check () { if [[ -d "/sys/firmware/efi/" ]]; then if (mount | grep /sys/firmware/efi/efivars); then mount -t efivarfs efivarfs /sys/firmware/efi/efivars fi # UEFI detected set_option "UEFI" 1 else # No UEFI detected set_option "UEFI" 0 fi } # Check if an element exists elements_present() { for e in "${@:2}"; do [[ "$e" == "$1" ]] && break; done } # Invalid option message invalid_option() { echo -ne "Please select a valid option: \n" } # Password helper function set_password() { # Read password without echoing (-s) read -rs -p "Please enter password: " PASSWORD1 echo -ne "\n" read -rs -p "Please re-enter password: " PASSWORD2 echo -ne "\n" if [[ "$PASSWORD1" == "$PASSWORD2" ]]; then set_option "$1" "$PASSWORD1" else echo -ne "Passwords do not match \n" return fi } # Make a title title () { echo -ne "\n" echo -ne "------------------------------------------------------------------------\n" echo -ne "\t\t\t\"$1\"\n" echo -ne "------------------------------------------------------------------------\n" } # Write shared functions to to setup.conf write_to_config() { cat << EOF > "$CONFIG_FILE" #!/usr/bin/env bash title () { echo -ne "\n" echo -ne "------------------------------------------------------------------------\n" echo -ne "\t\t\t\$1\n" echo -ne "------------------------------------------------------------------------\n" } install_pkg () { pacman -S --noconfirm --needed "$@" } refresh_pacman() { pacman -Syy } # Setup for logging LOG="${SCRIPT_DIR}/main.log" [[ -f $LOG ]] && rm -f "$LOG" logo () { echo -ne " ------------------------------------------------------------------------- █████╗ ██████╗ ██████╗██╗ ██╗████████╗██╗████████╗██╗ ██╗███████╗ ██╔══██╗██╔══██╗██╔════╝██║ ██║╚══██╔══╝██║╚══██╔══╝██║ ██║██╔════╝ ███████║██████╔╝██║ ███████║ ██║ ██║ ██║ ██║ ██║███████╗ ██╔══██║██╔══██╗██║ ██╔══██║ ██║ ██║ ██║ ██║ ██║╚════██║ ██║ ██║██║ ██║╚██████╗██║ ██║ ██║ ██║ ██║ ╚██████╔╝███████║ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝ " } EOF } # Ask user for option PROMPT="Please enter your option: " # This will be shown on every set as user is progressing logo () { echo -ne " ------------------------------------------------------------------------- █████╗ ██████╗ ██████╗██╗ ██╗████████╗██╗████████╗██╗ ██╗███████╗ ██╔══██╗██╔══██╗██╔════╝██║ ██║╚══██╔══╝██║╚══██╔══╝██║ ██║██╔════╝ ███████║██████╔╝██║ ███████║ ██║ ██║ ██║ ██║ ██║███████╗ ██╔══██║██╔══██╗██║ ██╔══██║ ██║ ██║ ██║ ██║ ██║╚════██║ ██║ ██║██║ ██║╚██████╗██║ ██║ ██║ ██║ ██║ ╚██████╔╝███████║ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝ " } # Backround checks background_check () { if connection_test; then echo -ne "ERROR! There seems to be no internet connection.\n" exit 1 fi check_arch efi_check check_root set_ntp refresh_pacman check_country install_font setfont ter-v22b write_to_config } # Set partioning layouts set_partion_layout() { title "Setup Partioning Layout" LAYOUTS=("Default" "LVM" "LVM+LUKS" "Maintain Current") PS3="$PROMPT" select OPT in "${LAYOUTS[@]}"; do if elements_present "$OPT" "${LAYOUTS[@]}"; then case "$REPLY" in 1) set_option "LAYOUT" 1 break ;; 2) # set_option "LAYOUT" "$OPT" set_option "LVM" 1 set_option "LUKS" 0 break ;; 3) # set_option "LAYOUT" "$OPT" set_option "LUKS" 1 set_option "LVM" 1 set_password "LUKS_PASSWORD" break ;; 4) echo -ne "Maintaining current settings" set_option "LAYOUT" 0 break ;; *) invalid_option setpartionlayout ;; esac else invalid_option filesystem fi done } # This function will handle file systems. set_filesystem () { title "Setup File System" FILESYS=("btrfs" "ext2" "ext3" "ext4" "f2fs" "jfs" "nilfs2" "ntfs" "reiserfs" "vfat" "xfs") PS3="$PROMPT" select OPT in "${FILESYS[@]}"; do if elements_present "$OPT" "${FILESYS[@]}"; then if [ "$OPT" == "btrfs" ]; then # Used -a to get more than one argument echo -ne "Please enter your btrfs subvolumes separated by space\n" echo -ne "usualy they start with @ for root or @home, @temp etc.\n" echo -ne "Defaults are @, @home, @var, @tmp, @.snapshots \n" read -r -p "press enter to use default: " -a ARR if [[ -z "${ARR[*]}" ]]; then set_option "SUBVOLUMES" "(@ @home @var @tmp @.snapshots)" break else # An array is a list of values. NAMES=() for i in "${ARR[@]}"; do # push values to array NAMES+=("$i") done # Set to config file set_option "SUBVOLUMES" "(${NAMES[*]})" break fi fi set_option "FS" "$OPT" break else invalid_option break fi done } # Added this from arch wiki https://wiki.archlinux.org/title/System_time set_timezone () { title "Setup Time Zone" _TIMEZONE="$(curl --fail https://ipapi.co/timezone)" _ZONE=($(timedatectl list-timezones | sed 's/\/.*$//' | uniq)) echo -ne "System detected your timezone to be '$_TIMEZONE'" echo -ne "\n" read -r -p "Is this correct? yes/no: " ANSWER case "$ANSWER" in y|Y|yes|Yes|YES) set_option TIMEZONE "$_TIMEZONE" ;; n|N|no|NO|No) title "Manually setting timezone" PS3="$PROMPT" echo -ne "Please select your zone: \n" select ZONE in "${_ZONE[@]}"; do if elements_present "$ZONE" "${_ZONE[@]}"; then _SUBZONE=($(timedatectl list-timezones | grep "${ZONE}" | sed 's/^.*\///')) PS3="$PROMPT" echo -ne "Please select your subzone: \n" select SUBZONE in "${_SUBZONE[@]}"; do if elements_present "$SUBZONE" "${_SUBZONE[@]}"; then set_option "TIMEZONE" "${ZONE}/${SUBZONE}" break else invalid_option break fi done break else invalid_option break fi done ;; *) echo "Wrong option. Try again";timezone;; esac } # These are default key maps as presented in official arch repo archinstall set_keymap () { title "Setup Keymap" KEYMAPS=("by" "ca" "cf" "cz" "de" "dk" "es" "et" "fa" "fi" "fr" "gr" "hu" "il" "it" "lt" "lv" "mk" "nl" "no" "pl" "ro" "ru" "sg" "ua" "uk" "us") PS3="$PROMPT" select OPT in "${KEYMAPS[@]}"; do if elements_present "$OPT" "${KEYMAPS[@]}"; then set_option "KEYMAP" "$OPT" break else invalid_option keymap fi done } # Confirm if ssd is present ssd_drive () { title "SSD Drive Confirmation" read -r -p "Is this system using an SSD? yes/no: " _SSD case "$_SSD" in y|Y|yes|Yes|YES) set_option "SSD" 1 set_option "MOUNTOPTION" "noatime,compress=zstd,ssd,commit=120" ;; n|N|no|NO|No) set_option "SSD" 0 set_option "MOUNTOPTION" "noatime,compress=zstd,commit=120" ;; *) echo "Wrong option. Try again";ssddrive;; esac } # Selection for disk type disk_selection () { # show disks present on system title "Disk Selection" DISKLIST="$(lsblk -n --output TYPE,KNAME,SIZE | awk '$1=="disk"{print "/dev/"$2" - "$3}')" # show disks with /dev/ prefix and size PS3="$PROMPT" select _DISK in "${DISKLIST[@]}"; do if elements_present "$_DISK" "${DISKLIST[@]}"; then # remove size from string DISK=$(echo "$_DISK" | awk '{print $1}') set_option "DISK" "$DISK" break else invalid_option break fi done } user_info () { title "Add Your Information" read -r -p "Please enter your username: " USERNAME set_option "USERNAME" "${USERNAME,,}" # convert to lower case as in issue #109 set_password "PASSWORD" read -r -p "Please enter your hostname: " HOSTNAME set_option "HOSTNAME" "$HOSTNAME" } # Set locale setlocale (){ title "Setup Locale" LOCALES=($(grep UTF-8 /etc/locale.gen | sed 's/\..*$//' | sed '/@/d' | awk '{print $1}' | uniq | sed 's/#//g')) PS3="$PROMPT" select LOCALE in "${LOCALES[@]}"; do if elements_present "$LOCALE" "${LOCALES[@]}"; then set_option "LOCALE" "${LOCALE}.UTF-8 UTF-8" break else invalid_option break fi done } # Desktop selection set_desktop() { title "Select either desktop Environment or Window Manager" SELECTION=("KDE" "Gnome" "XFCE" "Mate" "LXQT" "Minimal" "Awesome" "OpenBox" "i3" "i3-Gaps") PS3="$PROMPT" select OPT in "${SELECTION[@]}"; do if elements_present "$OPT" "${SELECTION[@]}"; then case "$REPLY" in 1) # More packages can be added here set_option "DE" "('plasma')" set_option "DM" "sddm" break ;; 2) set_option "DE" "('gnome')" set_option "DM" "gdm" break ;; 3) set_option "DE" "('xfce4')" set_option "DM" "lightdm" break ;; 4) set_option "DE" "('mate')" set_option "DM" "lightdm" break ;; 5) set_option "DE" "('lxqt')" set_option "DM" "lightdm" break ;; 6) set_option "DE" 0 set_option "DM" 0 break ;; 7) set_option "DE" 0 set_option "WM" "awesome" break ;; 8) # openbox set_option "DE" 0 set_option "WM" "openbox" break ;; 9) # i3 set_option "DE" 0 set_option "WM" "i3" break ;; 10) # i3-gaps set_option "DE" 0 set_option "WM" "i3-gaps" break ;; *) echo "Wrong option. Try again" break ;; esac else invalid_option break fi done } # Make choice for installation make_choice () { title "Make your choice" CHOICE=("Default Install" "Custom Install") PS3="$PROMPT" select OPT in "${CHOICE[@]}"; do if elements_present "$OPT" "${CHOICE[@]}"; then case "$REPLY" in 1) clear logo title "Please select presetup \n\t\t\tsettings for your system" user_info disk_selection set_locale ssd_drive break ;; 2) user_info break ;; *) echo "Wrong option. Try again" break ;; esac else invalid_option break fi done } background_check clear logo make_choice