622 lines
19 KiB
Bash
622 lines
19 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# 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
|
|
|
|
[[ -f "$CONFIG_FILE" ]] && rm -f "$CONFIG_FILE" >/dev/null 2>&1
|
|
|
|
set_option() {
|
|
if grep -Eq "^${1}.*" "$CONFIG_FILE"; then
|
|
sed -i -e "/^${1}.*/d" "$CONFIG_FILE"
|
|
fi
|
|
echo "${1}=${2}" >>"$CONFIG_FILE"
|
|
}
|
|
|
|
# Adding global functions and variables to use in this script
|
|
|
|
check_root() {
|
|
if [[ "$(id -u)" != "0" ]]; then
|
|
echo -ne "ERROR! This script must be running under the 'root' user!\n"
|
|
exit 0
|
|
fi
|
|
}
|
|
|
|
check_docker() {
|
|
if awk -F/ '$2 == "docker"' /proc/self/cgroup | read -r; then
|
|
echo -ne "ERROR! Docker container not supported (at the moment)\n"
|
|
exit 0
|
|
elif [[ -f /.dockerenv ]]; then
|
|
echo -ne "ERROR! Docker container not supported (at the moment)\n"
|
|
exit 0
|
|
fi
|
|
}
|
|
|
|
check_arch() {
|
|
if [[ ! -e /etc/arch-release ]]; then
|
|
echo -ne "ERROR! This script must be run in Arch Linux!\n"
|
|
exit 0
|
|
fi
|
|
}
|
|
|
|
check_pacman() {
|
|
if [[ -f /var/lib/pacman/db.lck ]]; then
|
|
echo "ERROR! Pacman is blocked."
|
|
echo -ne "If not running remove /var/lib/pacman/db.lck.\n"
|
|
exit 0
|
|
fi
|
|
}
|
|
|
|
connection_test() {
|
|
ping -q -w 1 -c 1 "$(ip r | grep default | awk 'NR==1 {print $3}')" &>/dev/null && return 1 || return 0
|
|
}
|
|
|
|
do_curl() {
|
|
_ISO=$(curl --fail https://ifconfig.co/country-iso)
|
|
set_option "ISO" "$_ISO"
|
|
}
|
|
|
|
set_ntp() {
|
|
timedatectl set-ntp true
|
|
}
|
|
|
|
efi_check() {
|
|
if [[ -d "/sys/firmware/efi/" ]]; then
|
|
if (mount | grep /sys/firmware/efi/efivars); then
|
|
(mount -t efivarfs efivarfs /sys/firmware/efi/efivars) >/dev/null 2>&1
|
|
fi
|
|
set_option "UEFI" 1
|
|
else
|
|
set_option "UEFI" 0
|
|
fi
|
|
}
|
|
|
|
set_btrfs() {
|
|
echo "Please enter your btrfs subvolumes separated by space"
|
|
echo "usualy they start with @."
|
|
echo "[like @home, default 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
|
|
NAMES=(@)
|
|
for i in "${ARR[@]}"; do
|
|
if [[ $i =~ [@] ]]; then
|
|
NAMES+=("$i")
|
|
else
|
|
NAMES+=(@"${i}")
|
|
fi
|
|
done
|
|
IFS=" " read -r -a SUBS <<<"$(tr ' ' '\n' <<<"${NAMES[@]}" | awk '!x[$0]++' | tr '\n' ' ')"
|
|
set_option "SUBVOLUMES" "${SUBS[*]}"
|
|
fi
|
|
}
|
|
|
|
set_lvm() {
|
|
read -r -p "Name your lvm volume group [like MyVolGroup, default is MyVolGroup]: " _VG
|
|
if [[ -z "$_VG" ]]; then
|
|
_VG="MyVolGroup"
|
|
fi
|
|
read -r -p "Enter number of partitions [like 2, default is 1]: " _PART_NUM
|
|
echo "Please make sure 1st partition is considered as root partition"
|
|
echo "And will be mounted at /mnt/ and other partitions will be mounted"
|
|
echo "at /mnt/partition_name by making a directory /mnt/partition_name"
|
|
|
|
i=1
|
|
_LVM_NAMES=()
|
|
LVM_SIZES=()
|
|
if [[ -z "$_PART_NUM" ]]; then
|
|
_PART_NUM=1
|
|
_LVM_NAMES+=("root")
|
|
# LVM_SIZES+=("100%FREE")
|
|
i=2
|
|
fi
|
|
while [[ $i -le "$_PART_NUM" ]]; do
|
|
if [[ "$_PART_NUM" -eq "1" ]]; then
|
|
read -r -p "Enter last partition name [like home]: " _LVM_NAME
|
|
_LVM_NAMES+=("$_LVM_NAME")
|
|
fi
|
|
read -r -p "Enter $i partition name [like root]: " _LVM_NAME
|
|
_LVM_NAMES+=("$_LVM_NAME")
|
|
read -r -p "Enter $i partition size [like 25G, 200M]: " _LVM_SIZE
|
|
LVM_SIZES+=("$_LVM_SIZE")
|
|
i=$((i + 1))
|
|
done
|
|
IFS=" " read -r -a LVM_NAMES <<<"$(tr ' ' '\n' <<<"${_LVM_NAMES[@]}" | awk '!x[$0]++' | tr '\n' ' ')"
|
|
set_option "LVM_VG" "$_VG"
|
|
set_option "LVM_PART_NUM" "$_PART_NUM"
|
|
set_option "LVM_NAMES" "(${LVM_NAMES[*]})"
|
|
set_option "LVM_SIZES" "(${LVM_SIZES[*]})"
|
|
}
|
|
|
|
elements_present() {
|
|
for e in "${@:2}"; do [[ "$e" == "$1" ]] && break; done
|
|
}
|
|
|
|
invalid_option() {
|
|
echo -ne "ERROR! Your selected option is invalid, retry \n"
|
|
}
|
|
|
|
set_password() {
|
|
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 "ERROR! Passwords do not match \n"
|
|
set_password
|
|
fi
|
|
}
|
|
|
|
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 <<EOF >"$CONFIG_FILE"
|
|
#!/usr/bin/env bash
|
|
|
|
title () {
|
|
echo -ne "\n"
|
|
echo -ne "------------------------------------------------------------------------\n"
|
|
echo -ne "\t\t\$1\n"
|
|
echo -ne "------------------------------------------------------------------------\n"
|
|
}
|
|
|
|
set_option() {
|
|
if grep -Eq "^\${1}.*" "\$CONFIG_FILE"; then
|
|
sed -i -e "/^\${1}.*/d" "\$CONFIG_FILE"
|
|
fi
|
|
echo "\${1}=\${2}" >>"\$CONFIG_FILE"
|
|
}
|
|
|
|
install_pkg () {
|
|
pacman -S --noconfirm --needed "\$@"
|
|
}
|
|
|
|
refresh_pacman() {
|
|
pacman -Sy --noconfirm
|
|
}
|
|
|
|
something_failed() {
|
|
echo "ERROR! Something is not right. Exiting.\n"
|
|
exit 0
|
|
}
|
|
|
|
logo () {
|
|
echo -ne "
|
|
------------------------------------------------------------------------
|
|
|
|
█████╗ ██████╗ ██████╗██╗ ██╗████████╗██╗████████╗██╗ ██╗███████╗
|
|
██╔══██╗██╔══██╗██╔════╝██║ ██║╚══██╔══╝██║╚══██╔══╝██║ ██║██╔════╝
|
|
███████║██████╔╝██║ ███████║ ██║ ██║ ██║ ██║ ██║███████╗
|
|
██╔══██║██╔══██╗██║ ██╔══██║ ██║ ██║ ██║ ██║ ██║╚════██║
|
|
██║ ██║██║ ██║╚██████╗██║ ██║ ██║ ██║ ██║ ╚██████╔╝███████║
|
|
╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝
|
|
"
|
|
}
|
|
|
|
BOOT=EFIBOOT
|
|
ROOT=ROOT
|
|
MOUNTPOINT=/mnt
|
|
EOF
|
|
}
|
|
|
|
PROMPT="Please enter your option: "
|
|
|
|
logo() {
|
|
echo -ne "
|
|
------------------------------------------------------------------------
|
|
|
|
█████╗ ██████╗ ██████╗██╗ ██╗████████╗██╗████████╗██╗ ██╗███████╗
|
|
██╔══██╗██╔══██╗██╔════╝██║ ██║╚══██╔══╝██║╚══██╔══╝██║ ██║██╔════╝
|
|
███████║██████╔╝██║ ███████║ ██║ ██║ ██║ ██║ ██║███████╗
|
|
██╔══██║██╔══██╗██║ ██╔══██║ ██║ ██║ ██║ ██║ ██║╚════██║
|
|
██║ ██║██║ ██║╚██████╗██║ ██║ ██║ ██║ ██║ ╚██████╔╝███████║
|
|
╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝
|
|
"
|
|
}
|
|
|
|
background_check() {
|
|
check_root
|
|
check_docker
|
|
check_arch
|
|
check_pacman
|
|
write_to_config
|
|
efi_check
|
|
if connection_test; then
|
|
echo -ne "ERROR! There seems to be no internet connection.\n"
|
|
exit 0
|
|
fi
|
|
set_ntp
|
|
do_curl
|
|
}
|
|
|
|
set_filesystem() {
|
|
title "Setup File System"
|
|
FILESYS=("btrfs" "ext2" "ext3" "ext4" "f2fs" "jfs" "nilfs2" "ntfs" "vfat" "xfs")
|
|
PS3="$PROMPT"
|
|
select OPT in "${FILESYS[@]}"; do
|
|
if elements_present "$OPT" "${FILESYS[@]}"; then
|
|
set_option "FS" "$OPT"
|
|
break
|
|
else
|
|
invalid_option
|
|
set_filesystem
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
|
|
set_partion_layout() {
|
|
title "Setup Partioning Layout"
|
|
LAYOUTS=("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
|
|
# ;;
|
|
1)
|
|
set_option "LVM" 1
|
|
set_lvm
|
|
break
|
|
;;
|
|
2)
|
|
set_lvm
|
|
set_option "LUKS" 1
|
|
set_option "LUKS_PATH" "/dev/mapper/luks"
|
|
set_password "LUKS_PASSWORD"
|
|
break
|
|
;;
|
|
3)
|
|
echo -ne "Maintaining current settings"
|
|
CHOICE=($(lsblk | grep 'part' | awk '{print "/dev/" substr($1,3)}'))
|
|
if [[ -d "/sys/firmware/efi/" ]]; then
|
|
echo "Select your boot partition"
|
|
PS3="$PROMPT"
|
|
select OPT in "${CHOICE[@]}"; do
|
|
if elements_present "$OPT" "${CHOICE[@]}"; then
|
|
set_option "LAYOUT" 0
|
|
set_option "BOOT_PARTITION" "$OPT"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
echo "Select your root partition"
|
|
PS3="$PROMPT"
|
|
select OPT in "${CHOICE[@]}"; do
|
|
if elements_present "$OPT" "${CHOICE[@]}"; then
|
|
set_option "ROOT_PARTITION" "$OPT"
|
|
break
|
|
fi
|
|
done
|
|
set_filesystem
|
|
break
|
|
;;
|
|
*)
|
|
invalid_option
|
|
set_partion_layout
|
|
break
|
|
;;
|
|
esac
|
|
else
|
|
invalid_option
|
|
set_partion_layout
|
|
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 " "
|
|
read -r -p "Is this correct? [like 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
|
|
set_timezone
|
|
break
|
|
fi
|
|
done
|
|
;;
|
|
|
|
*)
|
|
invalid_option
|
|
set_timezone
|
|
;;
|
|
esac
|
|
}
|
|
|
|
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
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
|
|
ssd_drive() {
|
|
title "SSD Drive Confirmation"
|
|
read -r -p "Is this system using an SSD? [like 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"
|
|
;;
|
|
*)
|
|
invalid_option
|
|
ssd_drive
|
|
;;
|
|
esac
|
|
}
|
|
|
|
disk_selection() {
|
|
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
|
|
DISK=$(echo "$_DISK" | awk '{print $1}')
|
|
set_option "DISK" "$DISK"
|
|
break
|
|
else
|
|
invalid_option
|
|
disk_selection
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
|
|
user_info() {
|
|
title "Add Your Information"
|
|
while true; do
|
|
read -r -p "Please enter your username [default is archtitus]: " USERNAME
|
|
if [[ -z "$USERNAME" ]]; then
|
|
set_option "USERNAME" "archtitus"
|
|
break
|
|
elif [[ "${USERNAME,,}" =~ ^[a-z_]([a-z0-9_-]{0,31}|[a-z0-9_-]{0,30}\$)$ ]]; then
|
|
set_option "USERNAME" "${USERNAME,,}" # convert to lower case as in issue #109
|
|
break
|
|
else
|
|
invalid_option
|
|
continue
|
|
fi
|
|
done
|
|
set_password "PASSWORD"
|
|
while true; do
|
|
read -r -p "Please enter your hostname [default is archlinux]: " HOSTNAME
|
|
if [[ -z "$HOSTNAME" ]]; then
|
|
set_option "HOSTNAME" "archlinux"
|
|
break
|
|
elif [[ "${HOSTNAME,,}" =~ ^[a-z][a-z0-9_.-]{0,62}[a-z0-9]$ ]]; then
|
|
set_option "HOSTNAME" "${HOSTNAME,,}"
|
|
break
|
|
else
|
|
invalid_option
|
|
continue
|
|
fi
|
|
done
|
|
}
|
|
|
|
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
|
|
set_locale
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
|
|
set_desktop() {
|
|
title "Select either desktop Environment or Window Manager"
|
|
SELECTION=("Default (KDE)" "Gnome" "XFCE" "Mate" "LXQT" "Minimal" "Awesome" "OpenBox" "i3" "i3-Gaps" "Deepin" "Budgie")
|
|
PS3="$PROMPT"
|
|
select OPT in "${SELECTION[@]}"; do
|
|
if elements_present "$OPT" "${SELECTION[@]}"; then
|
|
if [[ "$OPT" == "Default (KDE)" ]]; then
|
|
set_option "DESKTOP" "default"
|
|
break
|
|
else
|
|
set_option "DESKTOP" "${OPT,,}"
|
|
break
|
|
|
|
fi
|
|
else
|
|
invalid_option
|
|
set_desktop
|
|
break
|
|
fi
|
|
done
|
|
|
|
}
|
|
|
|
set_aur_helper() {
|
|
title "Select your preferred AUR helper"
|
|
SELECTION=("yay" "trizen" "aurman" "aura" "pikaur" "none")
|
|
PS3="$PROMPT"
|
|
select OPT in "${SELECTION[@]}"; do
|
|
if elements_present "$OPT" "${SELECTION[@]}"; then
|
|
set_option "AURHELPER" "$OPT"
|
|
break
|
|
else
|
|
invalid_option
|
|
set_aur_helper
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
|
|
set_grub_theme() {
|
|
title "Choose your preferred GRUB theme"
|
|
SELECTION=("CyberRe" "Cyberpunk" "Shodan" "Vimix" "fallout" "None")
|
|
PS3="$PROMPT"
|
|
select OPT in "${SELECTION[@]}"; do
|
|
if elements_present "$OPT" "${SELECTION[@]}"; then
|
|
set_option "GRUBTHEME" "${OPT}"
|
|
set_option "THEMEDIR" "/boot/grub/themes"
|
|
break
|
|
else
|
|
invalid_option
|
|
set_grub_theme
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
|
|
set_bootloader() {
|
|
title "Select your bootloader"
|
|
SELECTION=("Default (GRUB)" "Systemd" "UEFI" "None")
|
|
echo "Systemd and UEFI are only available on a UEFI system"
|
|
echo "None will skip a bootloader and you will not be able to boot"
|
|
PS3="$PROMPT"
|
|
select OPT in "${SELECTION[@]}"; do
|
|
if elements_present "$OPT" "${SELECTION[@]}"; then
|
|
if [[ "$OPT" == "Default (GRUB)" ]]; then
|
|
set_option "BOOTLOADER" "grub"
|
|
set_grub_theme
|
|
break
|
|
else
|
|
set_option "BOOTLOADER" "${OPT,,}"
|
|
break
|
|
fi
|
|
else
|
|
invalid_option
|
|
set_bootloader
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
|
|
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 btrfs as file systems,"
|
|
echo "KDE Plasma as desktop environment and sddm as window manager and package"
|
|
echo "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
|
|
user_info
|
|
disk_selection
|
|
clear
|
|
set_locale
|
|
clear
|
|
set_timezone
|
|
set_keymap
|
|
ssd_drive
|
|
set_btrfs
|
|
set_option "LAYOUT" 1
|
|
set_option "BOOTLOADER" "grub"
|
|
set_option "GRUBTHEME" "CyberRe"
|
|
set_option "FS" "btrfs"
|
|
set_option "AURHELPER" "yay"
|
|
set_option "DESKTOP" "default"
|
|
|
|
break
|
|
;;
|
|
2)
|
|
clear
|
|
logo
|
|
user_info
|
|
disk_selection
|
|
clear
|
|
set_locale
|
|
clear
|
|
set_timezone
|
|
set_keymap
|
|
ssd_drive
|
|
# Advance options
|
|
set_aur_helper
|
|
set_partion_layout
|
|
set_bootloader
|
|
set_filesystem
|
|
set_desktop
|
|
break
|
|
;;
|
|
*)
|
|
invalid_option
|
|
make_choice
|
|
break
|
|
;;
|
|
esac
|
|
else
|
|
invalid_option
|
|
make_choice
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
background_check
|
|
# write_to_config
|
|
clear
|
|
logo
|
|
make_choice
|
|
# user_info
|
|
# set_partion_layout
|