1206 lines
46 KiB
Bash
Executable file
1206 lines
46 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# Load the configuration file
|
|
init() {
|
|
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
source "$DIR"/etc/setup.conf
|
|
clear ; setfont Lat2-Terminus16.psfu.gz
|
|
dialog --title "Welcome to Parch Linux Installer" \
|
|
--ok-label "Begin Installation" --msgbox "Navigating the installer is \
|
|
easy.\nYou may select options using the ARROW keys and SPACE or \
|
|
ENTER.\nAlternate keys may also be used: '+', '-', and TAB." 7 70
|
|
}
|
|
|
|
# Proceed with installation only if there is an internet connection
|
|
check_connection() {
|
|
dialog --infobox "Checking internet connection..." 3 50
|
|
# Check if a web page is available
|
|
if ! nc -zw1 archlinux.org 443; then
|
|
dialog --title "Connect to the Internet" \
|
|
--msgbox "The installer was unable to detect a working internet \
|
|
connection. The installation media supports wired network devices on \
|
|
boot. Make sure the cable is plugged in. Wireless users should use the \
|
|
'iwctl' command to connect to a wireless connection.\n\nOnce you have \
|
|
a working internet connection, retry running the installer." 10 80
|
|
reset ; exit 1
|
|
fi
|
|
}
|
|
|
|
# Check and disable any active mountpoints
|
|
check_mountpoints() {
|
|
if mountpoint -q /mnt; then
|
|
dialog --infobox "Unmounting active mountpoints on $DISK..." 3 50
|
|
umount -R /mnt
|
|
fi
|
|
|
|
if free | awk '/^Swap:/ {exit !$2}'; then
|
|
swapoff -a
|
|
fi
|
|
}
|
|
|
|
# Check for LVM on the system to avoid conflicts
|
|
check_lvm_status() {
|
|
# Check for an existing volume group on the selected disk
|
|
if vgs --noheading --nosuffix -o pv_name | grep -q "$DISK"; then
|
|
vg_on_pv=$(pvs -o pv_name,vg_name | grep "$DISK" | awk '{print $2}')
|
|
dialog --title "WARNING: LVM Exists on $DISK" \
|
|
--yesno "A volume group ($vg_on_pv) was detected on the selected disk \
|
|
($DISK).\n\nIn order to proceed, the volume group ($vg_on_pv) needs to be \
|
|
removed and all data will be lost!\n\nAre you sure you want to remove the \
|
|
volume group '$vg_on_pv'?" 11 75
|
|
if [ $? -eq 0 ]; then
|
|
dialog --infobox "Removing $vg_on_pv from $DISK..." 3 50
|
|
vgchange -y -an "$vg_on_pv" &> /dev/null
|
|
vgremove -y "$vg_on_pv" &> /dev/null
|
|
else
|
|
dialog --title "ERROR: Unable to Partition $DISK" \
|
|
--msgbox "The installer can't proceed while LVM is active on \
|
|
$DISK.\n\nIf you have any active LVM devices, please make sure they are not in \
|
|
use and backup any data on the volume group before running the installer." 8 80
|
|
reset ; exit 1
|
|
fi
|
|
fi
|
|
|
|
# Check for a volume group with the same name on the system when creating LVM
|
|
if [ "$PARTITION_LAYOUT" != "Basic" ]; then
|
|
if vgs "$LVM_GROUP" &> /dev/null; then
|
|
dialog --title "WARNING: LVM Volume Group Exists" \
|
|
--yesno "A volume group with the name '$LVM_GROUP' already exists on \
|
|
your system.\n\nIn order to proceed, the volume group ($LVM_GROUP) needs to be \
|
|
overwritten and all data will be lost!\n\nAre you sure you want to overwrite \
|
|
the volume group '$LVM_GROUP'?" 11 80
|
|
if [ $? -eq 0 ]; then
|
|
dialog --infobox "Removing $LVM_GROUP from $DISK..." 3 50
|
|
vgchange -y -an "$LVM_GROUP" &> /dev/null
|
|
vgremove -y "$LVM_GROUP" &> /dev/null
|
|
else
|
|
dialog --title "ERROR: Unable to Partition $DISK" \
|
|
--msgbox "The installer can't partition the disk because a volume \
|
|
group with the name '$LVM_GROUP' already exists on your system.\n\nIf you have \
|
|
any active LVM devices, please make sure they are not in use and backup any \
|
|
data on the volume group before running the installer." 9 80
|
|
reset ; exit 1
|
|
fi
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Prompt the user to set their keyboard layout
|
|
set_keymap() {
|
|
while true; do
|
|
KEYMAP=$(dialog --title "Set the Keyboard Layout" --nocancel \
|
|
--default-item "us" --menu "Select a keymap that corresponds to your \
|
|
keyboard layout. Choose 'other' if your keymap is not listed. If you are \
|
|
unsure, the default is 'us' (United States/QWERTY).\n\nKeymap:" 22 57 10 \
|
|
"fr" "French" \
|
|
"de" "German" \
|
|
"gr" "Greek" \
|
|
"hu" "Hungarian" \
|
|
"it" "Italian" \
|
|
"pl" "Polish" \
|
|
"ru" "Russian" \
|
|
"es" "Spanish" \
|
|
"us" "United States" \
|
|
"other" "View all available keymaps" 3>&1 1>&2 2>&3)
|
|
|
|
if [ "$KEYMAP" = "other" ]; then
|
|
keymaps=()
|
|
for map in $(localectl list-keymaps); do
|
|
keymaps+=("$map" "")
|
|
done
|
|
KEYMAP=$(dialog --title "Set the Keyboard Layout" --cancel-label "Back" \
|
|
--menu "Select a keymap that corresponds to your keyboard layout. The \
|
|
default is 'us' (United States/QWERTY)." 30 60 25 \
|
|
"${keymaps[@]}" 3>&1 1>&2 2>&3)
|
|
if [ $? -eq 0 ]; then
|
|
break
|
|
fi
|
|
else
|
|
break
|
|
fi
|
|
done
|
|
dialog --infobox "Setting keymap to $KEYMAP..." 3 50
|
|
localectl set-keymap "$KEYMAP"
|
|
loadkeys "$KEYMAP"
|
|
}
|
|
|
|
# Prompt the user to set the system locale
|
|
set_locale() {
|
|
while true; do
|
|
LOCALE=$(dialog --title "Set the System Locale" --nocancel \
|
|
--default-item "en_US.UTF-8" --menu "Select a locale that corresponds \
|
|
to your language and region. The locale you select will define the language \
|
|
used by the system and other region specific information. Choose 'other' if \
|
|
your language and/or region is not listed. If you are unsure, the default is \
|
|
'en_US.UTF-8'.\n\nLocale:" 30 65 16 \
|
|
"zh_CN.UTF-8" "Chinese (Simplified)" \
|
|
"en_AU.UTF-8" "English (Australia)" \
|
|
"en_CA.UTF-8" "English (Canada)" \
|
|
"en_US.UTF-8" "English (United States)" \
|
|
"en_GB.UTF-8" "English (Great Britain)" \
|
|
"fr_FR.UTF-8" "French (France)" \
|
|
"de_DE.UTF-8" "German (Germany)" \
|
|
"it_IT.UTF-8" "Italian (Italy)" \
|
|
"ja_JP.UTF-8" "Japanese (Japan)" \
|
|
"pt_BR.UTF-8" "Portuguese (Brazil)" \
|
|
"pt_PT.UTF-8" "Portuguese (Portugal)" \
|
|
"ru_RU.UTF-8" "Russian (Russia)" \
|
|
"es_MX.UTF-8" "Spanish (Mexico)" \
|
|
"es_ES.UTF-8" "Spanish (Spain)" \
|
|
"sv_SE.UTF-8" "Swedish (Sweden)" \
|
|
"other" "View all available locales" 3>&1 1>&2 2>&3)
|
|
|
|
if [ "$LOCALE" = "other" ]; then
|
|
locales=()
|
|
# Read each entry in /etc/locale.gen and remove comments and spaces
|
|
while read -r line; do
|
|
locales+=("$line" "")
|
|
done < <(grep -E "^#?[a-z].*UTF-8" /etc/locale.gen | sed -e 's/#//' -e 's/\s.*$//')
|
|
LOCALE=$(dialog --title "Set the System Locale" --cancel-label "Back" \
|
|
--menu "Select a locale that corresponds to your language and region. \
|
|
The locale you select will define the language used by the system and other
|
|
region specific information. If you are unsure, the default is \
|
|
'en_US.UTF-8'.\n\nLocale:" 30 65 16 \
|
|
"${locales[@]}" 3>&1 1>&2 2>&3)
|
|
if [ $? -eq 0 ]; then
|
|
break
|
|
fi
|
|
else
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Prompt the user to set the system time zone
|
|
set_timezone() {
|
|
utc_enabled=true
|
|
regions=()
|
|
for region in \
|
|
$(find /usr/share/zoneinfo -mindepth 1 -maxdepth 1 -type d -printf '%f\n' \
|
|
| grep -E -v '/$|posix|right' \
|
|
| sort); do
|
|
regions+=("$region" "")
|
|
done
|
|
regions+=("other" "")
|
|
|
|
while true; do
|
|
ZONE=$(dialog --title "Set the Time Zone" --nocancel \
|
|
--menu "Select your time zone.\nIf your region is not listed, select \
|
|
'other'.\n\nTime zone:" 27 50 17 \
|
|
"${regions[@]}" 3>&1 1>&2 2>&3)
|
|
|
|
if [ "$ZONE" != "other" ]; then
|
|
zone_regions=()
|
|
for zone_region in \
|
|
$(find /usr/share/zoneinfo/"${ZONE}" -mindepth 1 -maxdepth 1 -printf '%f\n' \
|
|
| sort); do
|
|
zone_regions+=("$zone_region" "")
|
|
done
|
|
SUBZONE=$(dialog --title "Set the Time Zone" --cancel-label "Back" \
|
|
--menu "Select your time zone.\n\nTime zone:" 27 50 17 \
|
|
"${zone_regions[@]}" 3>&1 1>&2 2>&3)
|
|
if [ $? -eq 0 ]; then
|
|
if [ -d /usr/share/zoneinfo/"${ZONE}/${SUBZONE}" ]; then
|
|
subzone_regions=()
|
|
for subzone_region in \
|
|
$(find /usr/share/zoneinfo/"${ZONE}/${SUBZONE}" -mindepth 1 -maxdepth 1 -printf '%f\n' \
|
|
| sort); do
|
|
subzone_regions+=("$subzone_region" "")
|
|
done
|
|
SUBZONE_SUBREGION=$(dialog --title "Set the Time Zone" \
|
|
--cancel-label "Back" \
|
|
--menu "Select your time zone.\n\nTime zone:" 27 50 17 \
|
|
"${subzone_regions[@]}" 3>&1 1>&2 2>&3)
|
|
if [ $? -eq 0 ]; then
|
|
ZONE="${ZONE}/${SUBZONE}/${SUBZONE_SUBREGION}"
|
|
break
|
|
fi
|
|
else
|
|
ZONE="${ZONE}/${SUBZONE}"
|
|
break
|
|
fi
|
|
fi
|
|
else
|
|
for other_region in \
|
|
$(find /usr/share/zoneinfo -mindepth 1 -maxdepth 1 -type f -printf '%f\n' \
|
|
| grep -E -v '/$|iso3166.tab|leapseconds|posixrules|tzdata.zi|zone.tab|zone1970.tab' \
|
|
| sort); do
|
|
other_regions+=("$other_region" "")
|
|
done
|
|
ZONE=$(dialog --title "Set the Time Zone" --cancel-label "Back" \
|
|
--menu "Select your time zone.\n\nTime zone:" 27 50 17 \
|
|
"${other_regions[@]}" 3>&1 1>&2 2>&3)
|
|
if [ $? -eq 0 ]; then
|
|
ZONE="${ZONE}"
|
|
break
|
|
fi
|
|
fi
|
|
done
|
|
|
|
dialog --title "Set the Hardware Clock" --nocancel \
|
|
--yesno "Would you like to set the hardware clock from the system \
|
|
clock using UTC time?\nIf you select no, local time will be used \
|
|
instead.\n\nIf you are unsure, UTC time is the default." 8 85
|
|
if [ $? -ne 0 ]; then
|
|
utc_enabled=false
|
|
fi
|
|
}
|
|
|
|
# Prompt the user to set the system hostname
|
|
set_hostname() {
|
|
while true; do
|
|
HOST_NAME=$(dialog --title "Set the Hostname" --nocancel \
|
|
--inputbox "Please enter the hostname for this system.\n\nThe hostname \
|
|
is a single word that identifies your system to the network.\n\nHostname:" \
|
|
12 80 "Parch" 3>&1 1>&2 2>&3)
|
|
|
|
# Hostname must be alpha-numeric and may contain a dash only in between
|
|
if printf "%s" "$HOST_NAME" | grep -Eoq "^[a-zA-Z0-9-]{1,63}$" \
|
|
&& [ "${HOST_NAME:0:1}" != "-" ] \
|
|
&& [ "${HOST_NAME: -1}" != "-" ]; then
|
|
break
|
|
else
|
|
dialog --title "ERROR: Invalid Hostname Format" \
|
|
--msgbox "You entered an invalid hostname.\n\nA valid hostname may \
|
|
contain only the numbers 0-9, upper and lowercase letters (A-Z and a-z), and \
|
|
the minus sign. It must be at most 63 characters long, and may not begin \
|
|
or end with a minus sign." 9 75
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Prompt the user to create a password for the superuser account
|
|
set_root_passwd(){
|
|
inputs_match=false
|
|
while ! $inputs_match; do
|
|
input=$(dialog --title "Set the Root Password" --clear --stdout --nocancel \
|
|
--insecure --passwordbox "Please enter a password for 'root', the \
|
|
system administrative account.\n\nRoot password:" 10 75)
|
|
confirm_input=$(dialog --title "Set the Root Password" --clear --stdout \
|
|
--insecure --passwordbox "Re-enter password to verify:" 8 55)
|
|
|
|
if [ -z "$input" ]; then
|
|
dialog --title "ERROR: Empty Password" \
|
|
--msgbox "You are not allowed to have an empty password." 5 55
|
|
elif [ "$input" != "$confirm_input" ]; then
|
|
dialog --title "ERROR: Passwords Do No Match" \
|
|
--msgbox "The two passwords you entered did not match." 5 55
|
|
else
|
|
root_passwd="$input"
|
|
inputs_match=true
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Prompt the user to create an unprivileged user account
|
|
create_user() {
|
|
while true; do
|
|
FULL_NAME=$(dialog --title "Create a User Account" --nocancel \
|
|
--inputbox "The installer will create a user account for you. This is \
|
|
the main user account that you will login to and use for non-administrative \
|
|
activities.\n\nPlease enter the real name for this user. This information \
|
|
will be used for any program that uses the user's real name such as email. \
|
|
Entering your full name here is recommended; however, it may be left \
|
|
blank.\n\nFull name for the new user:" 15 80 3>&1 1>&2 2>&3)
|
|
|
|
USER_NAME=$(dialog --title "Create a User Account" \
|
|
--cancel-label "Back" --inputbox "Please enter a username for the new \
|
|
account.\n\nThe username should start with a lower-case letter, which can be \
|
|
followed by any combination of numbers, more lower-case letters, or the dash \
|
|
symbol.\n\nUsername for your account:" 13 80 3>&1 1>&2 2>&3)
|
|
|
|
if [ $? -eq 0 ]; then
|
|
# Username must start with lowercase letter. May contain lowercase
|
|
# alpha-numerics and dashes
|
|
if printf "%s" "$USER_NAME" | grep -Eoq "^[a-z][a-z0-9-]*$" \
|
|
&& [ "${#USER_NAME}" -lt 33 ]; then
|
|
# The reserved_username file contains usernames that should be avoided
|
|
if grep -Fxq "$USER_NAME" "$DIR"/etc/reserved_usernames; then
|
|
dialog --title "ERROR: Reserved Username" \
|
|
--msgbox "The username you entered ($USER_NAME) is reserved for \
|
|
use by the system. Please select a different one." 6 70
|
|
else
|
|
inputs_match=false
|
|
while ! $inputs_match; do
|
|
input=$(dialog --title "Set the Password for $USER_NAME" --clear \
|
|
--stdout --nocancel --insecure --passwordbox "Please enter a \
|
|
password for '$USER_NAME'.\n\nChoose a password for the new user:" 10 70)
|
|
confirm_input=$(dialog --title "Set the Password for $USER_NAME" \
|
|
--clear --stdout --insecure \
|
|
--passwordbox "Re-enter password to verify:" 8 55)
|
|
|
|
if [ -z "$input" ]; then
|
|
dialog --title "ERROR: Empty Password" \
|
|
--msgbox "You are not allowed to have an empty password." 5 55
|
|
elif [ "$input" != "$confirm_input" ]; then
|
|
dialog --title "ERROR: Passwords Do No Match" \
|
|
--msgbox "The two passwords you entered did not match." 5 55
|
|
else
|
|
user_passwd="$input"
|
|
inputs_match=true
|
|
fi
|
|
done
|
|
break
|
|
fi
|
|
else
|
|
dialog --title "ERROR: Invalid Username Format" \
|
|
--msgbox "You entered an invalid username.\n\nThe username must \
|
|
start with a lower-case letter, which can be followed by any combination of \
|
|
numbers, more lower-case letters, or the dash symbol, and must be no more \
|
|
than 32 characters long." 9 80
|
|
fi
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Prepare the user's selected disk for partitioning
|
|
prepare_disk() {
|
|
SWAP="-"
|
|
swap_enabled=false
|
|
block_devices=()
|
|
# List all available block devices excluding 'rom' and 'loop'
|
|
for device in $(lsblk -d -n -p -r -e 7,11 -o NAME); do
|
|
device_size=$(lsblk -d -n -r -o SIZE "$device")
|
|
block_devices+=("$device" "$device_size")
|
|
done
|
|
|
|
check_mountpoints
|
|
while true; do
|
|
PARTITION_LAYOUT=$(dialog --title "Partition the Disks" \
|
|
--cancel-label "Exit to Menu" \
|
|
--menu "The installer will now automatically partition a disk for you. \
|
|
If you have no preference or are unsure about which partition layout to \
|
|
choose, the 'Basic' layout is the simplest and should be enough for most use \
|
|
cases.\n\nPartition layout:" 14 80 3 \
|
|
"Basic" "Use entire disk" \
|
|
"LVM" "Use entire disk and set up LVM" \
|
|
"Encrypted" "Use entire disk and set up encrypted LVM" 3>&1 1>&2 2>&3)
|
|
|
|
if [ $? -eq 0 ]; then
|
|
DISK=$(dialog --title "Set the Installation Disk" --cancel-label "Back" \
|
|
--menu "Select the disk for Parch Linux to be installed on. Note that \
|
|
the disk you select will be erased, but not until you have confirmed the \
|
|
changes.\n\nDisk to partition:" 16 55 5 \
|
|
"${block_devices[@]}" 3>&1 1>&2 2>&3)
|
|
|
|
if [ $? -eq 0 ]; then
|
|
# NVME devices use nvme0n1p1, p2, p3 etc. for partition naming
|
|
PREFIX=""
|
|
if [[ "$DISK" == *"nvme"* ]]; then
|
|
PREFIX="p"
|
|
fi
|
|
|
|
FILE_SYSTEM=$(dialog --title "Set the Filesystem for $DISK_ROOT" \
|
|
--nocancel --menu "Select the type of filesystem to use for the \
|
|
specified device. If you are unsure, 'ext4' is the default.\n\nFilesystem \
|
|
type:" 15 68 5 \
|
|
"ext4" "Ext4 journaling filesystem" \
|
|
"ext3" "Ext3 journaling filesystem" \
|
|
"ext2" "Standard Linux Ext2 filesystem" \
|
|
"btrfs" "Btrfs Copy-on-Write B-tree filesystem" \
|
|
"xfs" "SGI's journaling filesystem" 3>&1 1>&2 2>&3)
|
|
|
|
dialog --title "Create a Swap Partition" \
|
|
--yesno "Would you like to create an optional swap partition? If \
|
|
you are unsure, it is recommended to create one." 6 57
|
|
if [ $? -eq 0 ]; then
|
|
# Get the amount of RAM in the system to use as default swap size
|
|
mem_total=$(free --giga | awk '/^Mem:/{print $2}')
|
|
if [ "$mem_total" != "0" ]; then
|
|
mem_total="${mem_total}G"
|
|
else
|
|
mem_total=$(free --mega | awk '/^Mem:/{print $2}')
|
|
mem_total="${mem_total}M"
|
|
fi
|
|
|
|
while true; do
|
|
SWAP=$(dialog --title "Allocate Swap Space" \
|
|
--inputbox "Specify how much swap space to allocate. If you are \
|
|
unsure, the default is to have swap space equal to the amount of RAM in your \
|
|
system.\n\nSwap partition size (use 'M' for MiB or 'G' for GiB):" 11 80 \
|
|
"$mem_total" 3>&1 1>&2 2>&3)
|
|
|
|
if [ $? -eq 0 ]; then
|
|
disk_size_bytes=$(lsblk -b -d -n -o SIZE "$DISK")
|
|
disk_size_mibs=$((disk_size_bytes/1024/1024))
|
|
disk_size_gibs=$((disk_size_mibs/1024))
|
|
swap_size=$(printf "%s" "$SWAP" | tr -c -d '[:digit:]')
|
|
|
|
# Input validation for swap size
|
|
if printf "%s" "$SWAP" | grep -Eoq "^[0-9]+[MG]$" \
|
|
&& [ "${swap_size:0:1}" != "0" ]; then
|
|
if [ "${SWAP: -1}" = "M" ] \
|
|
&& [ "$swap_size" -lt $((disk_size_mibs - 2048)) ]; then
|
|
swap_enabled=true
|
|
break
|
|
elif [ "${SWAP: -1}" = "G" ] \
|
|
&& [ "$swap_size" -lt $((disk_size_gibs - 2)) ]; then
|
|
swap_enabled=true
|
|
break
|
|
else
|
|
dialog --title "ERROR: Not Enough Disk Space" \
|
|
--msgbox "The amount you entered exceeds the amount of \
|
|
space available on the disk. Note that the installer sets aside an additional \
|
|
2 GiB to have enough space for the base installation." 8 60
|
|
fi
|
|
else
|
|
dialog --title "ERROR: Invalid Format" \
|
|
--msgbox "You entered an invalid format. Make sure to use \
|
|
'M' for 'MiB' or 'G' for 'GiB'." 6 60
|
|
fi
|
|
else
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
dialog --title "Confirm the Partition Layout for $DISK" --defaultno \
|
|
--yesno "WARNING: All data on the selected disk will be lost! Make \
|
|
sure to review your changes before continuing.\n\nDisk to partition: \
|
|
$DISK\nPartition layout: $PARTITION_LAYOUT\nFilesystem type: \
|
|
$FILE_SYSTEM\nSwap size: $SWAP\n\nAre you sure you want to write the \
|
|
changes to the disk?" 13 60
|
|
if [ $? -eq 0 ]; then
|
|
check_lvm_status
|
|
dialog --infobox "Formatting $DISK..." 3 50
|
|
sgdisk --zap-all "$DISK" &> /dev/null
|
|
wipefs -a "$DISK" &> /dev/null
|
|
dialog --infobox "Partitioning $DISK..." 3 50
|
|
create_partition_label
|
|
case "$PARTITION_LAYOUT" in
|
|
"Basic") create_basic_layout ;;
|
|
"LVM") create_lvm_layout ;;
|
|
"Encrypted") create_encrypted_layout ;;
|
|
esac
|
|
break
|
|
else
|
|
main_menu
|
|
fi
|
|
fi
|
|
else
|
|
main_menu
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Create a new partition label on the selected disk
|
|
create_partition_label() {
|
|
# UEFI systems use GPT partitioning and BIOS/CSM systems use MBR
|
|
if $UEFI; then
|
|
parted -s "$DISK" mklabel gpt &> /dev/null
|
|
else
|
|
parted -s "$DISK" mklabel msdos &> /dev/null
|
|
fi
|
|
if [ $? -ne 0 ]; then
|
|
dialog --title "ERROR: Unable to Partition $DISK" \
|
|
--msgbox "The installer encountered an error while partitioning \
|
|
$DISK.\n\nMake sure the disk you selected is not active before running the \
|
|
installer. If this error keeps occuring, please reboot your machine and try \
|
|
again." 8 80
|
|
reset ; exit 1
|
|
fi
|
|
}
|
|
|
|
# Partition the selected disk where everything is installed on one partition
|
|
create_basic_layout() {
|
|
if $UEFI; then
|
|
BOOT_PART="${DISK}${PREFIX}1"
|
|
ROOT_PART="${DISK}${PREFIX}2"
|
|
if $swap_enabled; then
|
|
SWAP_PART="${DISK}${PREFIX}3"
|
|
sgdisk -n 1:0:+512M -n 2:0:-"$SWAP" -n 3:-"$SWAP":-0 \
|
|
-t 1:ef00 -t 2:8300 -t 3:8200 "$DISK" &> /dev/null
|
|
mkswap "$SWAP_PART" &> /dev/null
|
|
swapon "$SWAP_PART"
|
|
else
|
|
sgdisk -n 1:0:+512M -n 2:0:0 -t 1:ef00 -t 2:8300 "$DISK" &> /dev/null
|
|
fi
|
|
mkfs.fat -F32 "$BOOT_PART" &> /dev/null
|
|
else
|
|
ROOT_PART="${DISK}${PREFIX}1"
|
|
if $swap_enabled; then
|
|
SWAP_PART="${DISK}${PREFIX}2"
|
|
echo -e "n\np\n1\n\n-${SWAP}\nn\np\n2\n\n\nt\n2\n82\nw" \
|
|
| fdisk "$DISK" &> /dev/null
|
|
mkswap "$SWAP_PART" &> /dev/null
|
|
swapon "$SWAP_PART"
|
|
else
|
|
echo -e "n\np\n1\n\n\nw" | fdisk "$DISK" &> /dev/null
|
|
fi
|
|
fi
|
|
|
|
case "$FILE_SYSTEM" in
|
|
btrfs|xfs) mkfs."$FILE_SYSTEM" -f "$ROOT_PART" &> /dev/null ;;
|
|
*) mkfs."$FILE_SYSTEM" "$ROOT_PART" &> /dev/null ;;
|
|
esac
|
|
mount "$ROOT_PART" /mnt
|
|
if [ $? -eq 0 ]; then
|
|
mounted=true
|
|
fi
|
|
if $UEFI; then
|
|
mkdir /mnt/boot
|
|
mount "$BOOT_PART" /mnt/boot
|
|
fi
|
|
}
|
|
|
|
# Partition the selected disk and configure LVM
|
|
create_lvm_layout() {
|
|
if $UEFI; then
|
|
BOOT_PART="${DISK}${PREFIX}1"
|
|
ROOT_PART="${DISK}${PREFIX}2"
|
|
sgdisk -n 1:0:+512M -n 2:0:0 -t 1:ef00 -t 2:8e00 "$DISK" &> /dev/null
|
|
mkfs.fat -F32 "$BOOT_PART" &> /dev/null
|
|
else
|
|
ROOT_PART="${DISK}${PREFIX}1"
|
|
echo -e "n\np\n1\n\n\nt\n8e\nw" | fdisk "$DISK" &> /dev/null
|
|
fi
|
|
|
|
dialog --infobox "Configuring LVM on $ROOT_PART..." 3 50
|
|
pvcreate -y "$ROOT_PART" &> /dev/null
|
|
vgcreate -y "$LVM_GROUP" "$ROOT_PART" &> /dev/null
|
|
if $swap_enabled; then
|
|
lvcreate -y -L "$SWAP" "$LVM_GROUP" -n "$LVM_SWAP" &> /dev/null
|
|
lvcreate -y -l 100%FREE "$LVM_GROUP" -n "$LVM_ROOT" &> /dev/null
|
|
mkswap "/dev/${LVM_GROUP}/${LVM_SWAP}" &> /dev/null
|
|
swapon "/dev/${LVM_GROUP}/${LVM_SWAP}"
|
|
else
|
|
lvcreate -y -l 100%FREE "$LVM_GROUP" -n "$LVM_ROOT" &> /dev/null
|
|
fi
|
|
|
|
case "$FILE_SYSTEM" in
|
|
btrfs|xfs) mkfs."$FILE_SYSTEM" -f "/dev/${LVM_GROUP}/${LVM_ROOT}" &> /dev/null ;;
|
|
*) mkfs."$FILE_SYSTEM" "/dev/${LVM_GROUP}/${LVM_ROOT}" &> /dev/null ;;
|
|
esac
|
|
mount "/dev/${LVM_GROUP}/${LVM_ROOT}" /mnt
|
|
if [ $? -eq 0 ]; then
|
|
mounted=true
|
|
fi
|
|
if $UEFI; then
|
|
mkdir /mnt/boot
|
|
mount "$BOOT_PART" /mnt/boot
|
|
fi
|
|
}
|
|
|
|
# Partition the selected disk and set up root disk encryption (LVM on LUKS)
|
|
create_encrypted_layout() {
|
|
# /boot is left unencrypted
|
|
BOOT_PART="${DISK}${PREFIX}1"
|
|
ROOT_PART="${DISK}${PREFIX}2"
|
|
if $UEFI; then
|
|
sgdisk -n 1:0:+512M -n 2:0:0 -t 1:ef00 -t 2:8e00 "$DISK" &> /dev/null
|
|
mkfs.fat -F32 "$BOOT_PART" &> /dev/null
|
|
else
|
|
echo -e "n\np\n1\n\n+512M\nn\np\n2\n\n\nt\n2\n8e\nw" | fdisk "$DISK" &> /dev/null
|
|
mkfs.ext4 "$BOOT_PART" &> /dev/null
|
|
fi
|
|
|
|
inputs_match=false
|
|
while ! $inputs_match; do
|
|
input=$(dialog --title "Encrypt $ROOT_PART" --clear --stdout \
|
|
--insecure --passwordbox "Enter a passphrase to encrypt \
|
|
$ROOT_PART.\n\nThe overall strength of the encryption process depends \
|
|
strongly on this passphrase, therefore you should set a passphrase that is \
|
|
not easy to guess.\n\nNote that the passphrase you enter will be required \
|
|
each time on boot.\n\nEncryption passphrase:" 15 80)
|
|
|
|
if [ $? -eq 0 ]; then
|
|
confirm_input=$(dialog --title "Encrypt $ROOT_PART" --clear --stdout \
|
|
--insecure --passwordbox "Re-enter passphrase to verify:" 8 55)
|
|
|
|
if [ -z "$input" ]; then
|
|
dialog --title "ERROR: Empty Passphrase" \
|
|
--msgbox "You are not allowed to have an empty passphrase." 5 55
|
|
elif [ "$input" != "$confirm_input" ]; then
|
|
dialog --title "ERROR: Passphrases Do No Match" \
|
|
--msgbox "The two passphrases you entered did not match." 5 55
|
|
elif [ "${#input}" -lt 8 ]; then
|
|
dialog --title "WARNING: Weak Passphrase" --defaultno \
|
|
--yesno "The passphrase you entered is less than 8 characters which \
|
|
is considered insecure.\n\nContinue using a weak passphrase?" 8 60
|
|
if [ $? -eq 0 ]; then
|
|
inputs_match=true
|
|
fi
|
|
else
|
|
inputs_match=true
|
|
fi
|
|
else
|
|
dialog --title "Revert Partition Changes" --defaultno \
|
|
--yesno "Are you sure you want to cancel the encryption \
|
|
process? If you choose yes, you will be returned to the partition menu." 7 65
|
|
if [ $? -eq 0 ]; then
|
|
prepare_disk
|
|
fi
|
|
fi
|
|
done
|
|
|
|
dialog --infobox "Encrypting $ROOT_PART..." 3 50
|
|
printf "%s" "$input" | cryptsetup luksFormat "$ROOT_PART" - &> /dev/null
|
|
printf "%s" "$input" | cryptsetup open "$ROOT_PART" "$CRYPT_DEVICE_NAME" -
|
|
dialog --infobox "Configuring LVM on $ROOT_PART..." 3 50
|
|
pvcreate -y "/dev/mapper/${CRYPT_DEVICE_NAME}" &> /dev/null
|
|
vgcreate -y "$LVM_GROUP" "/dev/mapper/${CRYPT_DEVICE_NAME}" &> /dev/null
|
|
|
|
if $swap_enabled; then
|
|
lvcreate -y -L "$SWAP" "$LVM_GROUP" -n "$LVM_SWAP" &> /dev/null
|
|
lvcreate -y -l 100%FREE "$LVM_GROUP" -n "$LVM_ROOT" &> /dev/null
|
|
mkswap "/dev/mapper/${LVM_GROUP}-${LVM_SWAP}" &> /dev/null
|
|
swapon "/dev/mapper/${LVM_GROUP}-${LVM_SWAP}"
|
|
else
|
|
lvcreate -y -l 100%FREE "$LVM_GROUP" -n "$LVM_ROOT" &> /dev/null
|
|
fi
|
|
|
|
case "$FILE_SYSTEM" in
|
|
btrfs|xfs) mkfs."$FILE_SYSTEM" -f "/dev/mapper/${LVM_GROUP}-${LVM_ROOT}" &> /dev/null ;;
|
|
*) mkfs."$FILE_SYSTEM" "/dev/mapper/${LVM_GROUP}-${LVM_ROOT}" &> /dev/null ;;
|
|
esac
|
|
mount "/dev/mapper/${LVM_GROUP}-${LVM_ROOT}" /mnt
|
|
if [ $? -eq 0 ]; then
|
|
mounted=true
|
|
fi
|
|
mkdir /mnt/boot
|
|
mount "$BOOT_PART" /mnt/boot
|
|
}
|
|
|
|
# Use the reflector script to update the pacman mirror list
|
|
update_mirrorlist() {
|
|
dialog --title "Update the Mirror List" \
|
|
--yesno "Would you like to update the Parch Linux mirror list?\n\nUpdating \
|
|
the mirror list will speed up the download of packages. If you select no, \
|
|
your download speed may be affected." 8 70
|
|
|
|
if [ $? -eq 0 ]; then
|
|
dialog --infobox "Updating pacman mirror list..." 3 50
|
|
# Sort the 50 most recently synchronized HTTPS mirrors by download speed
|
|
reflector --latest 50 --protocol https --sort rate --save /etc/pacman.d/mirrorlist
|
|
fi
|
|
}
|
|
|
|
# Prompt the user to install the base packages for the system
|
|
configure_install() {
|
|
bluetooth_enabled=false
|
|
dm_enabled=false
|
|
multilib=false
|
|
DESKTOP_PACKAGES=()
|
|
|
|
if $UEFI; then
|
|
DESKTOP_PACKAGES+=('efibootmgr')
|
|
fi
|
|
|
|
if [ "$PARTITION_LAYOUT" = "LVM" ]; then
|
|
DESKTOP_PACKAGES+=('lvm2')
|
|
elif [ "$PARTITION_LAYOUT" = "Encrypted" ]; then
|
|
DESKTOP_PACKAGES+=('lvm2' 'cryptsetup')
|
|
fi
|
|
|
|
if [ "$FILE_SYSTEM" = "btrfs" ]; then
|
|
DESKTOP_PACKAGES+=('btrfs-progs')
|
|
elif [ "$FILE_SYSTEM" = "xfs" ]; then
|
|
DESKTOP_PACKAGES+=('xfsprogs')
|
|
fi
|
|
|
|
if [ "$architecture" = "x86_64" ]; then
|
|
dialog --title "Enable multilib" \
|
|
--yesno "Would you like to enable the 'multilib' repository?\n\nBy \
|
|
default, Arch only includes 64-bit software in its repositories. The \
|
|
'multilib' repository contains 32-bit software that is compatible on a 64-bit \
|
|
system (e.g. wine, steam, etc)." 9 70
|
|
if [ $? -eq 0 ]; then
|
|
multilib=true
|
|
fi
|
|
fi
|
|
|
|
while true; do
|
|
DESKTOP=$(dialog --title "Choose your Graphical Environment" --no-cancel \
|
|
--menu "Select the style of graphical environment you wish to \
|
|
use.\n\nGraphical environment:" 12 75 3 \
|
|
"Desktop Environment" "Traditional complete graphical user interface" \
|
|
"Window Manager" "Standalone minimal graphical user interface" \
|
|
"None" "Command-line only interface" 3>&1 1>&2 2>&3)
|
|
|
|
if [ "$DESKTOP" = "Desktop Environment" ]; then
|
|
GUI=$(dialog --title "Select a Desktop Environment" \
|
|
--cancel-label "Back" \
|
|
--menu "Select a desktop environment to install:" 15 65 8 \
|
|
"Budgie" "Modern GNOME based desktop" \
|
|
"Cinnamon" "Traditional desktop experience" \
|
|
"GNOME" "Modern simplicity focused desktop" \
|
|
"KDE Plasma" "Full featured QT based desktop" \
|
|
"LXDE" "Lightweight and efficient desktop" \
|
|
"LXQT" "Lightweight and efficient QT based desktop" \
|
|
"MATE" "Continuation of the GNOME 2 desktop" \
|
|
"Xfce" "Lightweight and modular desktop" 3>&1 1>&2 2>&3)
|
|
if [ $? -eq 0 ]; then
|
|
break
|
|
fi
|
|
elif [ "$DESKTOP" = "Window Manager" ]; then
|
|
GUI=$(dialog --title "Select a Window Manager" \
|
|
--cancel-label "Back" \
|
|
--menu "Select a window manager to install:" 13 75 6 \
|
|
"awesome" "Highly configurable, dynamic window manager" \
|
|
"bspwm" "Tiling window manager based on binary space partitioning" \
|
|
"Fluxbox" "Stacking window manager based on Blackbox" \
|
|
"i3" "Dynamic tiling window manager inspired by wmii" \
|
|
"Openbox" "Highly configurable, stacking window manager" \
|
|
"xmonad" "Dynamic tiling window manager configured in Haskell" 3>&1 1>&2 2>&3)
|
|
if [ $? -eq 0 ]; then
|
|
break
|
|
fi
|
|
else
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ "$DESKTOP" != "None" ]; then
|
|
DESKTOP_PACKAGES+=("${DESKTOP_DEFAULTS[@]}")
|
|
case "$GUI" in
|
|
"Budgie") DESKTOP_PACKAGES+=('budgie-desktop' 'gnome-control-center')
|
|
dialog --title "Install Extras" --yesno "Would you like to \
|
|
install the 'gnome' group?\n\nIt contains additional utilities and \
|
|
applications that integrate well with the Budgie desktop." 8 60
|
|
if [ $? -eq 0 ]; then
|
|
DESKTOP_PACKAGES+=('gnome')
|
|
fi
|
|
xinit_config="export XDG_CURRENT_DESKTOP=Budgie:GNOME ; exec budgie-desktop"
|
|
;;
|
|
"Cinnamon") DESKTOP_PACKAGES+=('cinnamon' 'cinnamon-translations' 'nemo-fileroller')
|
|
xinit_config="exec cinnamon-session"
|
|
;;
|
|
"GNOME") DESKTOP_PACKAGES+=('gnome')
|
|
dialog --title "Install Extras" --yesno "Would you like to \
|
|
install the 'gnome-extra' group?\n\nIt contains additional utilities and \
|
|
applications that integrate well with the GNOME desktop." 8 60
|
|
if [ $? -eq 0 ]; then
|
|
DESKTOP_PACKAGES+=('gnome-extra')
|
|
fi
|
|
xinit_config="exec gnome-session"
|
|
;;
|
|
"KDE Plasma") DESKTOP_PACKAGES+=('plasma')
|
|
dialog --title "Install Extras" --yesno "Would you like \
|
|
to install the 'kde-applications' group?\n\nIt contains additional utilities \
|
|
and applications that integrate well with the Plasma desktop." 8 60
|
|
if [ $? -eq 0 ]; then
|
|
DESKTOP_PACKAGES+=('kde-applications')
|
|
fi
|
|
xinit_config="exec startkde"
|
|
;;
|
|
"LXDE") DESKTOP_PACKAGES+=('lxde')
|
|
xinit_config="exec startlxde"
|
|
;;
|
|
"LXQT") DESKTOP_PACKAGES+=('lxqt' 'breeze-icons')
|
|
xinit_config="exec startlxqt"
|
|
;;
|
|
"MATE") DESKTOP_PACKAGES+=('mate' 'gtk-engines' 'gtk-engine-murrine')
|
|
dialog --title "Install Extras" --yesno "Would you like to \
|
|
install the 'mate-extra' group?\n\nIt contains additional utilities and \
|
|
applications that integrate well with the MATE desktop." 8 60
|
|
if [ $? -eq 0 ]; then
|
|
DESKTOP_PACKAGES+=('mate-extra')
|
|
fi
|
|
xinit_config="exec mate-session"
|
|
;;
|
|
"Xfce") DESKTOP_PACKAGES+=('xfce4')
|
|
dialog --title "Install Extras" --yesno "Would you like to \
|
|
install the 'xfce4-goodies' group?\n\nIt contains additional utilities and \
|
|
applications that integrate well with the Xfce desktop." 8 60
|
|
if [ $? -eq 0 ]; then
|
|
DESKTOP_PACKAGES+=('xfce4-goodies')
|
|
fi
|
|
xinit_config="exec startxfce4"
|
|
;;
|
|
"awesome") DESKTOP_PACKAGES+=('awesome')
|
|
xinit_config="exec awesome"
|
|
;;
|
|
"bspwm") DESKTOP_PACKAGES+=('bspwm' 'sxhkd')
|
|
xinit_config="sxhkd & ; exec bspwm"
|
|
;;
|
|
"Fluxbox") DESKTOP_PACKAGES+=('fluxbox')
|
|
xinit_config="exec startfluxbox"
|
|
;;
|
|
"i3") DESKTOP_PACKAGES+=('i3')
|
|
xinit_config="exec i3"
|
|
;;
|
|
"Openbox") DESKTOP_PACKAGES+=('openbox')
|
|
xinit_config="exec openbox-session"
|
|
;;
|
|
"xmonad") DESKTOP_PACKAGES+=('xmonad' 'xmonad-contrib')
|
|
xinit_config="exec xmonad"
|
|
;;
|
|
esac
|
|
|
|
# GNOME already has networkmanager applet built-in. Plasma uses plasma-nm
|
|
if [ "$GUI" != "GNOME" ]; then
|
|
if [ "$GUI" = "KDE Plasma" ]; then
|
|
DESKTOP_PACKAGES+=('plasma-nm')
|
|
else
|
|
DESKTOP_PACKAGES+=('network-manager-applet' 'gnome-keyring')
|
|
fi
|
|
fi
|
|
|
|
# Check for available bluetooth devices
|
|
if $bluetooth; then
|
|
dialog --title "Enable Bluetooth" \
|
|
--yesno "The installer has detected Bluetooth support on your \
|
|
system.\n\nWould you like to install and enable the Bluetooth service?" 7 65
|
|
if [ $? -eq 0 ]; then
|
|
bluetooth_enabled=true
|
|
DESKTOP_PACKAGES+=('bluez' 'bluez-utils' 'pulseaudio-bluetooth')
|
|
dialog --title "Install Bluetooth Manager" \
|
|
--yesno "Would you like to install a graphical Bluetooth \
|
|
manager?\n\nThe utility that best integrates with the desktop environment \
|
|
you selected will be installed." 8 60
|
|
if [ $? -eq 0 ]; then
|
|
case "$GUI" in
|
|
"Budgie"|"GNOME") DESKTOP_PACKAGES+=('gnome-bluetooth') ;;
|
|
"Cinnamon") DESKTOP_PACKAGES+=('blueberry') ;;
|
|
"KDE Plasma") DESKTOP_PACKAGES+=('bluedevil') ;;
|
|
*) DESKTOP_PACKAGES+=('blueman') ;;
|
|
esac
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
dialog --title "Install a Display Manager" \
|
|
--yesno "Would you like to install a graphical login manager?\n\nIf you \
|
|
select no, 'xinit' will be installed so you can manually start Xorg with the\
|
|
'startx' command." 8 60
|
|
if [ $? -eq 0 ]; then
|
|
DM=$(dialog --title "Install a Display Manager" \
|
|
--menu "Select a display manager to install:" 10 50 3 \
|
|
"gdm" "GNOME Display Manager" \
|
|
"lightdm" "Lightweight Display Manager" \
|
|
"sddm" "Simple Desktop Display Manager" 3>&1 1>&2 2>&3)
|
|
if [ $? -eq 0 ]; then
|
|
dm_enabled=true
|
|
case "$DM" in
|
|
"gdm") DESKTOP_PACKAGES+=('gdm') ;;
|
|
"lightdm") DESKTOP_PACKAGES+=('lightdm' 'lightdm-gtk-greeter' 'lightdm-gtk-greeter-settings') ;;
|
|
"sddm") DESKTOP_PACKAGES+=('sddm') ;;
|
|
esac
|
|
else
|
|
DESKTOP_PACKAGES+=('xorg-xinit')
|
|
dialog --title "xinit" \
|
|
--msgbox "No display manager selected. Installing 'xorg-xinit'. The \
|
|
installer will create a xinitrc file for you.\n\nYou will need to use the \
|
|
'startx' command to start the graphical environment once you login." 9 57
|
|
fi
|
|
else
|
|
DESKTOP_PACKAGES+=('xorg-xinit')
|
|
dialog --title "xinit" \
|
|
--msgbox "No display manager selected. Installing 'xorg-xinit'. The \
|
|
installer will create a xinitrc file for you.\n\nYou will need to use the \
|
|
'startx' command to start the graphical environment once you login." 9 57
|
|
fi
|
|
|
|
# Intel/AMD/NVIDIA drivers are not installed on virtual machines
|
|
if [ "$hypervisor" = "none" ]; then
|
|
if lspci | grep "VGA" | grep -iq "Intel"; then
|
|
DESKTOP_PACKAGES+=('xf86-video-intel')
|
|
fi
|
|
|
|
if lspci | grep "VGA" | grep -iq "NVIDIA"; then
|
|
gpu_driver=$(dialog --title "Install Graphics Driver" --no-cancel \
|
|
--menu "The installer has detected an NVIDIA graphics card on your \
|
|
system.\n\nYou may choose to install either the open-source or proprietary \
|
|
driver. If you are unsure, the proprietary driver usually offers the best \
|
|
performance.\n\nGraphics driver:" 16 70 3 \
|
|
"NVIDIA" "Proprietary NVIDIA driver" \
|
|
"Nouveau" "Open-source Nouveau driver" \
|
|
"None" "-" 3>&1 1>&2 2>&3)
|
|
if [ "$gpu_driver" = "NVIDIA" ]; then
|
|
# Get only the GPU PCI device ID
|
|
gpu_pci_id=$(lspci -nn | grep -ioP 'VGA.*NVIDIA.*\[\K[\w:]+' | sed 's/.*://')
|
|
# Automatically install the correct driver based on the PCI ID data
|
|
if grep -Fq "$gpu_pci_id" "$DIR"/etc/nvidia_390_pci_ids; then
|
|
DESKTOP_PACKAGES+=('nvidia-390xx' 'nvidia-390xx-utils' 'nvidia-390xx-settings')
|
|
elif grep -Fq "$gpu_pci_id" "$DIR"/etc/nvidia_340_pci_ids; then
|
|
# Support for nvidia-340xx has been dropped, use nouveau
|
|
dialog --title "Install Graphics Driver" \
|
|
--msgbox "Proprietary driver support has ended for your graphics \
|
|
card.\n\nThe open-source Nouveau driver will be installed." 7 65
|
|
DESKTOP_PACKAGES+=('xf86-video-nouveau' 'mesa')
|
|
else
|
|
DESKTOP_PACKAGES+=('nvidia' 'nvidia-utils' 'nvidia-settings')
|
|
fi
|
|
else
|
|
DESKTOP_PACKAGES+=('xf86-video-nouveau' 'mesa')
|
|
fi
|
|
elif lspci | grep "VGA" | grep -q "ATI\|AMD"; then
|
|
gpu_driver=$(dialog --title "Install Graphics Driver" --no-cancel \
|
|
--menu "The installer has detected an ATI/AMD graphics card on your \
|
|
system.\nThe appropriate driver to install depends on how modern your GPU \
|
|
is.\n\nIf you are unsure, the ATI driver is generally more stable and \
|
|
supports the majority of ATI/AMD GPUs. If you have one of the latest AMD GPUs \
|
|
(Volcanic Islands or newer), then you should install the AMDGPU \
|
|
driver.\n\nGraphics driver:" 17 75 3 \
|
|
"ATI" "Open-source ATI/AMD Radeon driver" \
|
|
"AMDGPU" "Open-source driver for the latest AMD GPUs" \
|
|
"None" "-" 3>&1 1>&2 2>&3)
|
|
if [ "$gpu_driver" = "ATI" ]; then
|
|
DESKTOP_PACKAGES+=('xf86-video-ati' 'mesa')
|
|
else
|
|
DESKTOP_PACKAGES+=('xf86-video-amdgpu' 'mesa')
|
|
fi
|
|
fi
|
|
else
|
|
dialog --title "Virtual Machine Detected" \
|
|
--msgbox "The installer has detected a virtualized environment: \
|
|
$hypervisor\n\nAny required drivers or utilities will be \
|
|
installed for you." 7 70
|
|
case "$hypervisor" in
|
|
"vmware") DESKTOP_PACKAGES+=('open-vm-tools' 'xf86-video-vmware' 'xf86-input-vmmouse' 'mesa' 'gtkmm' 'gtkmm3') ;;
|
|
"oracle") DESKTOP_PACKAGES+=('virtualbox-guest-utils' 'virtualbox-guest-dkms') ;;
|
|
"parallels") DESKTOP_PACKAGES+=('xf86-video-vesa') ;;
|
|
*) DESKTOP_PACKAGES+=('xf86-video-fbdev') ;;
|
|
esac
|
|
fi
|
|
fi
|
|
}
|
|
|
|
install_base() {
|
|
while true; do
|
|
dialog --title "Installation Summary" \
|
|
--yesno "The base system is ready to be installed on $DISK.\nThe \
|
|
following packages will be installed:\n\n${BASE_PACKAGES[*]} \
|
|
${BASE_ESSENTIALS[*]} ${DESKTOP_PACKAGES[*]}\n\nInstall Parch Linux?" 0 0
|
|
if [ $? -eq 0 ]; then
|
|
clear
|
|
pacstrap /mnt "${BASE_PACKAGES[@]}" "${BASE_ESSENTIALS[@]}" "${DESKTOP_PACKAGES[@]}"
|
|
if [ $? -eq 0 ]; then
|
|
installed=true
|
|
else
|
|
dialog --title "ERROR: Install Failed" \
|
|
--msgbox "Parch Linux failed to install on $DISK.\n\nThe installer \
|
|
encountered an error while executing pacstrap." 7 65
|
|
reset ; exit 1
|
|
fi
|
|
break
|
|
else
|
|
dialog --title "Cancel Installation" \
|
|
--yesno "Are you sure you want to exit to the main menu?" 5 55
|
|
if [ $? -eq 0 ]; then
|
|
main_menu
|
|
fi
|
|
fi
|
|
done
|
|
}
|
|
|
|
# Apply the user's system settings
|
|
configure_system() {
|
|
dialog --infobox "Generating the fstab file..." 3 50
|
|
# Generate the fstab file
|
|
genfstab -U -p /mnt >> /mnt/etc/fstab
|
|
|
|
dialog --infobox "Adjusting time zone and system clock..." 3 50
|
|
# Set the time zone and adjust the hardware clock to the system time (UTC)
|
|
ln -sf /usr/share/zoneinfo/"$ZONE" /mnt/etc/localtime
|
|
if $utc_enabled; then
|
|
arch-chroot /mnt hwclock --systohc --utc
|
|
else
|
|
arch-chroot /mnt hwclock --systohc --localtime
|
|
fi
|
|
|
|
dialog --infobox "Generating locales..." 3 50
|
|
# Set locale and keyboard layout if applicable and generate the locales
|
|
sed -i "s/#en_US.UTF-8/en_US.UTF-8/" /mnt/etc/locale.gen
|
|
if [ "$LOCALE" != "en_US.UTF-8" ]; then
|
|
sed -i "s/#$LOCALE/$LOCALE/" /mnt/etc/locale.gen
|
|
fi
|
|
echo "LANG=$LOCALE" > /mnt/etc/locale.conf
|
|
if [ "$KEYMAP" != "us" ]; then
|
|
echo "KEYMAP=$KEYMAP" > /mnt/etc/vconsole.conf
|
|
if [ "$DESKTOP" != "None" ]; then
|
|
echo -e "Section \"InputClass\"\nIdentifier \"system-keyboard\"\nMatchIsKeyboard \"on\"\nOption \"XkbLayout\" \"$KEYMAP\"\nEndSection" > /mnt/etc/X11/xorg.conf.d/00-keyboard.conf
|
|
fi
|
|
fi
|
|
arch-chroot /mnt locale-gen &> /dev/null
|
|
|
|
dialog --infobox "Configuring system hostname..." 3 50
|
|
# Set the hostname and add a matching entry to /etc/hosts
|
|
echo "$HOST_NAME" > /mnt/etc/hostname
|
|
echo -e "127.0.0.1\tlocalhost\n::1\t\tlocalhost\n127.0.1.1\t$HOST_NAME.localdomain\t$HOST_NAME" >> /mnt/etc/hosts
|
|
|
|
# Modify mkinitcpio.conf hooks if required and generate a new initramfs
|
|
if [ "$PARTITION_LAYOUT" != "Basic" ]; then
|
|
dialog --infobox "Recreating the initramfs image..." 3 50
|
|
if [ "$PARTITION_LAYOUT" = "LVM" ]; then
|
|
sed -i "s/HOOKS=.*/HOOKS=(base udev autodetect modconf block lvm2 filesystems fsck)/" /mnt/etc/mkinitcpio.conf
|
|
elif [ "$PARTITION_LAYOUT" = "Encrypted" ]; then
|
|
sed -i "s/HOOKS=.*/HOOKS=(base udev autodetect keyboard keymap consolefont modconf block encrypt lvm2 filesystems fsck)/" /mnt/etc/mkinitcpio.conf
|
|
fi
|
|
arch-chroot /mnt mkinitcpio -p linux &> /dev/null
|
|
fi
|
|
|
|
dialog --infobox "Installing GRUB to $DISK..." 3 50
|
|
# Append the required kernel parameters to unlock an encrypted partition
|
|
if [ "$PARTITION_LAYOUT" = "Encrypted" ]; then
|
|
root_part_uuid=$(blkid -s UUID -o value "$ROOT_PART")
|
|
sed -i "s/GRUB_CMDLINE_LINUX=\"\(.*\)\"/GRUB_CMDLINE_LINUX=\"\1 cryptdevice=UUID=$root_part_uuid:$CRYPT_DEVICE_NAME root=\/dev\/mapper\/$LVM_GROUP-$LVM_ROOT\"/" /mnt/etc/default/grub
|
|
fi
|
|
|
|
# Remove the 'quiet' parameter to have a verbose output during boot
|
|
sed -i 's/\(GRUB_CMDLINE_LINUX_DEFAULT=\).*/\1\"\"/g' /mnt/etc/default/grub
|
|
sed -i s/GRUB_DISTRIBUTOR=\"Arch\"/GRUB_DISTRIBUTOR=\"Parch\"/g etc/default/grub
|
|
|
|
# Install GRUB to the target disk and generate the main configuration file
|
|
if $UEFI; then
|
|
arch-chroot /mnt grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB &> /dev/null
|
|
else
|
|
arch-chroot /mnt grub-install --target=i386-pc "$DISK" &> /dev/null
|
|
fi
|
|
dialog --infobox "Generating the GRUB configuration file..." 3 50
|
|
arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg &> /dev/null
|
|
|
|
dialog --infobox "Configuring user accounts..." 3 50
|
|
# Set the root password and create a user account
|
|
arch-chroot /mnt chpasswd <<<"root:$root_passwd"
|
|
# User is added to the 'wheel' group and is granted root privileges with sudo
|
|
if [ -z "$FULL_NAME" ]; then
|
|
arch-chroot /mnt useradd -m -g users -G wheel -s /bin/bash "$USER_NAME"
|
|
else
|
|
arch-chroot /mnt useradd -m -g users -G wheel -c "$FULL_NAME" -s /bin/bash "$USER_NAME"
|
|
fi
|
|
arch-chroot /mnt chpasswd <<<"$USER_NAME:$user_passwd"
|
|
sed -i '/^# %wheel ALL=(ALL:ALL) ALL/s/^# //' /mnt/etc/sudoers
|
|
|
|
# Uncomment multilib in pacman.conf and refresh the database
|
|
if $multilib; then
|
|
sed -i "/\[multilib\]/,/Include/"'s/^#//' /mnt/etc/pacman.conf
|
|
dialog --infobox "Refreshing pacman database..." 3 50
|
|
arch-chroot /mnt pacman -Sy &> /dev/null
|
|
fi
|
|
|
|
dialog --infobox "Enabling NetworkManager service..." 3 50
|
|
arch-chroot /mnt systemctl enable NetworkManager.service &> /dev/null
|
|
|
|
if $bluetooth_enabled; then
|
|
dialog --infobox "Enabling Bluetooth service..." 3 50
|
|
arch-chroot /mnt systemctl enable bluetooth.service &> /dev/null
|
|
fi
|
|
|
|
# xinitrc is created in user's home directory if display manager is not set
|
|
if [ "$DESKTOP" != "None" ] && ! $dm_enabled; then
|
|
dialog --infobox "Generating the xinitrc file..." 3 50
|
|
echo "$xinit_config" > /mnt/home/"$USER_NAME"/.xinitrc
|
|
elif $dm_enabled; then
|
|
dialog --infobox "Enabling display manager service..." 3 50
|
|
arch-chroot /mnt systemctl enable "$DM".service &> /dev/null
|
|
fi
|
|
|
|
if [ "$hypervisor" != "none" ]; then
|
|
if [ "$hypervisor" = "oracle" ]; then
|
|
dialog --infobox "Enabling VirtualBox modules..." 3 50
|
|
arch-chroot /mnt systemctl enable vboxservice.service &> /dev/null
|
|
elif [ "$hypervisor" = "vmware" ]; then
|
|
dialog --infobox "Enabling VMware Open-VM-Tools..." 3 50
|
|
arch-chroot /mnt systemctl enable vmtoolsd.service &> /dev/null
|
|
arch-chroot /mnt systemctl enable vmware-vmblock-fuse.service &> /dev/null
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# System power menu
|
|
reboot_system() {
|
|
if $installed; then
|
|
while true; do
|
|
choice=$(dialog --title "Reboot System" --nocancel \
|
|
--menu "Parch Linux has finished installing.\nYou must restart your \
|
|
system to boot Arch.\n\nPlease select one of the following options:" 13 60 3 \
|
|
"Reboot" "Reboot system" \
|
|
"Poweroff" "Poweroff system" \
|
|
"Exit" "Unmount system and exit to CLI" 3>&1 1>&2 2>&3)
|
|
|
|
dialog --infobox "Unmounting partitions on /mnt..." 3 50
|
|
umount -R /mnt
|
|
case "$choice" in
|
|
"Reboot") reset ; reboot ; exit ;;
|
|
"Poweroff") reset ; poweroff ; exit ;;
|
|
"Exit") reset ; exit ;;
|
|
esac
|
|
done
|
|
else
|
|
dialog --title "Reboot System" \
|
|
--yesno "The installation is incomplete.\n\nAre you sure you want to \
|
|
reboot your system?" 7 60
|
|
if [ $? -eq 0 ]; then
|
|
check_mountpoints
|
|
reset ; reboot ; exit
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Menu which allows the user to navigate the installer
|
|
main_menu() {
|
|
while true; do
|
|
choice=$(dialog --title "Main Menu" --nocancel \
|
|
--menu "Select an option below using the UP/DOWN keys and SPACE or \
|
|
ENTER.\nAlternate keys may also be used: '+', '-', and TAB." 19 70 11 \
|
|
"KEYMAP" "Set the keyboard layout" \
|
|
"LOCALE" "Set the system locale" \
|
|
"TIMEZONE" "Set the system time zone" \
|
|
"HOSTNAME" "Set the system's hostname" \
|
|
"ROOT PASSWORD" "Set the root password" \
|
|
"CREATE USER" "Create your user account" \
|
|
"PARTITION" "Partition the installation drive" \
|
|
"UPDATE MIRRORS" "Update the pacman mirror list" \
|
|
"INSTALL" "Install Parch Linux" \
|
|
"REBOOT" "Reboot system" \
|
|
"EXIT" "Exit Parch Linux Installer" 3>&1 1>&2 2>&3)
|
|
|
|
case "$choice" in
|
|
"KEYMAP") set_keymap ;;
|
|
"LOCALE") set_locale ;;
|
|
"TIMEZONE") set_timezone ;;
|
|
"HOSTNAME") set_hostname ;;
|
|
"ROOT PASSWORD") set_root_passwd ;;
|
|
"CREATE USER") create_user ;;
|
|
"PARTITION") if $mounted; then
|
|
dialog --title "Partition the Disks" \
|
|
--yesno "A disk is mounted on the system and ready for \
|
|
installation.\n\nAre you sure you want to return to partitioning?" 7 70
|
|
if [ $? -eq 0 ]; then
|
|
mounted=false
|
|
prepare_disk
|
|
fi
|
|
else
|
|
prepare_disk
|
|
fi
|
|
;;
|
|
"UPDATE MIRRORS") update_mirrorlist ;;
|
|
"INSTALL") if $mounted; then
|
|
configure_install
|
|
install_base
|
|
configure_system
|
|
reboot_system
|
|
else
|
|
dialog --title "ERROR: No Filesytem Mounted" \
|
|
--yesno "The installer was unable to detect a \
|
|
mounted filesystem.\n\nReturn to partitioning?" 7 60
|
|
if [ $? -eq 0 ]; then
|
|
prepare_disk
|
|
fi
|
|
fi
|
|
;;
|
|
"REBOOT") reboot_system ;;
|
|
"EXIT") reset ; exit ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
main() {
|
|
init
|
|
check_connection
|
|
set_keymap
|
|
set_locale
|
|
set_timezone
|
|
set_hostname
|
|
set_root_passwd
|
|
create_user
|
|
prepare_disk
|
|
update_mirrorlist
|
|
configure_install
|
|
install_base
|
|
configure_system
|
|
reboot_system
|
|
}
|
|
|
|
main
|