Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@gazorby
Last active March 5, 2020 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gazorby/e3589c05e3cef8516a21f37114645b09 to your computer and use it in GitHub Desktop.
Save gazorby/e3589c05e3cef8516a21f37114645b09 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# This script assumes networking is up
############################################################
# CONFIGURATION START
############################################################
############
# MANDATORY
############
_HOSTNAME="smallbox"
_KEYMAP="fr"
_SYSTEM_LANGUAGE="en_US" # Only UTF-8 variant will be used
_TIMEZONE="Europe/Paris"
_CPU="intel !amd"
_DISPLAY_DRIVER="intel !nvidia !amdgpu !ati !nouveau"
_BOOTLOADER="refind-efi"
_CRYPT_PASSWD="archlinux"
_CRYPT_PASSWD_RETYPE="archlinux"
_ERASE_DRIVE="true"
# required if _ERASE_DRIVE is false, ignored otherwise
_PART_EFI=/dev/sda1
_PART_SWAP=/dev/sda2
_PART_SYSTEM=/dev/sda3
# required if _ERASE_DRIVE is true, ignored otherwise
_DRIVE=/dev/sda
_PART_EFI_SIZE="550" # EFI partition size in MiB
_PART_SWAP_SIZE="12" # Size in GiB
_PART_SYSTEM_LABEL="cryptsystem" # label of system partition
_PART_SWAP_LABEL="cryptswap" # label of swap partition
o=defaults,x-mount.mkdir
o_btrfs=$o,compress=lzo,ssd,noatime
###########
#OPTIONNAL
###########
_DESKTOP="false"
_BLUETOOTH="true"
_AUR="false"
# Will be ignored if _DESKTOP is false
_DE="!gnome !kde !xfce"
# Will be ignored if _DESKTOP is false
_WINDOW_MANAGER="!gdm !sddm !lightdm"
# System language may not be included. Only UTF-8 variant will be used
_AVAILABLE_LANGUAGES="en_US fr_FR"
# If empty, no new user will be created
_USER="gazorby"
# Change the default shell for the new user (if empty, bash will be used)
_SHELL="fish"
# Change this!
_ROOT_PASSWD="archlinux"
_ROOT_PASSWD_RETYPE="archlinux"
_USER_PASSWD="archlinux"
_USER_PASSWD_RETYPE="archlinux"
# Extra systems packages
_PKGS_SYSTEM="openssh git man-db man-pages texinfo sudo vim curl ufw ripgrep fd exa highlight yarn $_SHELL"
# Will be installed if _DESKTOP is '1'
_PKGS_DESKTOP_BASE="xorg-server xorg-xinit xdg-user-dirs mesa xterm otf-fira-sans noto-fonts-emoji ttf-croscore ttf-roboto vlc firefox"
_PKGS_AUR_PKGS="protonmail-bridge authy bitwarden-bin direnv jetbrains-toolbox spotify ttf-roboto-slab visual-studio-code-bin starship-bin"
# Will be installed if _DE is set to 'gnome'
_PKGS_GNOME_EXTRAS="gvfs chrome-gnome-shell gnome-tweaks evolution materia-gtk-theme tilix"
# Will be installed if _DE is set to 'kde'
_PKGS_KDE_EXTRAS="kde-applications materia-kde"
# Will be installed if _DE is set to 'xfce'
_PKGS_XFCE_EXTAS="gvfs materia-gtk-theme"
# Other packages
_PKGS_CUSTOM="gdm gnome-shell tilix gnome-control-center"
############################################################
# CONFIGURATION END
############################################################
############################################################
# Global variables
############################################################
_PKGS="$_PKGS_SYSTEM $_PKGS_CUSTOM"
CHROOT_RUN="arch-chroot /mnt"
START_DATE="$(date '+%Y-%m-%d--%H:%M:%S')"
PROGNAME=${0##*/} # ./name.sh ==> name.sh
TEMP_DIR="$(mktemp -d /tmp/XXXXXXX)" # Temporary directory
LOG_FILE=/tmp/log_"$PROGNAME"_["$START_DATE"].txt # Store logs
DEBUG_LOG_FILE=/tmp/log_debug_"$PROGNAME"_["$START_DATE"].txt # Store logs
OUT_END="$TEMP_DIR/out_end.txt" # Store output to display after script execution
OUT_TMP="$TEMP_DIR/out_tmp.txt"
LOCKFILE=/tmp/script_lockfile.lock
LOCKFD=99
_SERVER_TEST=google.com
# COLORS used in output
NORMAL="\e[0m"
GREEN="\e[32m"
YELLOW="\e[33m"
RED="\e[31m"
BLUE="\e[34m"
CYAN="\e[36m"
BOLD="\e[1m"
# Options
QUIET="false"
LOCK="false"
LOG="true"
NOCONFIRM="false"
priority_options_pattern='@(--debug|-h|--help|--strict|--lock|--logs)'
############################################################
# PRIVATE FUNCTIONS
############################################################
_lock() { flock -$1 $LOCKFD; }
_no_more_locking() { _lock u; _lock xn && rm -f $LOCKFILE; }
_prepare_locking() { eval "exec $LOCKFD>\"$LOCKFILE\""; }
# PRIVATE (better to use use shortcuts)
# Display logs
#
# Arguments :
#
# $1 (required): loglevel
# - info, warning, error, step and info will be
# displayed like this : " [colored loglevel] message "
# - title will show " ==> bold title "
# - none will only show the message
# Any other loglevel (except title and none) will be green
#
# $2 (required): where to write log message
# - out : display the log immediatly
# - exit : log will be displayed on script exit
# - persist : write to a log file
# - tmp : write logs to a temporary file used to display them later
function _log () {
local message="$3"
local loglevel="$1"
local where="$2"
local loglevel_format
case "$loglevel" in
warning)
loglevel_format="[${YELLOW}warning${NORMAL}]"
;;
error)
loglevel_format="[${RED}error${NORMAL}]"
;;
none)
loglevel_format=""
;;
info|*)
loglevel_format="[${GREEN}info${NORMAL}]"
;;
esac
if [[ $loglevel = title && $where != persist ]]; then
# ==> title
loglevel_format="\n$BLUE==> ${NORMAL}${BOLD}%s${NORMAL}"
fi
# output - [loglevel] message
if [[ $where = now && $QUIET = false ]]; then
# No newline if info is a step
if [[ $loglevel = step ]]; then
printf "$loglevel_format %s" "$message"
else
printf "$loglevel_format %s\n" "$message"
fi
# Write logs in temp file which is read on script exit
elif [[ $where =~ exit|tmp && $QUIET = false ]]; then
message="$(str_add_prefix "$message" ' ')"
local out=""
case "$where" in
exit)
out="$OUT_END"
;;
tmp)
out="$OUT_TMP"
;;
esac
printf "$loglevel_format\n%s\n" "$message" >> "$out"
fi
if [[ $LOG = true ]]; then
loglevel=${loglevel//title/info}
local date="[$(date '+%Y-%m-%d %H:%M:%S')]"
printf "%s\t%s\n" "$date[$loglevel]" "${@:3}" >> $LOG_FILE
fi
}
############################################################
# PUBLIC FUNCTIONS
############################################################
# display script usage
#
# Arguments :
# $1 (optionnmal): Cause that showing up this help
function usage() {
# Empty string if param 1 empty
local error=${1:-""}
printf ""
printf "\e[31m%s\e[0m\n\n" "$error"
printf "%s\n\n" "Usage :"
printf "\e[1m\e[33m%s\e[0m\n" "./$PROGNAME.sh [option]"
printf "%s\n" ""
printf "\t\e[1m%s\e[0m\t%s\n" "--debug " "Run script in debug mode (All executed commands are displayed)"
printf "\t\e[1m%s\e[0m\t%s\n" "--lock " "Lock the script (only one instance can be executed)"
printf "\t\e[1m%s\e[0m\t%s\n" "--no-logs " "Don't write logs"
printf "\t\e[1m%s\e[0m\t%s\n" "--check | -c " "Run sanity checks"
printf "\t\e[1m%s\e[0m\t%s\n" "--noconfirm " "No prompts"
printf "\t\e[1m%s\e[0m\t%s\n" "--partition | -p" "Create partitions"
printf "\t\e[1m%s\e[0m\t%s\n" "--format | -f " "Format partitions"
printf "\t\e[1m%s\e[0m\t%s\n" "--mount | -m " "Mount partitions"
printf "\t\e[1m%s\e[0m\t%s\n" "--strict " "Run script in scrict mode (enable error when trying to expand an unset parameter)"
printf "\t\e[1m%s\e[0m\t%s\n" "-h --help " "Show this help"
}
# Log shortcut functions
info () { _log info now "$*"; }
error () { _log error now "$*"; }
warning () { _log warning now "$*"; }
warning_keep () { _log warning tmp "$*"; }
error_keep () { _log error tmp "$*"; }
title () { _log title now "$*"; }
on_exit () { _log "$1" exit "${@:2}"; }
print_kept_logs () { cat "$OUT_TMP"; }
clear_kept_logs () { truncate -s 0 "$OUT_TMP"; }
# Trim whitespace from a string
#
# Arguments :
# $* (required): String to be trimmed
function trim() {
local var="$*"
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"
# remove space whitespace inside string
var="${var// /}"
printf "$var"
}
function str_add_brefore_match() {
local value="$2"
local match="$3"
printf "${1%%${match}*}${value}${match}${1##*${match}}"
}
function str_add_prefix() {
local string="____ ____$1"
local value="$2"
printf "${string%%____ ____*}${2}${string##*____ ____}"
}
# Obtain an exclusive lock immediately or exit
function exlock_now() {
if ! _lock xn; then
on_exit error "Couldn't acquire the lock!"
exit 1
fi
}
# Locking shortcuts
exlock() { _lock x; } # obtain an exclusive lock
shlock() { _lock s; } # obtain a shared lock
unlock() { _lock u; } # drop a lock
function check_var_value() {
local SEVERITY="$1"
local NAME="$2"
local VALUE="$3"
local MESSAGE="${4}"
if [ -z "$VALUE" ]; then
if [[ $SEVERITY = error ]]; then
on_exit error "$NAME variable must have a value. -- $MESSAGE"
exit 1
elif [[ $SEVERITY = warning ]]; then
warning_keep "$NAME variable is no set. -- $MESSAGE"
fi
return 1
fi
}
function check_var_equals() {
local SEVERITY=$1
local NAME1=$2
local NAME2=$3
local VALUE1=$4
local VALUE2=$5
if [[ $VALUE1 != $VALUE2 ]]; then
if [[ $SEVERITY = error ]]; then
on_exit error "$NAME1 and $NAME2 must be equal [$VALUE1, $VALUE2]."
exit 1
elif [[ $SEVERITY = warning ]]; then
warning_keep "$NAME1 and $NAME2 are not equal [$VALUE1, $VALUE2]."
fi
return 1
fi
}
function check_var_match() {
local SEVERITY=$1
local NAME=$2
local VALUE=$3
local PATTERN=$4
if ! [[ $VALUE =~ $PATTERN ]]; then
if [[ $SEVERITY = error ]]; then
on_exit error "$NAME doesn't match the required pattern [$PATTERN]"
exit 1
elif [[ $SEVERITY = warning ]]; then
warning_keep "$NAME doesn't match the required pattern [$PATTERN]"
fi
return 1
fi
}
function check_var_bool() {
local SEVERITY=$1
local NAME=$2
local VALUE=$3
check_var_match "$SEVERITY" "$NAME" "$VALUE" "(^true$)|(^false$)"
if [[ $? != 0 ]]; then
return 1
else
return 0
fi
}
function sanitize_var() {
var="$1"
# remove disabled
var="${var//\!+([![:space:]])/}"
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"
printf "$var"
}
function uncomment() {
local file="$2"
local pattern="$1"
sed -i "/$pattern/s/^#//" $file
}
function prompt_yes_no() {
local message=$1
local default=${2:-"none"}
if [[ $NOCONFIRM = true ]]; then
return
fi
printf "$message [yes/no] default=$default\n"
read res
if [[ -z $res && $default != none ]]; then
if [[ $default = yes ]]; then
return 0
else
return 1
fi
fi
while ! [[ $res =~ (^yes$)|(^no$) ]]; do
printf "please, type \"yes\" or \"no\""
read res
done
if [[ $res = yes ]]; then
return 0
else
return 1
fi
}
function pacman_install() {
local PACKAGES=$1
for VARIABLE in {1..5}
do
arch-chroot /mnt pacman -Syu --noconfirm --needed $PACKAGES
if [ $? == 0 ]; then
break
else
info "Waiting before retrying"
sleep 10
fi
done
}
function part_prepare() {
if [[ -e /dev/mapper/system ]]; then
cryptsetup close /dev/mapper/system
fi
if [[ -e /dev/mapper/swap ]]; then
cryptsetup remove "$_PART_SWAP_LABEL"
fi
umount -R /mnt
}
function part_create() {
if [[ $_ERASE_DRIVE = true ]]; then
sgdisk --zap-all $_DRIVE
wipefs --all $_DRIVE
sgdisk --clear \
--new=1:0:+"$_PART_EFI_SIZE"MiB --typecode=1:ef00 --change-name=1:EFI \
--new=2:0:+"$_PART_SWAP_SIZE"GiB --typecode=2:8200 --change-name=2:"$_PART_SWAP_LABEL" \
--new=3:0:0 --typecode=3:8300 --change-name=3:"$_PART_SYSTEM_LABEL" \
$_DRIVE
fi
}
function part_format() {
title "Format partitions"
if [[ $_ERASE_DRIVE = true ]]; then
mkfs.fat -F32 -n EFI /dev/disk/by-partlabel/EFI
printf "$_CRYPT_PASSWD\n$_CRYPT_PASSWD_RETYPE" | cryptsetup luksFormat --align-payload=8192 -s 256 -c aes-xts-plain64 /dev/disk/by-partlabel/"$_PART_SYSTEM_LABEL"
printf "$_CRYPT_PASSWD\n$_CRYPT_PASSWD_RETYPE" | cryptsetup open /dev/disk/by-partlabel/"$_PART_SYSTEM_LABEL" system
cryptsetup open --type plain --key-file /dev/urandom /dev/disk/by-partlabel/"$_PART_SWAP_LABEL" swap
# create the swap partition
mkswap -L swap /dev/mapper/swap
swapon -L swap
# format the system partition with btrfs. Inside we will use subvolumes
mkfs.btrfs --force --label system /dev/mapper/system
# mount the newly created partition
mount -t btrfs LABEL=system /mnt
else
printf "$_CRYPT_PASSWD\n$_CRYPT_PASSWD_RETYPE" | cryptsetup luksFormat --align-payload=8192 -s 256 -c aes-xts-plain64 "$_PART_SYSTEM"
printf "$_CRYPT_PASSWD\n$_CRYPT_PASSWD_RETYPE" | cryptsetup open "$_PART_SYSTEM" system
cryptsetup open --type plain --key-file /dev/urandom "$_PART_SWAP" swap
fi
# open the encrypted partition with label system
# If something fails and you need to restart your system this is the line you need to open your partition again later on.
# I'l mark those commands with an asterisk should you need to reboot and start over with eg. the boot option.
# *
# open the swap partition with a random key
# create the swap partition
mkswap -L swap /dev/mapper/swap
swapon -L swap
# format the system partition with btrfs. Inside we will use subvolumes
mkfs.btrfs --force --label system /dev/mapper/system
# mount the newly created partition
mount -t btrfs LABEL=system /mnt
# and create the neccessary subvolumes
btrfs subvolume create /mnt/root
btrfs subvolume create /mnt/home
btrfs subvolume create /mnt/snapshots
}
function part_mount() {
title "Mount partitions"
# then unmount to mount again with subvolumes
umount -R /mnt
mount -t btrfs -o subvol=root,$o_btrfs LABEL=system /mnt
mount -t btrfs -o subvol=home,$o_btrfs LABEL=system /mnt/home
mount -t btrfs -o subvol=snapshots,$o_btrfs LABEL=system /mnt/.snapshots
# create a boot partition and mount as well
mkdir /mnt/boot
if [[ $_ERASE_DRIVE = true ]]; then
mount LABEL=EFI /mnt/boot;
else
mount $_PART_EFI /mnt/boot
fi
}
function part_umount() {
cryptsetup close /dev/mapper/system
umount -R /mnt
}
function set_packages() {
title "Set package list"
_PKGS="$_PKGS $_BOOTLOADER"
if [[ $_CPU =~ ^(intel|amd)$ ]]; then
_PKGS="$_PKGS ${_CPU}-ucode"
fi
if [[ $_BLUETOOTH = true ]]; then
_PKGS="$_PKGS bluez"
fi
if [[ $_DESKTOP = true ]]; then
_PKGS="$_PKGS $_PKGS_DESKTOP_BASE"
if [[ $_DE = gnome ]]; then
_PKGS="$_PKGS gnome $_PKGS_GNOME_EXTRAS"
elif [[ $_DE = kde ]]; then
_PKGS="$_PKGS plasma $_PKGS_KDE_EXTRAS"
elif [[ $_DE = xfce ]]; then
_PKGS="$_PKGS xfce4 $_PKGS_XFCE_EXTAS"
fi
_PKGS="$_PKGS $_WINDOW_MANAGER"
fi
case "$_DISPLAY_DRIVER" in
"nvidia" )
_PKGS="$_PKGS nvidia"
;;
"nvidia-lts" )
_PKGS="$_PKGS nvidia-lts"
;;
"nvidia-dkms" )
_PKGS="$_PKGS nvidia-dkms"
;;
"nvidia-390xx" )
_PKGS="$_PKGS nvidia-390xx"
;;
"nvidia-390xx-lts" )
_PKGS="$_PKGS nvidia-390xx-lts"
;;
"nvidia-390xx-dkms" )
_PKGS="$_PKGS nvidia-390xx-dkms"
;;
esac
}
function packages_aur() {
if [[ $_AUR = true ]]; then
pacman_install "git"
arch-chroot /mnt sed -i 's/%wheel ALL=(ALL:ALL) ALL/%wheel ALL=(ALL) NOPASSWD: ALL/' /etc/sudoers
arch-chroot /mnt bash -c "printf \"$_USER_PASSWD\n$_USER_PASSWD\n$_USER_PASSWD\n$_USER_PASSWD\n\" | su $_USER -s /bin/bash -c \"cd /home/$_USER && git clone https://aur.archlinux.org/yay.git && (cd yay && makepkg -si --noconfirm) && rm -rf yay\""
arch-chroot /mnt sed -i 's/%wheel ALL=(ALL) NOPASSWD: ALL/%wheel ALL=(ALL:ALL) ALL/' /etc/sudoers
if [[ -n "$_AUR_PKGS" ]]; then
aur_install "$_AUR_PKGS"
fi
fi
}
function aur_install() {
local packages=$1
for VARIABLE in {1..5}
do
arch-chroot /mnt bash -c "printf \"$_USER_PASSWD\n$_USER_PASSWD\n$_USER_PASSWD\n$_USER_PASSWD\n\" | su $_USER -c \"yay -Syu --noconfirm --needed $packages\""
if [ $? == 0 ]; then
break
else
sleep 10
fi
done
}
function conf_locale() {
info "Uncommenting in /etc/locale.gen [$_AVAILABLE_LANGUAGES]"
for lang in $_AVAILABLE_LANGUAGES; do
uncomment "${lang}.UTF-8 UTF-8" /mnt/etc/locale.gen
done
# be sure to have system language available
uncomment "${_SYSTEM_LANGUAGE}.UTF-8 UTF-8" /mnt/etc/locale.gen
arch-chroot /mnt locale-gen
arch-chroot /mnt localectl set-locale "LANG=${_SYSTEM_LANGUAGE}.UTF-8"
}
function conf_time_date() {
info "Enable network time synchronization"
arch-chroot /mnt timedatectl set-ntp 1
info "Set timezone to $_TIMEZONE"
arch-chroot /mnt timedatectl set-timezone $_TIMEZONE
}
function conf_hostname() {
info "Set hostname to $_HOSTNAME"
arch-chroot /mnt hostnamectl set-hostname $_HOSTNAME
}
function conf_keymap() {
info "Set keymap to $_KEYMAP"
arch-chroot /mnt printf "%s" "KEYMAP=$_KEYMAP" > /etc/vconsole.conf
}
function conf_hosts() {
info "Write hosts file"
arch-chroot /mnt printf "%s\n" \
"127.0.0.1 localhost" \
"::1 localhost" \
"127.0.1.1 $_HOSTNAME.localdomain $_HOSTNAME" \
>> /etc/hosts
}
function conf_mkinitcpio() {
title "Edit mkinitcpio configuration"
local mkinitcpio_hooks="base systemd sd-vconsole modconf keyboard keymap block filesystems btrfs sd-encrypt fsck"
arch-chroot /mnt sed -i "s/MODULES=()/MODULES=($MODULES)/" /etc/mkinitcpio.conf
# set hooks
arch-chroot /mnt sed -i "s/HOOKS=.*/HOOKS=\"$mkinitcpio_hooks\"/g" /etc/mkinitcpio.conf
# recreate initramfs image
arch-chroot /mnt mkinitcpio -P
}
function conf_custom() {
info "Edit pacman.conf to colorize output"
uncomment "Color" /mnt/etc/pacman.conf
}
function new_user() {
title "Add new user $_USER"
if [[ -n $_USER ]]; then
arch-chroot /mnt useradd -m -G wheel,storage,optical $_USER
if ! [[ -z $_SHELL ]]; then
arch-chroot /mnt usermod -s /usr/bin/$_SHELL $_USER
fi
printf "$_USER_PASSWD\n$_USER_PASSWD_RETYPE" | arch-chroot /mnt passwd $_USER
printf "%s" "%wheel ALL=(ALL:ALL) ALL" >> /mnt/etc/sudoers
fi
}
function enable_services() {
title "Enabling systemd services"
arch-chroot /mnt systemctl enable NetworkManager.service
if [[ -n $_WINDOW_MANAGER ]]; then
info "Enabling $_WINDOW_MANAGER"
case "$_WINDOW_MANAGER" in
gdm)
arch-chroot /mnt systemctl enable gdm.service
;;
lightdm)
arch-chroot /mnt systemctl enable lightdm.service
;;
sddm)
arch-chroot /mnt systemctl enable sddm.service
;;
esac
fi
if [[ $_BLUETOOTH = true ]]; then
info "Enabling bluetooth"
arch-chroot /mnt systemctl enable bluetooth.service
fi
}
function bootloader_refind() {
title "installing refind bootloader"
local part_system_uuid=""
if [[ $_ERASE_DRIVE = false ]]; then
part_system_uuid=$(trim $(lsblk -fsno UUID $_PART_SYSTEM))
else
part_system_uuid=$(trim $(lsblk -fsno UUID ${_DRIVE}3))
fi
local subvol_root_uuid=$(trim $(blkid --output value --match-tag UUID /dev/mapper/system))
# backup existing conf
mv /mnt/boot/EFI/refind/refind.conf /mnt/boot/EFI/refind/refind.bak
arch-chroot /mnt refind-install
printf "%s\n" \
"timeout 20" \
"use_graphics_for windows # Specify the simpler mac-style behaviour" \
"also_scan_dirs +,@/ # Search for boot loaders in the specified directory" \
> /mnt/boot/EFI/refind/refind.conf
printf "%s" "\"Boot with standard options\" \"rd.luks.name=$part_system_uuid=cryptsystem root=UUID=$subvol_root_uuid rootflags=subvol=root initrd=/${_CPU}-ucode.img initrd=/initramfs-linux.img\"" \
> /mnt/boot/refind_linux.conf
}
function fstab() {
title "Generating fstab"
# Identify partition with labels
genfstab -L -p /mnt >> /mnt/etc/fstab
# fix fstab so swap partition can be found again
arch-root /mnt sed -i s+LABEL=swap+/dev/mapper/swap+ /etc/fstab
# tell crypttab which partition to mount
printf "\n%s" "swap /dev/disk/by-partlabel/cryptswap /dev/urandom swap,cipher=aes-cbc-essiv:sha256,size=256" >> /mnt/etc/crypttab
}
function check_internet() {
if nc -zw1 $_SERVER_TEST 443 && printf | openssl s_client -connect $_SERVER_TEST:443 2>&1 |awk '
handshake && $1 == "Verification" { if ($2=="OK") exit; exit 1 }
$1 $2 == "SSLhandshake" { handshake = 1 }'
then
info "Connected to internet!"
return 0
fi
}
function check_packages_exists() {
title "Check if packages exists"
pacman -Sy
for package in $_PKGS; do
info "Checking for $package in packages"
if ! pacman -Si $package >/dev/null; then
info "Checking for $package in groups"
if ! pacman -Sg $package >/dev/null; then
on_exit error "Package $package was not found in repositories!"
printf "\n"
exit 1
fi
fi
done
printf "\n"
}
function sanitize() {
title "Sanitize variables"
_PART_EFI_SIZE=$(sanitize_var "$_PART_EFI_SIZE")
_PART_SWAP_SIZE=$(sanitize_var "$_PART_SWAP_SIZE")
_PART_SYSTEM_LABEL=$(sanitize_var "$_PART_SYSTEM_LABEL")
_PART_SWAP_LABEL=$(sanitize_var "$_PART_SWAP_LABEL")
_DRIVE=$(sanitize_var "$_DRIVE")
_AVAILABLE_LANGUAGES=$(sanitize_var "$_AVAILABLE_LANGUAGES")
_SYSTEM_LANGUAGE=$(sanitize_var "$_SYSTEM_LANGUAGE")
_HOSTNAME=$(sanitize_var "$_HOSTNAME")
_PART_SWAP_SIZE=$(sanitize_var "$_PART_SWAP_SIZE")
_ROOT_PASSWD=$(sanitize_var "$_ROOT_PASSWD")
_BOOTLOADER=$(sanitize_var "$_BOOTLOADER")
_USER=$(sanitize_var "$_USER")
_DESKTOP=$(sanitize_var "$_DESKTOP")
_WINDOW_MANAGER=$(sanitize_var "$_WINDOW_MANAGER")
_DISPLAY_DRIVER=$(sanitize_var "$_DISPLAY_DRIVER")
_CPU=$(sanitize_var "$_CPU")
_DE=$(sanitize_var "$_DE")
}
function check() {
title "Check variables"
# if ! check_internet; then
# on_exit error "No internet connection!"
# exit 1
# fi
check_var_value error "_AVAILABLE_LANGUAGES" "$_AVAILABLE_LANGUAGES"
check_var_value error "_SYSTEM_LANGUAGE" "$_SYSTEM_LANGUAGE"
check_var_value error "_HOSTNAME" "$_HOSTNAME"
check_var_value error "_PART_SWAP_SIZE" "$_PART_SWAP_SIZE"
check_var_value error "_ROOT_PASSWD" "$_ROOT_PASSWD"
check_var_value error "_CRYPT_PASSWD" "$_CRYPT_PASSWD" "Partition must be encrypted"
check_var_value error "_BOOTLOADER" "$_BOOTLOADER"
check_var_value error "_DISPLAY_DRIVER" "$_DISPLAY_DRIVER"
check_var_bool error "_ERASE_DRIVE" "$_ERASE_DRIVE"
check_var_bool error "_BLUETOOTH" "$_BLUETOOTH"
check_var_bool error "_AUR" "$_AUR"
check_var_bool error "_DESKTOP" "$_DESKTOP"
if [[ $_ERASE_DRIVE = false ]]; then
check_var_value error "_PART_EFI" "$_PART_EFI" "EFI partition needed since _ERASE_DRIVE is false"
check_var_value error "_PART_SWAP" "$_PART_SWAP" "swap partition needed since _ERASE_DRIVE is false"
check_var_value error "_PART_SYSTEM" "$_PART_SYSTEM" "system partition needed since _ERASE_DRIVE is false"
else
check_var_value error "_PART_EFI_SIZE" "$_PART_EFI_SIZE" "EFI partition size needed since _ERASE_DRIVE is true"
check_var_value error "_PART_SWAP_SIZE" "$_PART_SWAP_SIZE" "swap partition size needed since _ERASE_DRIVE is true"
check_var_value error "_PART_SYSTEM_LABEL" "$_PART_SYSTEM_LABEL" "system partition label size needed since _ERASE_DRIVE is true"
check_var_value error "_PART_SWAP_LABEL" "$_PART_SWAP_SIZE" "swap partition label size needed since _ERASE_DRIVE is true"
check_var_value error "_DRIVE" "$_DRIVE" "drive needed since _ERASE_DRIVE is true"
fi
if ! check_var_value warning "_USER" "$_USER" "No new user will be created (not recommended)"; then
check_var_value error "_USER_PASSWD" " "$_USER_PASSWD""
check_var_equals error "_USER_PASSWD" "_USER_PASSWD_RETYPE" "$_USER_PASSWD" "$_USER_PASSWD_RETYPE"
fi
check_var_equals error "_CRYPT_PASSWD" "_CRYPT_PASSWD_RETYPE" "$_CRYPT_PASSWD" "$_CRYPT_PASSWD_RETYPE"
check_var_match error "_CPU" "$_CPU" "^(intel|amd)$"
check_var_match error "_BOOTLOADER" "$_BOOTLOADER" "^refind-efi$"
if [[ $_DESKTOP = true ]]; then
check_var_match warning "_DE" "$_DE" "^(kde|gnome|xfce)$"
if [[ -z $_WINDOW_MANAGER ]]; then
warning_keep "You installed a desktop environment without a window manager"
fi
fi
check_packages_exists
}
# Called first in entry point. Set all necessary things
# No arguments
function init () {
# Bash will remember & return the highest exitcode in a chain of pipes.
# This way you can catch the error in case mysqldump fails in `mysqldump | gzip`, for example.
set -o pipefail
# Enable extended globbing (used in option parsing)
shopt -s extglob
# Call finalize when script exit (whatever the return code)
trap 'finalize' EXIT INT TERM
touch "$OUT_END" "$OUT_TMP" "$LOG_FILE"
# variables sanitizer
sanitize
_prepare_locking
exlock_now
}
# Called on EXIT
# Used to print messages on exit
# Arguments : Exit cause
function finalize () {
title "Script complete!"
if [[ -f "$OUT_END" ]]; then
cat "$OUT_END"
fi
if [[ $LOG = true ]]; then
printf "\n"
info "See logs in ${LOG_FILE}"
info "See all output in ${DEBUG_LOG_FILE}"
else
rm --force "$LOG_FILE"
fi
rm --recursive --force --dir "$TEMP_DIR"
_no_more_locking
}
############################################################
# Entry point
############################################################
PROGNAME="$(trim ${PROGNAME%.*})" # name.sh ==> name, and then trim the string
###############
# Parsing
###############
# First parsing to priority options
for option in $@; do
case $option in
--debug)
set -x
;;
--strict)
set -o nounset
;;
--no-logs)
LOG="false"
;;
--quiet)
QUIET="true"
;;
--noconfirm)
NOCONFIRM="true"
;;
--lock)
LOCK="true"
;;
-h|--help)
usage
exit
;;
--) # End of all options.
shift
break
;;
*) # Default case: No more options, so break out of the loop.
continue
esac
done
# Drop lock if not wanted
if [[ $LOCK = false ]]; then
unlock
fi
init
# Second parsing
while :; do
case $1 in
# Catch unknow options except all priority options (require extended globbing).
$priority_options_pattern)
shift
continue
;;
--check|-c)
set_packages
check
print_kept_logs
clear_kept_logs
exit
;;
--partition|-p)
part_create
exit
;;
--format|-f)
part_format
exit
;;
--mount|-m)
part_mount
exit
;;
--umount|u)
part_umount
exit
;;
-?*)
usage "Invalid option $1"
exit
;;
# End of all options.
--)
shift
break
;;
# Default case: No more options, so break out of the loop.
*)
break
esac
shift
done
###############
# Installation
###############
# checks
set_packages
check
print_kept_logs
prompt_yes_no "Do you want to continue?" || exit 1
# partitions
part_prepare
part_create
part_format
part_mount
title "Install base packages"
pacstrap /mnt base base-devel linux linux-firmware
# base configuration
title "Base configuration"
info "Set root password"
printf "$_ROOT_PASSWD\n$_ROOT_PASSWD_RETYPE" | arch-chroot /mnt passwd
conf_locale
conf_time_date
conf_hostname
conf_keymap
conf_hosts
conf_custom
# Install packages
title "Installing packages"
pacman_install "btrfs-progs networkmanager $_PKGS"
# post install config
new_user
enable_services
bootloader_refind
packages_aur
conf_mkinitcpio
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment