#!/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 } # if btrfs is selected set_btrfs() { # Used -a to get more than one argument echo "Please enter your btrfs subvolumes separated by space" echo "usualy they start with @ like @home, @temp etc." echo "Defaults are @home, @var, @tmp, @.snapshots" echo " " read -r -p "press enter to use default: " -a ARR if [[ -z "${ARR[*]}" ]]; then set_option "SUBVOLUMES" "(@ @home @var @tmp @.snapshots)" else # An array is a list of values. NAMES=(@) for i in "${ARR[@]}"; do # Check for user input for @ if [[ $i =~ [@] ]]; then # push values to array NAMES+=("$i") else NAMES+=(@"${i}") fi done # Check for duplicates IFS=" " read -r -a SUBS <<<"$(tr ' ' '\n' <<<"${NAMES[@]}" | sort -u | tr '\n' ' ')" # Set to config file set_option "SUBVOLUMES" "${SUBS[*]}" 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" set_password fi } # Make a title title() { echo -ne "\n" echo -ne "------------------------------------------------------------------------\n" echo -ne "\t\t\"$1\"\n" echo -ne "------------------------------------------------------------------------\n" } # Write shared functions to to setup.conf write_to_config() { cat <"$CONFIG_FILE" #!/usr/bin/env bash title () { echo -ne "\n" echo -ne "------------------------------------------------------------------------\n" echo -ne "\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 set_option "SCRIPT_DIR" "$SCRIPT_DIR" 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 set_partion_layout ;; esac else invalid_option set_partion_layout 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 set_btrfs break 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" set_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 set_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" ssd_drive ;; 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 set_locale() { 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 "Your system choice" CHOICE=("Default Install" "Custom Install") PS3="$PROMPT" echo "Default installation comprises of the settings and the packages used" echo "by Chris Titus himself. More specifically, it uses 3 partitions, GPT" echo "btrfs as file systems, KDE Plasma as desktop environment and sddm as " echo "window manager and package list is in 'pkg-files/pacman-pkgs.txt'." echo "While custom install allows you to choose your choices i.e. LVM, LUKS," echo "DE, WM, file systems and etc." echo " " 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 clear set_locale clear set_timezone set_keymap ssd_drive set_btrfs set_option "FS" "btrfs" set_option "DE" "plasma" set_option "DM" "sddm" set_option "LAYOUT" 1 break ;; 2) clear logo user_info disk_selection clear set_locale clear set_timezone set_keymap ssd_drive # Advance options set_partion_layout set_filesystem set_desktop break ;; *) echo "Wrong option. Try again" break ;; esac else invalid_option break fi done } background_check # write_to_config clear logo make_choice