mirror of
https://git.myvelabs.com/lab/archlinux.git
synced 2025-12-17 21:26:25 +00:00
347 lines
11 KiB
Bash
Executable file
347 lines
11 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -a -E
|
|
|
|
# Exit function
|
|
trap '[ "${?}" -ne 77 ] || exit 77' ERR
|
|
function die
|
|
{
|
|
echo -e '\n\e[1;31mError encountered, script aborted...\e[0m\n'
|
|
exit 77
|
|
}
|
|
|
|
# Internet connection check
|
|
if ! nc -z -w 1 archlinux.org 443 >/dev/null 2>&1 || ! nc -z -w 1 google.com 443 >/dev/null 2>&1
|
|
then
|
|
die 'No internet connectivity detected, plug in an ethernet cable or run \e[32miwd-connect\e[33m if using wifi and try again'
|
|
fi
|
|
|
|
clear
|
|
|
|
echo -e '\e[3m## rev '${revision}'\e[0m\n'
|
|
echo -e '\t\e[1;4;34mArch Linux Recovery\e[0m\n\n'
|
|
echo -e '\e[1mSelect a system configuration from the options below\e[0m\n'
|
|
echo -e '\t1) Basic'
|
|
echo -e '\t2) Full Disk LUKS Encryption with EFISTUB'
|
|
echo -e '\t3) Full Disk LUKS Encryption with Secured GRUB'
|
|
echo -e '\t4) Yubikey Full Disk Encryption with EFISTUB'
|
|
echo -e '\t5) Yubikey Full Disk Encryption with Secured GRUB'
|
|
|
|
if ls -l /dev/disk/* | grep -q 'virtio\|QEMU'
|
|
then
|
|
echo
|
|
until [[ ${arch} = [1-5] ]]
|
|
do
|
|
read -n 1 -p '> ' arch
|
|
[[ ${arch} = [1-5] ]] || echo -e '\n\n\e[1;31mInvalid selection, type an option from 1 to 5\e[0m'
|
|
done
|
|
else
|
|
echo -e '\t6) Full Disk Encryption with Detached LUKS Header and Secured GRUB'
|
|
echo -e '\t7) Yubikey Encrypted Detached LUKS Header with Secured GRUB\n'
|
|
until [[ ${arch} = [1-7] ]]
|
|
do
|
|
read -n 1 -p '> ' arch
|
|
[[ ${arch} = [1-7] ]] || echo -e '\n\n\e[1;31mInvalid selection, type an option from 1 to 7\e[0m'
|
|
done
|
|
fi
|
|
|
|
# Prevent continuing unless yubikey is detected, only applies to yubikey setups
|
|
if [[ ${arch} = [457] ]] && ! dmesg | grep -q -i YubiKey
|
|
then
|
|
echo -e '\n\n\e[1mYubikey not detected'
|
|
echo -e 'Insert one to continue\e[5m...\e[0m'
|
|
until dmesg | grep -q -i YubiKey
|
|
do
|
|
sleep 1
|
|
done
|
|
fi
|
|
|
|
# Installation drive
|
|
echo -e '\n\n\e[1;36mIdentify the system drive from the list of available devices below\e[0m'
|
|
lsblk -d -o name,model,size,mountpoint | grep -v 'archiso'
|
|
echo -e '\e[3m## SSD and HDD device format begins with "sd" or "hd" (sda, sdb, sd[*])'
|
|
echo -e '## NVME and PCI device format is "nvme[*]n1" (nvme0n1, nvme1n1, nvme[*]n1)\e[0m'
|
|
while true
|
|
do
|
|
read -r -p 'Installation device: ' installation_disk
|
|
lsblk -o name | grep -q -w ${installation_disk} && [ ${installation_disk} ] && break
|
|
lsblk -d -o name,model,size,mountpoint | grep -v 'archiso'
|
|
[ -z ${installation_disk} ] && echo -e '\e[1;31mField cannot be empty, try again\e[0m' ||
|
|
echo -e '\e[1;31mInvalid selection or drive not available, try again\e[0m'
|
|
done
|
|
echo -e '\n\e[1mInstallation drive set as \e[32m/dev/'${installation_disk}'\e[0m'
|
|
echo
|
|
|
|
# Detached boot drive
|
|
if [[ ${arch} = [67] ]]
|
|
then
|
|
echo -e '\e[1;34mIdentify the removable boot drive from the list of available devices below\e[0m'
|
|
lsblk -d -o name,model,size,mountpoint | grep -v "archiso\|${installation_disk}"
|
|
echo -e '\e[3m## Removable drives usually begin with "sd" (sda, sdb, sd[*])\e[0m'
|
|
while true
|
|
do
|
|
read -r -p 'Removable boot device: ' external_boot_disk
|
|
lsblk -o name | grep -v ${installation_disk} | grep -q -w ${external_boot_disk} && [ ${external_boot_disk} ] && break
|
|
lsblk -d -o name,model,size,mountpoint | grep -v "archiso\|${installation_disk}"
|
|
if [ -z ${external_boot_disk} ]
|
|
then
|
|
echo -e '\e[1;31mField cannot be empty, try again\e[0m'
|
|
elif [ ${external_boot_disk} = ${installation_disk} ]
|
|
then
|
|
echo -e '\e[1;31mBoot drive cannot be the same as the system drive, try again\e[0m'
|
|
else
|
|
echo -e '\e[1;31mInvalid selection or drive not available, try again\e[0m'
|
|
fi
|
|
done
|
|
echo -e '\n\e[1mDetached boot drive set as \e[32m/dev/'${external_boot_disk}'\e[0m'
|
|
echo
|
|
fi
|
|
|
|
if [[ ${arch} = [457] ]]
|
|
then
|
|
until [[ ${decrypt_root} = [yYnN] ]]
|
|
do
|
|
read -n 1 -p $'\n\e[1mDoes the yubikey automatically decrypt root upon boot (1FA)? (y/n): \e[0m' decrypt_root
|
|
[[ ${decrypt_root} = [yYnN] ]] || echo -e -n '\n\n\e[1;31mNot a valid answer, type "y" or "n"\e[0m'
|
|
done
|
|
echo
|
|
fi
|
|
|
|
# Functions
|
|
function decryptRootLuks
|
|
{
|
|
while true
|
|
do
|
|
unset lukspass
|
|
|
|
echo -e '\e[1;36mEnter the encryption passphrase for the system drive\e[0m'
|
|
until [ ${lukspass} ]
|
|
do
|
|
read -s -r -p 'Encryption password: ' lukspass
|
|
[ ${lukspass} ] || echo -e '\n\n\e[1;31mPassphrase field cannot be empty, try again\e[0m'
|
|
done
|
|
|
|
echo -e '\n\n\e[1;36mAttempting to decrypt '${rootpart}'\e[0m'
|
|
if printf '%s' "${lukspass}" | cryptsetup open -v ${rootpart} cryptroot ${luks_header}
|
|
then
|
|
unset lukspass
|
|
echo -e '\e[1;92mDecryption successful\e[0m'
|
|
break
|
|
else
|
|
echo -e '\e[1;31mPassphrase failed, try again\e[0m\n'
|
|
fi
|
|
done
|
|
}
|
|
|
|
function decryptRootYubikey
|
|
{
|
|
echo
|
|
yes | pacman -Sy &>/dev/null
|
|
|
|
for package in yubikey-personalization yubikey-full-disk-encryption
|
|
do
|
|
if ! pacman -Q | grep -q -w ${package}
|
|
then
|
|
missing_yubikey_req+=(${package})
|
|
fi
|
|
done
|
|
|
|
if [ ${missing_yubikey_req} ]
|
|
then
|
|
yes | pacman -Sy ${missing_yubikey_req[@]}
|
|
unset missing_yubikey_req
|
|
echo
|
|
fi
|
|
|
|
# # Custom challenge slot
|
|
# sed -i '/YKFDE_CHALLENGE_SLOT/c\YKFDE_CHALLENGE_SLOT="1"' /etc/ykfde.conf
|
|
|
|
while true
|
|
do
|
|
unset lukspass
|
|
|
|
echo -e '\e[1;36mEnter the encryption passphrase for the system drive\e[0m'
|
|
until [ ${lukspass} ]
|
|
do
|
|
read -s -r -p 'Encryption password: ' lukspass
|
|
[ ${lukspass} ] || echo -e '\n\n\e[1;31mPassphrase field cannot be empty, try again\e[0m'
|
|
done
|
|
|
|
if [[ ${decrypt_root} = [yY] ]]
|
|
then
|
|
sed -i '/YKFDE_CHALLENGE=/c\YKFDE_CHALLENGE="'"$(printf '%q' ${lukspass})"'"' /etc/ykfde.conf
|
|
fi
|
|
|
|
echo -e '\n\n\e[1;36mAttempting to decrypt '${rootpart}' with yubikey HMAC encryption\e[0m'
|
|
if printf '%s\n' "${lukspass}" | ykfde-open -d ${rootpart} -n cryptroot -- ${luks_header}
|
|
then
|
|
unset lukspass
|
|
echo -e '\e[1;92mDecryption successful\e[0m'
|
|
break
|
|
else
|
|
echo -e '\e[1;31mPassphrase failed, try again\e[0m\n'
|
|
fi
|
|
done
|
|
}
|
|
|
|
function decryptBootLuks
|
|
{
|
|
while true
|
|
do
|
|
unset grubpass
|
|
|
|
echo -e '\e[1;36mEnter the encryption passphrase for the bootloader\e[0m'
|
|
until [ ${grubpass} ]
|
|
do
|
|
read -s -r -p 'Bootloader password: ' grubpass
|
|
[ ${grubpass} ] || echo -e '\n\n\e[1;31mPassword field cannot be empty, try again\e[0m'
|
|
done
|
|
|
|
echo -e '\n\n\e[1;36mAttempting to decrypt bootloader...\e[0m'
|
|
if printf '%s' "${grubpass}" | cryptsetup open ${bootpart} cryptboot
|
|
then
|
|
unset grubpass
|
|
echo -e '\e[1;92mDecryption successful\e[0m'
|
|
break
|
|
else
|
|
echo -e '\e[1;31mPassphrase failed, try again\e[0m\n'
|
|
fi
|
|
done
|
|
}
|
|
|
|
function configureVolumes
|
|
{
|
|
echo -e '\n\e[1;36mMounting volumes\e[0m'
|
|
|
|
case $(blkid -s TYPE -o value ${rootvol}) in
|
|
zfs_member)
|
|
if ! zpool list | grep -q zroot
|
|
then
|
|
zpool import -R /mnt zroot -N -d ${rootvol}
|
|
fi
|
|
zfs mount zroot/ROOT
|
|
zfs mount -a
|
|
;;
|
|
btrfs)
|
|
mount ${rootvol} /mnt
|
|
;;
|
|
ext4)
|
|
mount ${rootvol} /mnt
|
|
mount ${bootvol} /mnt/boot
|
|
if [[ ${arch} = [3567] ]]
|
|
then
|
|
mount ${efivol} /mnt/boot/efi
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Grab disk-id of ${drive}
|
|
installation_disk_id=$(ls -l /dev/disk/by-id/* | grep "${installation_disk}$" | grep 'wwn\|nvme-uuid\|nvme-nvme\|nvme-eui\|QEMU\|virtio\|VBOX' | awk '{print $9}' | head -1)
|
|
external_boot_disk_id=$(ls -l /dev/disk/by-id/* | grep "${external_boot_disk}$" | grep 'wwn\|nvme-uuid\|nvme-nvme\|nvme-eui\|QEMU\|virtio\|VBOX\|usb' | awk '{print $9}' | head -1)
|
|
|
|
# System configurations
|
|
case ${arch} in
|
|
1) # Basic
|
|
export {efivol,bootvol}=${installation_disk_id}-part1
|
|
export {rootpart,rootvol}=${installation_disk_id}-part2
|
|
configureVolumes
|
|
;;
|
|
|
|
2|4) # FDE with EFISTUB
|
|
export {efivol,bootvol}=${installation_disk_id}-part1
|
|
rootpart=${installation_disk_id}-part2
|
|
rootvol=/dev/mapper/cryptroot
|
|
|
|
case ${arch} in
|
|
2)
|
|
if [[ $(blkid -s TYPE -o value ${rootpart}) = "zfs_member" ]]
|
|
then
|
|
zpool import -R /mnt zroot -N -d ${rootpart}
|
|
printf '%s' "${lukspass}" | zfs load-key zroot
|
|
else
|
|
decryptRootLuks
|
|
fi
|
|
;;
|
|
4) decryptRootYubikey;;
|
|
esac
|
|
configureVolumes
|
|
;;
|
|
|
|
3|5) # FDE with Secured GRUB
|
|
efivol=${installation_disk_id}-part1
|
|
bootpart=${installation_disk_id}-part2
|
|
rootpart=${installation_disk_id}-part3
|
|
rootvol=/dev/mapper/cryptroot
|
|
bootvol=/dev/mapper/cryptboot
|
|
|
|
case ${arch} in
|
|
3) decryptRootLuks;;
|
|
5) decryptRootYubikey;;
|
|
esac
|
|
|
|
decryptBootLuks
|
|
configureVolumes
|
|
;;
|
|
|
|
6|7) # FDE with detached luks header
|
|
efivol=${external_boot_disk_id}-part1
|
|
bootpart=${external_boot_disk_id}-part2
|
|
rootpart=${installation_disk_id}
|
|
rootvol=/dev/mapper/cryptroot
|
|
bootvol=/dev/mapper/cryptboot
|
|
luks_header='--header /mnt/header.img'
|
|
|
|
decryptBootLuks
|
|
mount /dev/mapper/cryptboot /mnt
|
|
case ${arch} in
|
|
6) decryptRootLuks;;
|
|
7) decryptRootYubikey;;
|
|
esac
|
|
umount /mnt
|
|
configureVolumes
|
|
;;
|
|
|
|
esac
|
|
|
|
echo -e '\e[1;92mSystem successfully mounted...\e[0m\n'
|
|
|
|
if [[ $(blkid -s TYPE -o value ${rootvol}) = "btrfs" ]]
|
|
then
|
|
install /dev/stdin /usr/local/bin/btrfs-mount <<- BTRFSSU
|
|
#!/usr/bin/env bash
|
|
btrfsopts=$(awk '$2=="/"' /mnt/etc/fstab | awk '{print $4}' | sed 's/,subvol=.*//')
|
|
umount -R /mnt
|
|
echo
|
|
|
|
# Mount @root subvolume
|
|
mount -o ${btrfsopts},subvol=@ ${rootvol} /mnt
|
|
|
|
# Mount all subvolumes
|
|
arch-chroot /mnt mount --all
|
|
lsblk
|
|
echo -e '\n\t\e[1;92mBtrfs subvolumes successful mounted!\e[0m\n'
|
|
BTRFSSU
|
|
|
|
echo -e '\e[1mRun \e[92mbtrfs-mount\e[0m\e[1m to mount all the btrfs subvolumes\e[0m\n'
|
|
fi
|
|
|
|
if [[ ${arch} = [3567] ]]
|
|
then
|
|
install /dev/stdin /usr/local/bin/re-grub <<REGRUB
|
|
#!/usr/bin/env bash
|
|
set -e
|
|
|
|
if findmnt '/mnt/boot/efi' | grep -q "${efivol}" && findmnt '/mnt/boot' | grep -q "${bootvol}"
|
|
then
|
|
arch-chroot /mnt /bin/bash <<'GRUB'
|
|
grub-install --target=x86_64-efi --bootloader-id=GRUB --efi-directory=/boot/efi --recheck
|
|
grub-mkconfig -o /boot/grub/grub.cfg
|
|
echo -e '\n\t\e[1;92mGrub successfuly re-installed!\e[0m\n'
|
|
GRUB
|
|
else
|
|
echo -e '\n\t\e[1;31mEFI partition not mounted, try again\e[0m\n'
|
|
fi
|
|
REGRUB
|
|
|
|
echo -e '\e[1mRun \e[92mre-grub\e[0m\e[1m to regenerate grub\e[0m\n'
|
|
fi
|