|
#!/usr/bin/env sh |
|
# |
|
# TODO: |
|
# * Suspend/resume to/from swap: https://wiki.archlinux.org/index.php/Power_management/Suspend_and_hibernate#Required_kernel_parameters |
|
# * Emojis? http://www.omgubuntu.co.uk/2016/03/enable-color-emoji-linux-svg-font |
|
|
|
|
|
set -e |
|
# set -x |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Config. |
|
|
|
#--YOUR-CUSTOMIZATIONS-BELOW-------------------------------------------------------------------------------------------- |
|
|
|
# General. |
|
DESIRED_COUNTRY='US' |
|
DESIRED_TIMEZONE='America/Chicago' |
|
DESIRED_LOCALE='en_US.UTF-8 UTF-8' |
|
DESIRED_LOCALE2='en_US.UTF-8' |
|
DESIRED_LANGUAGE='en_US' |
|
DESIRED_HOSTNAME='bo-laptop' |
|
DESIRED_USERNAME='bo' |
|
# Cipher Strength. |
|
CIPHER_STRENGTH=256 |
|
# Key file. |
|
KEYFILE_NAME='multikeyfile' |
|
# If these devs are not found, will default to /dev/sda & /dev/sdb. |
|
DEV_DRIVE1='/dev/nvme0n1' |
|
DEV_DRIVE2='/dev/nvme1n1' |
|
# Partition numbers. |
|
PARTNUM_EFI='1' |
|
PARTNUM_SWAP1='2' |
|
PARTNUM_DATA1='3' |
|
PARTNUM_SWAP2='1' |
|
PARTNUM_DATA2='2' |
|
# Swap size in harddrive sectors. |
|
SWAP_SIZE=34603007 |
|
|
|
|
|
#--DO-NOT-MODIFY-ANYTHING-BEYOND-THIS-LINE-UNLESS-NECESSARY------------------------------------------------------------- |
|
|
|
KERNEL_PARAMS='' |
|
# Key file. |
|
KEYFILE="/mnt/boot/${KEYFILE_NAME}" |
|
KEYFILE_MAPPED="/dev/mapper/${KEYFILE_NAME}" |
|
# /dev/mapper/* related. |
|
DATA1_MAPNAME='container1' |
|
DATA2_MAPNAME='container2' |
|
DATA1_MAPPED="/dev/mapper/${DATA1_MAPNAME}" |
|
DATA2_MAPPED="/dev/mapper/${DATA2_MAPNAME}" |
|
SWAP1_MAPNAME='swap1' |
|
SWAP2_MAPNAME='swap2' |
|
SWAP1_MAPPED="/dev/mapper/${SWAP1_MAPNAME}" |
|
SWAP2_MAPPED="/dev/mapper/${SWAP2_MAPNAME}" |
|
SWAP_RAID='/dev/md1' |
|
# Used later. |
|
PART_EFI='' |
|
PART_SWAP1='' |
|
PART_DATA1='' |
|
PART_SWAP2='' |
|
PART_DATA2='' |
|
SWAP_UUID='' |
|
ROOT_UUID='' |
|
|
|
INTEL_DEV_ID="$(lspci -nn | grep -Ei "(VGA|3D).+ Intel .*" | sed -E 's/.*\[([a-fA-F0-9]+:[a-fA-F0-9]+)\].*/\1/g')" |
|
NVIDIA_DEV_ID="$(lspci -nn | grep -Ei "(VGA|3D).+ nVidia .*" | sed -E 's/.*\[([a-fA-F0-9]+:[a-fA-F0-9]+)\].*/\1/g')" |
|
NVIDIA_BUS_ID="$(lspci | grep -Ei "(VGA|3D).+ nVidia .*" | cut -b1-7)" |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# General Methods. |
|
|
|
wait_for_user_input() { |
|
printf "\nPress ENTER to continue.\n" |
|
read |
|
} |
|
|
|
# Chopped up version of armrr. |
|
# https://github.com/Gen2ly/armrr |
|
dld_mirror_list() { |
|
# "sh" shell doesn't support local variables so these will be global. :/ |
|
# TODO: test this install script in bash. |
|
url="https://www.archlinux.org/mirrorlist/?country=${DESIRED_COUNTRY}&protocol=http&ip_version=4&use_mirror_status=on" |
|
tmp_ml=$(mktemp --suffix=-mirrorlist) |
|
|
|
if curl -s "${url}" -o "${tmp_ml}"; then |
|
if ! grep "^## Arch Linux repository mirrorlist" "${tmp_ml}" > /dev/null; then |
|
echo 'Warning: Downloaded mirrorlist invalid. Not using.' |
|
return |
|
fi |
|
else |
|
echo 'Warning: Download of mirrorlist failed. Not using.' |
|
return |
|
fi |
|
|
|
# Enable all servers. |
|
sed -i 's/^#Server/Server/g' "${tmp_ml}" |
|
|
|
# Copy over the new mirror list. |
|
install -Dm644 "${tmp_ml}" /etc/pacman.d/mirrorlist |
|
} |
|
|
|
# Attempts to find a device for our work. If passing a unix-style dev, like "nvme" drives, pass the full dev; e.g. |
|
# '/dev/nvme0n1' rather than '/dev/nvme0'. |
|
# |
|
# Takes two arguments: |
|
# 1. our desired dev; e.g. '/dev/nvme0' |
|
# 2. our allowable fallback dev; e.g. '/dev/sda' |
|
find_proper_drive() { |
|
ourdev="$1" |
|
defaultdev="$2" |
|
returndev="${ourdev}" |
|
|
|
if [ ! -e "${ourdev}" ]; then |
|
returndev="${defaultdev}" |
|
fi |
|
|
|
# Is the device NVME? Does it not end in "n1"? If both are true, then append "n1" to the dev name. |
|
if [ "${returndev#*nvme}" != "${returndev}" -a "${returndev%n1}" == "${returndev}" ]; then |
|
returndev="${returndev}n1" |
|
fi |
|
|
|
printf "%s" "${returndev}" |
|
} |
|
|
|
find_proper_partition() { |
|
ourdev="$1" |
|
ourpart="$2" |
|
|
|
if [ "${ourdev#*nvme}" != "${ourdev}" ]; then |
|
ourdev="${ourdev}p" |
|
fi |
|
|
|
printf "%s%s" "${ourdev}" "${ourpart}" |
|
} |
|
|
|
|
|
unmount_all() { |
|
set +e |
|
swapoff "${SWAP_RAID}" |
|
mdadm --stop --force "${SWAP_RAID}" |
|
cryptsetup close "${SWAP1_MAPNAME}" |
|
cryptsetup close "${SWAP2_MAPNAME}" |
|
umount -R /mnt/arch/home |
|
umount -R /mnt/arch |
|
umount -R /mnt/btrfs-pool |
|
cryptsetup close "${DATA1_MAPNAME}" |
|
cryptsetup close "${DATA2_MAPNAME}" |
|
umount -R "${DATA1_MAPPED}" |
|
umount -R "${DATA2_MAPPED}" |
|
cryptsetup close "${KEYFILE_NAME}" |
|
umount -R "${KEYFILE_MAPPED}" |
|
umount -R /mnt/boot |
|
set -e |
|
} |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Confirm Execution of This Script. |
|
|
|
|
|
clear |
|
|
|
echo ' |
|
|
|
|
|
WARNING! WARNING! WARNING! WARNING! |
|
WARNING! WARNING! WARNING! WARNING! |
|
|
|
THIS SCRIPT WILL ABSOLUTELY WIPE OUT YOUR DATA ON AT LEAST THE FIRST TWO DRIVES AND WILL REPLACE YOUR BOOT LOADER! |
|
YOU ALONE CARRY THE RESPONSIBILITY FOR ANY DATA LOSS BY USING THIS SCRIPT. |
|
|
|
THERE WILL BE NO CONFIRMATION BEFORE DATA DESTRUCTION BEYOND THIS POINT! |
|
|
|
WARNING! WARNING! WARNING! WARNING! |
|
WARNING! WARNING! WARNING! WARNING! |
|
|
|
|
|
Do you acknowledge you alone carry the responsibility for any data loss and want to continue? |
|
* If so, press enter three times. |
|
* If not, press CTRL+C to cancel this script. |
|
' |
|
wait_for_user_input |
|
wait_for_user_input |
|
wait_for_user_input |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# General Prep. |
|
# https://wiki.archlinux.org/index.php/beginners'_guide#Update_the_system_clock |
|
# https://wiki.archlinux.org/index.php/beginners'_guide#Select_the_mirrors |
|
# https://wiki.archlinux.org/index.php/Mirrors |
|
|
|
# Ensure nothing is mounted that we intend to mount later. |
|
unmount_all |
|
|
|
|
|
printf "\n\nActivating network time to ensure the system's time is correct.\n" |
|
sudo tee /etc/systemd/timesyncd.conf <<-'EOF' > /dev/null |
|
[Time] |
|
#NTP=0.north-america.pool.ntp.org 1.north-america.pool.ntp.org 2.north-america.pool.ntp.org 3.north-america.pool.ntp.org |
|
NTP=time1.google.com time2.google.com time3.google.com time4.google.com |
|
FallbackNTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org |
|
EOF |
|
|
|
timedatectl set-ntp true |
|
|
|
|
|
printf "\n\nRanking pacman mirrors.\n" |
|
dld_mirror_list |
|
|
|
|
|
printf "\n\nEnabling multilib.\n" |
|
sed -i '/[#]*\[multilib\]/ { N; d; }' /etc/pacman.conf |
|
sed -i '/[#]*\[archlinuxfr\]/ { N; N; d; }' /etc/pacman.conf |
|
tee -a /etc/pacman.conf <<'EOF' > /dev/null |
|
|
|
[multilib] |
|
Include = /etc/pacman.d/mirrorlist |
|
|
|
[archlinuxfr] |
|
SigLevel = Never |
|
Server = http://repo.archlinux.fr/$arch |
|
EOF |
|
|
|
|
|
printf "\n\nInstalling latest utils.\n" |
|
pacman -Sy --noconfirm btrfs-progs parallel |
|
|
|
|
|
# Figure out if we have devices to raid. |
|
DEV_DRIVE1="$(find_proper_drive "${DEV_DRIVE1}" "/dev/sda")" |
|
DEV_DRIVE2="$(find_proper_drive "${DEV_DRIVE2}" "/dev/sdb")" |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Partition Drives. |
|
# https://wiki.archlinux.org/index.php/beginners'_guide#Prepare_the_storage_devices |
|
|
|
# Reset the drive's partition table to a fresh GPT. |
|
sgdisk --zap "${DEV_DRIVE1}" |
|
sgdisk --clear --mbrtogpt "${DEV_DRIVE1}" |
|
|
|
# Calculate sectors for drive 1's EFI boot partition. |
|
EFI_SECT_START=2048 |
|
EFI_SECT_END=$((EFI_SECT_END=EFI_SECT_START+2097151)) |
|
|
|
# Calculate sectors for drive 1's swap. |
|
SWAP_SECT_START=$((SWAP_SECT_START=EFI_SECT_END+1)) |
|
SWAP_SECT_END=$((SWAP_SECT_END=SWAP_SECT_START+SWAP_SIZE)) |
|
|
|
# Calculate sectors for drive 1's data. |
|
DATA_SECT_START=$((DATA_SECT_START=SWAP_SECT_END+1)) |
|
DATA_SECT_END=$(sgdisk -E ${DEV_DRIVE1}) |
|
|
|
# Create a 1024MB EFI boot partition. |
|
sgdisk --new ${PARTNUM_EFI}:${EFI_SECT_START}:${EFI_SECT_END} \ |
|
--change-name ${PARTNUM_EFI}:'EFI System Partition' \ |
|
--typecode ${PARTNUM_EFI}:ef00 "${DEV_DRIVE1}" |
|
|
|
# Create a SWAP partition. |
|
sgdisk --new ${PARTNUM_SWAP1}:${SWAP_SECT_START}:${SWAP_SECT_END} \ |
|
--change-name ${PARTNUM_SWAP1}:'SWAP1' \ |
|
--typecode ${PARTNUM_SWAP1}:8200 "${DEV_DRIVE1}" |
|
|
|
# Create the root partition. |
|
sgdisk --new ${PARTNUM_DATA1}:${DATA_SECT_START}:${DATA_SECT_END} \ |
|
--change-name ${PARTNUM_DATA1}:'DATA1' \ |
|
--typecode ${PARTNUM_DATA1}:8300 "${DEV_DRIVE1}" |
|
|
|
# Print out the partition table for the first drive. |
|
sgdisk --print "${DEV_DRIVE1}" |
|
|
|
|
|
# Reset the drive's partition table to a fresh GPT. |
|
sgdisk --zap "${DEV_DRIVE2}" |
|
sgdisk --clear --mbrtogpt "${DEV_DRIVE2}" |
|
|
|
# Calculate sectors for drive 2's swap. |
|
SWAP_SECT_START=2048 |
|
SWAP_SECT_END=$((SWAP_SECT_END=SWAP_SECT_START+SWAP_SIZE)) |
|
|
|
# Calculate sectors for drive 2's data. |
|
DATA_SECT_START=$((DATA_SECT_START=SWAP_SECT_END+1)) |
|
DATA_SECT_END=$(sgdisk -E ${DEV_DRIVE2}) |
|
|
|
# Create a 16.5GB SWAP partition. |
|
sgdisk --new ${PARTNUM_SWAP2}:${SWAP_SECT_START}:${SWAP_SECT_END} \ |
|
--change-name ${PARTNUM_SWAP2}:'SWAP2' \ |
|
--typecode ${PARTNUM_SWAP2}:8200 "${DEV_DRIVE2}" |
|
|
|
# Create the root partition. |
|
sgdisk --new ${PARTNUM_DATA2}:${DATA_SECT_START}:${DATA_SECT_END} \ |
|
--change-name ${PARTNUM_DATA2}:'DATA2' \ |
|
--typecode ${PARTNUM_DATA2}:8300 "${DEV_DRIVE2}" |
|
|
|
# Print out the partition table for the first drive. |
|
sgdisk --print "${DEV_DRIVE2}" |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Discover proper partition names. |
|
|
|
PART_EFI="$(find_proper_partition "${DEV_DRIVE1}" "${PARTNUM_EFI}")" |
|
PART_SWAP1="$(find_proper_partition "${DEV_DRIVE1}" "${PARTNUM_SWAP1}")" |
|
PART_DATA1="$(find_proper_partition "${DEV_DRIVE1}" "${PARTNUM_DATA1}")" |
|
PART_SWAP2="$(find_proper_partition "${DEV_DRIVE2}" "${PARTNUM_SWAP2}")" |
|
PART_DATA2="$(find_proper_partition "${DEV_DRIVE2}" "${PARTNUM_DATA2}")" |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Setup The Key. |
|
# https://bbs.archlinux.org/viewtopic.php?id=196840 |
|
|
|
echo " |
|
|
|
Creating keyfile used to decrypt each drive in the array. This key is encrypted and will be what you unlock when |
|
entering the proper password on boot. |
|
|
|
When prompted, please provide a password you can remember. |
|
" |
|
# wait_for_user_input |
|
|
|
# Format the EFI+BOOT partition and mount it. |
|
printf "\n\nBuilding /mnt/boot (EFI).\n" |
|
mkfs.fat -F32 "${PART_EFI}" |
|
[ ! -d /mnt/boot ] && mkdir -p /mnt/boot |
|
mount "${PART_EFI}" /mnt/boot |
|
|
|
# Generate a blank keyfile -- apparently the LUKS header is 2MB, so we'll need 2MB + the 2MB for keys. |
|
dd if=/dev/zero of="${KEYFILE}" bs=4M count=1 |
|
|
|
# Format our keyfile. |
|
cryptsetup --batch-mode --verbose --verify-passphrase \ |
|
--cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 800 --use-random \ |
|
luksFormat "${KEYFILE}" |
|
|
|
# Decrypt and open the keyfile. |
|
printf "\n\nEnter your encrypt password when prompted below.\n" |
|
cryptsetup open --type luks "${KEYFILE}" "${KEYFILE_NAME}" |
|
|
|
|
|
set +e |
|
|
|
# Write zeros to the keyfile. |
|
dd if=/dev/zero of="${KEYFILE_MAPPED}" |
|
# Want 4 keys. (4 * 4096 / 8) = 2048 bytes". |
|
dd iflag=fullblock if=/dev/random of="${KEYFILE_MAPPED}" bs=2048 count=1 |
|
|
|
set -e |
|
|
|
|
|
printf "\n\nVerify there is enough random content in the keyfile:\n" |
|
hexdump -C "${KEYFILE_MAPPED}" |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Create Encrypted Swap. |
|
# https://wiki.archlinux.org/index.php/Dm-crypt/Swap_encryption |
|
|
|
printf "\n\nCreating the containers for our swap.\n" |
|
|
|
cryptsetup --batch-mode --verbose \ |
|
--cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 800 --use-random \ |
|
--key-file "${KEYFILE_MAPPED}" --keyfile-offset 0 --keyfile-size 512 \ |
|
luksFormat "${PART_SWAP1}" |
|
|
|
cryptsetup --batch-mode --verbose \ |
|
--cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 800 --use-random \ |
|
--key-file "${KEYFILE_MAPPED}" --keyfile-offset 512 --keyfile-size 512 \ |
|
luksFormat "${PART_SWAP2}" |
|
|
|
|
|
printf "\n\nOpening the containers for our swap.\n" |
|
|
|
cryptsetup open --type luks \ |
|
--key-file "${KEYFILE_MAPPED}" --keyfile-offset 0 --keyfile-size 512 "${PART_SWAP1}" "${SWAP1_MAPNAME}" # swapDevice |
|
|
|
cryptsetup open --type luks \ |
|
--key-file "${KEYFILE_MAPPED}" --keyfile-offset 512 --keyfile-size 512 "${PART_SWAP2}" "${SWAP2_MAPNAME}" # swapDevice |
|
|
|
|
|
# Wipe 999MB of each drive (for testing of a full disk wipe). |
|
# printf "%s\n%s\n" "${SWAP1_MAPPED}" "${SWAP2_MAPPED}" | parallel "dd if=/dev/zero of='{}' bs=1M count=999 status=progress" |
|
# TODO: remove the above parallel command and uncomment the below. |
|
# Fully wipe both drives to fill them with encrypted "garbage" making it near impossible to discern where new encrypted |
|
# data is stored. |
|
# printf "%s\n%s\n" "${SWAP1_MAPPED}" "${SWAP2_MAPPED}" | parallel "dd if=/dev/zero of='{}' bs=1M status=progress" |
|
|
|
# Create raid for swap. Why? Only because of resume. I intend to use VMs for most of my memory and am uncertain that the |
|
# memory used by VMs can be compressed to the default 2/5ths to fit all 32GBs of system memory into a single swap |
|
# partition. On top of that, I want my swap partitions to be used evenly, which can either be done via setting their |
|
# priority to exactly the same (kernel will then "stripe" them) or mdadm'ing them. If I let the kernel decide what swap |
|
# partition to prioritize for hibernation, I will not be able to reliably resume because the kernel "resume" parameter |
|
# does not consider multiple swap devices! Therefore we must raid them. |
|
mdadm --create "${SWAP_RAID}" --force --level=0 --raid-devices=2 "${SWAP1_MAPPED}" "${SWAP2_MAPPED}" |
|
|
|
# Make the swap partition. |
|
mkswap "${SWAP_RAID}" |
|
|
|
# Start using the swap partition. |
|
swapon "${SWAP_RAID}" |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Create Encrypted BTRFS. |
|
# https://wiki.archlinux.org/index.php/beginners'_guide#Format_the_file_systems_and_enable_swap |
|
# http://kneit.in/2015/09/17/brtfs-raid-on-dmcrypt.html#planning-your-disk-layout |
|
|
|
printf "\n\nCreating the containers for our array.\n" |
|
|
|
cryptsetup --batch-mode --verbose \ |
|
--cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 800 --use-random \ |
|
--key-file "${KEYFILE_MAPPED}" --keyfile-offset 1024 --keyfile-size 512 \ |
|
luksFormat "${PART_DATA1}" |
|
|
|
cryptsetup --batch-mode --verbose \ |
|
--cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 800 --use-random \ |
|
--key-file "${KEYFILE_MAPPED}" --keyfile-offset 1536 --keyfile-size 512 \ |
|
luksFormat "${PART_DATA2}" |
|
|
|
|
|
printf "\n\nOpening the containers for our array.\n" |
|
|
|
cryptsetup open --type luks \ |
|
--key-file "${KEYFILE_MAPPED}" --keyfile-offset 1024 --keyfile-size 512 "${PART_DATA1}" \ |
|
"${DATA1_MAPNAME}" |
|
|
|
cryptsetup open --type luks \ |
|
--key-file "${KEYFILE_MAPPED}" --keyfile-offset 1536 --keyfile-size 512 "${PART_DATA2}" \ |
|
"${DATA2_MAPNAME}" |
|
|
|
|
|
# Close the no longer needed cryptkey. |
|
cryptsetup close "${KEYFILE_NAME}" |
|
|
|
|
|
# Wipe 999MB of each drive (for testing of a full disk wipe). |
|
# printf "%s\n%s\n" "${DATA1_MAPPED}" "${DATA2_MAPPED}" | parallel "dd if=/dev/zero of='{}' bs=1M count=999 status=progress" |
|
# TODO: remove the above parallel command and uncomment the below. |
|
# Fully wipe both drives to fill them with encrypted "garbage" making it near impossible to discern where new encrypted |
|
# data is stored. |
|
# printf "%s\n%s\n" "${DATA1_MAPPED}" "${DATA2_MAPPED}" | parallel "dd if=/dev/zero of='{}' bs=1M status=progress" |
|
|
|
|
|
# Make the BTRFS RAID 0 (stripe) for data & RAID 1 (mirror) for meta data, the latter helps detect & avoid corruption. |
|
printf "\n\nFormatting the containers with btrfs.\n" |
|
mkfs.btrfs -m raid1 -d raid0 "${DATA1_MAPPED}" "${DATA2_MAPPED}" |
|
|
|
|
|
# Mount our BTRFS RAID--defaults for mounting on NVME are fine, just add compression cause it's good stuff. |
|
# WARNING: Do not add "discard" to mounting NVME SSDs! Btrfs does not do this by default, which is good. |
|
[ ! -d /mnt/btrfs-pool ] && mkdir /mnt/btrfs-pool |
|
mount -t btrfs -o defaults,compress=lzo "${DATA1_MAPPED}" /mnt/btrfs-pool |
|
|
|
|
|
# Change our working dir. |
|
pushd /mnt/btrfs-pool |
|
|
|
# Create desired subvolumes for easy snapshots. |
|
btrfs sub create @ |
|
btrfs sub create @home |
|
btrfs sub create @snapshots |
|
# Paths we do not want to include in snapshots. |
|
btrfs sub create @var-cache-pacman-pkg |
|
btrfs sub create @var-abs |
|
btrfs sub create @var-tmp |
|
btrfs sub create @tmp |
|
btrfs sub create @srv |
|
|
|
|
|
# List our subvols. |
|
btrfs sub list . |
|
|
|
# Reset our current working folder. |
|
popd |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Mount Our Partitions. |
|
# https://wiki.archlinux.org/index.php/beginners'_guide#Format_the_file_systems_and_enable_swap |
|
|
|
|
|
# Mount our root subvolume. |
|
[ ! -d /mnt/arch ] && mkdir /mnt/arch |
|
mount -t btrfs -o defaults,compress=lzo,subvol=@ "${DATA1_MAPPED}" /mnt/arch |
|
|
|
|
|
# Make some system dirs. |
|
[ ! -d /mnt/arch/boot ] && mkdir -p /mnt/arch/boot |
|
[ ! -d /mnt/arch/home ] && mkdir -p /mnt/arch/home |
|
[ ! -d /mnt/arch/etc ] && mkdir -p /mnt/arch/etc |
|
[ ! -d /mnt/arch/var/log ] && mkdir -p /mnt/arch/var/log |
|
# Paths we do not want to include in snapshots. |
|
[ ! -d /mnt/arch/var/cache/pacman/pkg ] && mkdir -p /mnt/arch/var/cache/pacman/pkg |
|
[ ! -d /mnt/arch/var/abs ] && mkdir -p /mnt/arch/var/abs |
|
[ ! -d /mnt/arch/var/tmp ] && mkdir -p /mnt/arch/var/tmp |
|
[ ! -d /mnt/arch/tmp ] && mkdir -p /mnt/arch/tmp |
|
[ ! -d /mnt/arch/srv ] && mkdir -p /mnt/arch/srv |
|
|
|
|
|
# Bind boot to two locations since a symlink cannot be used within /mnt/arch once we get into arch-chroot or mkinitcpio. |
|
mount --bind /mnt/boot /mnt/arch/boot |
|
|
|
|
|
# Disable copy-on-write to avoid fragmentation. |
|
chattr +C /mnt/arch/var/log |
|
|
|
|
|
# Mount our subvols. |
|
# We keep them as subvols not nested under root so that rolling back the subvol named "@" will be easy, again, due to |
|
# not having nested subvols under "@". |
|
mount -t btrfs -o defaults,compress=lzo,subvol=@home "${DATA1_MAPPED}" /mnt/arch/home |
|
mount -t btrfs -o defaults,compress=lzo,subvol=@var-cache-pacman-pkg "${DATA1_MAPPED}" /mnt/arch/var/cache/pacman/pkg |
|
mount -t btrfs -o defaults,compress=lzo,subvol=@var-abs "${DATA1_MAPPED}" /mnt/arch/var/abs |
|
mount -t btrfs -o defaults,compress=lzo,subvol=@var-tmp "${DATA1_MAPPED}" /mnt/arch/var/tmp |
|
mount -t btrfs -o defaults,compress=lzo,subvol=@tmp "${DATA1_MAPPED}" /mnt/arch/tmp |
|
mount -t btrfs -o defaults,compress=lzo,subvol=@srv "${DATA1_MAPPED}" /mnt/arch/srv |
|
|
|
|
|
# Mount our btrfs pool, without specifying subvolumes, to make it easier to manage subvols. |
|
[ ! -d /mnt/arch/mnt/btrfs-pool ] && mkdir -p /mnt/arch/mnt/btrfs-pool |
|
mount -t btrfs -o defaults,compress=lzo "${DATA1_MAPPED}" /mnt/arch/mnt/btrfs-pool |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Install Arch Linux. |
|
# https://wiki.archlinux.org/index.php/beginners'_guide#Installation |
|
|
|
# Package descriptions: |
|
# * intel-ucode: updated microcode for intel CPUs. AMDs do not need an extra pkg for updates. |
|
# * mesa-libgl, lib32-mesa-libgl: adds OpenGL support to intel gpu. |
|
# * mesa: an open-source implementation of the OpenGL specification. |
|
# * vulkan-intel: adds Vulkan, replacement for OpenGL, to intel gpu. |
|
# * xf86-video-*: hybrid graphics cards drivers (nvidia + intel, or amd + intel); |
|
# see https://wiki.archlinux.org/index.php/PRIME |
|
# * nvidia*, lib32-nvidia-libgl: nVidia supplied linux video drivers--very performant. |
|
# see https://wiki.archlinux.org/index.php/NVIDIA_Optimus |
|
# * xorg-xrandr: required by nvidia* packages, according to the wiki. |
|
# * iw: CLI WIFI configuration util. |
|
# * netctl: installed with "base"; recommended for networking control. https://wiki.archlinux.org/index.php/Netctl |
|
# * ifplugd: starts & stops DHCP profiles when network cable is plugged in or unplugged. |
|
# * wpa_actiond: same concept as ifplugd but for wifi. |
|
# * wpa_supplicant: A utility providing key negotiation for WPA wireless networks. |
|
# * dialog: A tool to display dialog boxes from shell scripts. |
|
# * libva-intel-driver, libva-vdpau-driver (req. nouveau-fw), nvidia-utils: "Video Acceleration API" (VA-API) for hw |
|
# accel video encoding and decoding. https://wiki.archlinux.org/index.php/VA-API |
|
# * libvdpau-va-gl, mesa-vdpau (req. nouveau-fw), nvidia-utils: "Video Decode and Presentation API for Unix" (VDPAU) is |
|
# an open source library and API to offload portions of the video decoding process and video post-processing to the |
|
# GPU video-hardware. https://wiki.archlinux.org/index.php/VDPAU |
|
# * qemu, libvirt, bridge-utils: KVM & VFIO related. |
|
# |
|
# Dependencies for future packages/apps: |
|
# * python3: snapper gui |
|
# * gtk3: snapper gui |
|
# * python-dbus: snapper gui |
|
# * python-gobject: snapper gui |
|
# * python-setuptools: snapper gui |
|
# * gtksourceview3: snapper gui |
|
|
|
printf "\n\nInstalling Arch Linux.\n" |
|
pacstrap /mnt/arch \ |
|
alsa-utils \ |
|
alsa-oss \ |
|
alsa-lib \ |
|
base \ |
|
base-devel \ |
|
mtr \ |
|
bash-completion \ |
|
btrfs-progs \ |
|
dialog \ |
|
downgrade \ |
|
efibootmgr \ |
|
gtk3 \ |
|
qt4 \ |
|
gtksourceview3 \ |
|
htop \ |
|
intel-ucode \ |
|
iotop \ |
|
iw \ |
|
lib32-alsa-plugins \ |
|
lib32-mesa-libgl \ |
|
libvdpau-va-gl \ |
|
linux-headers \ |
|
libva-intel-driver \ |
|
mesa \ |
|
mesa-libgl \ |
|
mesa-vdpau \ |
|
pulseaudio \ |
|
pulseaudio-alsa \ |
|
pulseaudio-bluetooth \ |
|
pulseaudio-equalizer \ |
|
pulseaudio-gconf \ |
|
python \ |
|
python-dbus \ |
|
python-gobject \ |
|
python-setuptools \ |
|
python2 \ |
|
snapper \ |
|
vulkan-icd-loader \ |
|
vulkan-intel \ |
|
wget \ |
|
wpa_supplicant \ |
|
wpa_supplicant_gui \ |
|
xf86-input-evdev \ |
|
xf86-input-synaptics \ |
|
yaourt \ |
|
qemu libvirt bridge-utils \ |
|
|
|
|
|
# ifplugd \ |
|
# wpa_actiond \ |
|
# nvidia \ |
|
# nvidia-utils \ |
|
# nvidia-libgl \ |
|
# lib32-nvidia-libgl \ |
|
# xorg-xrandr \ |
|
|
|
# xf86-video-intel \ # apparently has poor performance. https://www.reddit.com/r/archlinux/comments/4cojj9/it_is_probably_time_to_ditch_xf86videointel/ |
|
# xf86-video-nouveau \ |
|
# xf86-video-vesa \ |
|
# xf86-video-ati \ |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Configure Arch. |
|
|
|
printf "\n\nGenerating fstab.\n" |
|
genfstab -pU /mnt/arch > /mnt/arch/etc/fstab |
|
cat /mnt/arch/etc/fstab |
|
|
|
|
|
# Set the hostname. |
|
echo "${DESIRED_HOSTNAME}" > /mnt/arch/etc/hostname |
|
|
|
# Copy files that do not seem to be copied by pacstrap. |
|
install -Dm644 /etc/pacman.d/mirrorlist /mnt/arch/etc/pacman.d/mirrorlist |
|
install -Dm644 /etc/pacman.conf /mnt/arch/etc/pacman.conf |
|
cp /etc/locale.gen /etc/locale.conf /mnt/arch/etc/ |
|
|
|
|
|
printf "\n\nConfiguring arch.\n" |
|
arch-chroot /mnt/arch /bin/bash <<-EOC |
|
loadkeys us |
|
|
|
printf "\n\nGenerating locale config.\n" |
|
echo "${DESIRED_LOCALE}" > /etc/locale.gen |
|
locale-gen |
|
|
|
echo "LANG=${DESIRED_LOCALE2}" > /etc/locale.conf |
|
# echo "LANGUAGE=${DESIRED_LANGUAGE}" >> /etc/locale.conf |
|
# # echo 'LC_ALL=C' >> /etc/locale.conf |
|
export LANG="${DESIRED_LOCALE2}" |
|
localectl set-locale LANG="${DESIRED_LOCALE2}" |
|
|
|
|
|
printf "\n\nSet timezone.\n" |
|
ln -s "/usr/share/zoneinfo/${DESIRED_TIMEZONE}" /etc/localtime |
|
# Adjust time skew. |
|
hwclock --systohc --utc |
|
|
|
printf "\n\nActivating network time to ensure the system's time is correct.\n" |
|
tee /etc/systemd/timesyncd.conf <<-'EOF' > /dev/null |
|
[Time] |
|
NTP=0.north-america.pool.ntp.org 1.north-america.pool.ntp.org 2.north-america.pool.ntp.org 3.north-america.pool.ntp.org |
|
FallbackNTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org |
|
EOF |
|
|
|
|
|
# Download latest pacman package list. |
|
pacman -Sy |
|
|
|
|
|
# Install python pip. |
|
wget https://bootstrap.pypa.io/get-pip.py |
|
python get-pip.py |
|
rm -f get-pip.py |
|
EOC |
|
|
|
|
|
# Enable "LLMNR" for systemd-resolved so that we may resolve hosts on the LAN without needing a DNS server. |
|
sed -i 's/^[#]*\s*LLMNR=.*/LLMNR=yes/g' /mnt/arch/etc/systemd/resolved.conf |
|
|
|
# Add systemd-resolved to the host lookup order to act as a local DNS middle-man or cache. |
|
sed -i 's/^hosts:.*/hosts: files mymachines resolve myhostname dns/g' /mnt/arch/etc/nsswitch.conf |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Configure Xorg. |
|
|
|
printf "\n\nConfiguring Xorg.\n" |
|
|
|
# TODO: CODE NEEDS TO DOWNLOAD AND INSTALL THIS INTEL GUC FIRMWARE UNTIL IT MAKES IT INTO THE NEXT KERNEL OR WHATEVER: |
|
# https://01.org/sites/default/files/downloads/intelr-graphics-linux/sklgucver61.tar.bz2 |
|
# probably can have it replace the v4 guc: |
|
# ln -sf /lib/firmware/i915/skl_guc_ver6_1.bin /lib/firmware/i915/skl_guc_ver4.bin |
|
# have to rebuild init: |
|
# mkinitcpio -p linux |
|
|
|
tee /mnt/arch/etc/X11/xorg.conf <<EOF > /dev/null |
|
Section "Module" |
|
Load "modesetting" |
|
EndSection |
|
|
|
# Section "Device" |
|
# Identifier "nvidia" |
|
# Driver "nvidia" |
|
# BusID "${NVIDIA_DEV_ID}" |
|
# Option "AllowEmptyInitialConfiguration" |
|
# EndSection |
|
|
|
# If not use xf86-video-intel but kernel provided mesa for intel gfx, then you need this config. |
|
Section "Device" |
|
Identifier "Intel Graphics" |
|
# Driver "intel" |
|
Driver "modesetting" |
|
# BusID "${INTEL_DEV_ID}" |
|
Option "AccelMethod" "sna" |
|
Option "TearFree" "True" |
|
Option "DRI" "3" |
|
# Option "Tiling" "True" |
|
# Option "SwapbuffersWait" "True" |
|
EndSection |
|
|
|
# Section "ServerLayout" |
|
# Identifier "layout" |
|
# Screen 1 "nvidia" |
|
# Inactive "intel" |
|
# EndSection |
|
EOF |
|
|
|
# tee /mnt/arch/etc/X11/xorg.conf.d/20-intel.conf <<EOF > /dev/null |
|
# EOF |
|
|
|
# tee /mnt/arch/etc/X11/xinit/xinitrc.d/nvidia-optimus.sh <<EOF > /dev/null |
|
# #!/bin/sh |
|
# xrandr --setprovideroutputsource modesetting NVIDIA-0 |
|
# xrandr --auto |
|
# EOF |
|
|
|
# chmod +x /mnt/arch/etc/X11/xinit/xinitrc.d/nvidia-optimus.sh |
|
|
|
|
|
# Monitor Scale related. |
|
sudo tee /mnt/arch/etc/X11/xinit/xinitrc.d/70-xrandr-scale.sh <<'EOF' > /dev/null |
|
#!/usr/bin/env sh |
|
|
|
set -e |
|
# Set the gnome scale to something larger than what we really want so we can scale it down. |
|
gsettings set org.gnome.desktop.interface scaling-factor 2 |
|
# Get the name of the first connected display's port. |
|
PRI_PORT="$(xrandr | grep -v disconnected | grep connected | cut -d' ' -f1)" |
|
# Set the scale. |
|
xrandr --output ${PRI_PORT} --scale 1.35x1.35 |
|
# Reset "panning" so xrandr will tell us the virtual resolution of the screen. |
|
xrandr --output ${PRI_PORT} --panning 0x0 |
|
# Get the virtual resolution of the screen. |
|
SCALED_RES="$(xrandr | grep ${PRI_PORT} | sed -E 's/.* ([0-9]+x[0-9]+).*/\1/')" |
|
# Set the panning size to the virtual resolution of the screen to force it to properly fill the screen & avoid improper mou$ |
|
xrandr --output ${PRI_PORT} --panning ${SCALED_RES} |
|
EOF |
|
|
|
sudo chmod +x /mnt/arch/etc/X11/xinit/xinitrc.d/70-xrandr-scale.sh |
|
|
|
|
|
|
|
# #----------------------------------------------------------------------------------------------------------------------- |
|
# # KVM + VFIO + libvirt + qemu -- GPU passthrough. |
|
# # Older guide: |
|
# # http://www.se7ensins.com/forums/threads/how-to-setup-a-gaming-virtual-machine-with-gpu-passthrough-qemu-kvm-libvirt-and-vfio.1371980/ |
|
# # Newer guide: |
|
# # http://chanster.net/article/2016/03/05/qemu-gpu-passthrough/ |
|
|
|
# printf "\n\nConfiguring mkinitcpio to load the vfio related modules.\n" |
|
# sed -Ei 's/^MODULES=".*/MODULES="i915 vfio vfio_iommu_type1 vfio_pci vfio_virqfd"/' /mnt/arch/etc/mkinitcpio.conf |
|
|
|
# # DETACH GPU FROM HOST |
|
# if [ -e /mnt/arch/etc/modprobe.d/vfio.conf ]; then |
|
# cp -b --preserve /mnt/arch/etc/modprobe.d/vfio.conf{,-bak} |
|
# sed -Ei '/^options/d' /mnt/arch/etc/modprobe.d/vfio.conf |
|
# fi |
|
# echo "options vfio-pci ids=${NVIDIA_DEV_ID}" | tee /mnt/arch/etc/modprobe.d/vfio.conf |
|
|
|
# tee /mnt/arch/etc/modprobe.d/00-modprobe.conf <<'EOF' > /dev/null |
|
# blacklist radeon |
|
# blacklist nvidia |
|
# EOF |
|
|
|
# # Bind the addon GPU to VFIO. |
|
# # ls /sys/bus/pci/devices | grep -i '01:00.0\|01:00.1' |
|
# echo "DEVICES=\"0000:${NVIDIA_BUS_ID}\"" > /mnt/arch/usr/local/etc/vfio-devices |
|
|
|
# tee /mnt/arch/usr/local/bin/vfio-bind <<'EOF' > /dev/null |
|
# #!/bin/sh |
|
# # This script loads the vfio-pci module, locates the devices passed in as arguments and rebinds them to vfio-pci. |
|
# # http://chanster.net/article/2016/03/05/qemu-gpu-passthrough/ |
|
# modprobe vfio-pci |
|
# for dev in "$@"; do |
|
# vendor=$(cat /sys/bus/pci/devices/${dev}/vendor) |
|
# device=$(cat /sys/bus/pci/devices/${dev}/device) |
|
# if [ -e /sys/bus/pci/devices/${dev}/driver ]; then |
|
# echo ${dev} > /sys/bus/pci/devices/${dev}/driver/unbind |
|
# fi |
|
# echo ${vendor} ${device} > /sys/bus/pci/drivers/vfio-pci/new_id |
|
# done |
|
# EOF |
|
# chmod +x /mnt/arch/usr/local/bin/vfio-bind |
|
|
|
# tee /mnt/arch/usr/lib/systemd/system/vfio-bind.service <<'EOF' > /dev/null |
|
# [Unit] |
|
# Description=Binds devices to vfio-pci |
|
# After=syslog.target |
|
|
|
# [Service] |
|
# EnvironmentFile=-/usr/local/etc/vfio-bind |
|
# Type=oneshot |
|
# RemainAfterExit=yes |
|
# ExecStart=-/usr/local/bin/vfio-bind $DEVICES |
|
|
|
# [Install] |
|
# WantedBy=multi-user.target |
|
# EOF |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Configure Boot. |
|
|
|
printf "\n\nAdding the multidecrypt mkinitcpio hook.\n" |
|
tee /etc/initcpio/hooks/multidecrypt <<EOF > /dev/null |
|
#!/usr/bin/ash |
|
|
|
run_hook() { |
|
# set -x |
|
|
|
modprobe -a -q dm-crypt >/dev/null 2>&1 |
|
modprobe -a -q loop >/dev/null 2>&1 |
|
|
|
[ "\${quiet}" = "y" ] && CSQUIET=">/dev/null" |
|
|
|
if [ -z "\${multidecrypt}" ]; then |
|
err "No dm-crypt luks devices specified for multidecrypt, aborting..." |
|
exit 1 |
|
fi |
|
|
|
# Loop until the user provides a valid password. |
|
while ! eval cryptsetup open --type luks "/${KEYFILE_NAME}" "${KEYFILE_NAME}" \${CSQUIET}; do |
|
sleep 2; |
|
done |
|
|
|
if [ ! -e "${KEYFILE_MAPPED}" ]; then |
|
err "${KEYFILE_NAME} decryption failed, aborting..." |
|
exit 1 |
|
fi |
|
|
|
luksdevnum=1 |
|
mapdevnum=1 |
|
for luksdev in \${multidecryptswap//:/ }; do |
|
if resolved=\$(resolve_device "\${luksdev}" \${rootdelay}); then |
|
eval cryptsetup open --type luks \ |
|
--key-file "${KEYFILE_MAPPED}" \ |
|
--keyfile-offset \$(((\$luksdevnum-1)*512)) \ |
|
--keyfile-size 512 \ |
|
\${resolved} \ |
|
swap\${mapdevnum} \ |
|
\${CSQUIET} |
|
# swapDevice \ |
|
|
|
if [ ! -e "/dev/mapper/swap\${mapdevnum}" ]; then |
|
err "swap\${mapdevnum} creation failed, continuing with other specified devices..." |
|
fi |
|
else |
|
err "Could not resolve \${luksdev}, continuing with other specified devices..." |
|
fi |
|
let luksdevnum++ |
|
let mapdevnum++ |
|
done |
|
|
|
mapdevnum=1 |
|
for luksdev in \${multidecrypt//:/ }; do |
|
if resolved=\$(resolve_device "\${luksdev}" \${rootdelay}); then |
|
eval cryptsetup open --type luks \ |
|
--key-file "${KEYFILE_MAPPED}" \ |
|
--keyfile-offset \$(((\$luksdevnum-1)*512)) \ |
|
--keyfile-size 512 \ |
|
\${resolved} \ |
|
container\${mapdevnum} \ |
|
\${CSQUIET} |
|
|
|
if [ ! -e "/dev/mapper/container\${mapdevnum}" ]; then |
|
err "container\${mapdevnum} creation failed, continuing with other specified devices..." |
|
fi |
|
else |
|
err "Could not resolve \${luksdev}, continuing with other specified devices..." |
|
fi |
|
let luksdevnum++ |
|
let mapdevnum++ |
|
done |
|
|
|
# Clean up. |
|
cryptsetup close "${KEYFILE_NAME}" |
|
} |
|
|
|
# vim: set ft=sh ts=4 sw=4 et: |
|
EOF |
|
|
|
|
|
printf "\n\nAdding the multidecrypt mkinitcpio install.\n" |
|
tee /etc/initcpio/install/multidecrypt <<EOF > /dev/null |
|
#!/bin/bash |
|
|
|
build() { |
|
local mod |
|
|
|
add_module dm-crypt |
|
if [[ \${CRYPTO_MODULES} ]]; then |
|
for mod in \${CRYPTO_MODULES}; do |
|
add_module "\$mod" |
|
done |
|
else |
|
add_all_modules '/crypto/' |
|
fi |
|
|
|
# add loop module for mounting of keyfile |
|
add_module loop |
|
|
|
add_binary "cryptsetup" |
|
add_binary "dmsetup" |
|
add_file "/usr/lib/udev/rules.d/10-dm.rules" |
|
add_file "/usr/lib/udev/rules.d/13-dm-disk.rules" |
|
add_file "/usr/lib/udev/rules.d/95-dm-notify.rules" |
|
add_file "/usr/lib/initcpio/udev/11-dm-initramfs.rules" "/usr/lib/udev/rules.d/11-dm-initramfs.rules" |
|
|
|
add_file "/boot/${KEYFILE_NAME}" "/${KEYFILE_NAME}" |
|
|
|
add_runscript |
|
} |
|
|
|
help() { |
|
cat <<HELPEOF |
|
This hook allows for startup decryption of multiple dm-crypt luks encrypted |
|
devices. Users should specify the devices to be unlocked using: |
|
|
|
'multidecrypt=device[[:device]...]' |
|
|
|
on the kernel command line, where 'device' is the path to the raw device, |
|
specified using PARTUUID or some other means. Devices will be available as |
|
/dev/mapper/container[1,2,3...] etc. |
|
|
|
The hook expects a dm-crypt luks encrypted file called /boot/${KEYFILE_NAME} to |
|
exist. This keyfile contains a concatenation of 4096 bit keys for each |
|
encrypted device in the same order as specified in the multidecrypt kernel |
|
command line argument. |
|
|
|
If decryption of one of the devices fails, the hook will attempt to continue |
|
to decrypt any other specified devices. This is useful for btrfs software |
|
raid if a device has failed as an example. |
|
|
|
You will be prompted for the password to the ${KEYFILE_NAME} container at runtime. |
|
This means you must have a keyboard available to input it, and you may need the |
|
keymap hook as well to ensure that the keyboard is using the layout you expect. |
|
HELPEOF |
|
} |
|
|
|
# vim: set ft=sh ts=4 sw=4 et: |
|
EOF |
|
|
|
|
|
cp -Rf /etc/initcpio/{hooks,install} /mnt/arch/etc/initcpio/ |
|
|
|
|
|
printf "\n\nConfiguring mkinitcpio to use multidecrypt hook.\n" |
|
sed -i 's/^HOOKS=.*/HOOKS="base udev multidecrypt mdadm_udev resume modconf block filesystems fsck btrfs keyboard autodetect"/' \ |
|
/mnt/arch/etc/mkinitcpio.conf |
|
|
|
|
|
printf "\n\nGathering partition UUIDs for both btrfs partitions used in RAID 0 (stripe)." |
|
# Will be mounted by multidecrypt. |
|
PART_DATA1_PARTUUID="$(blkid -s PARTUUID -o value "${PART_DATA1}")" |
|
PART_DATA2_PARTUUID="$(blkid -s PARTUUID -o value "${PART_DATA2}")" |
|
PART_SWAP1_PARTUUID="$(blkid -s PARTUUID -o value "${PART_SWAP1}")" |
|
PART_SWAP2_PARTUUID="$(blkid -s PARTUUID -o value "${PART_SWAP2}")" |
|
SWAP_UUID="$(blkid -s UUID -o value "${SWAP_RAID}")" |
|
# Will be mounted by BTRFS. |
|
ROOT_UUID="$(blkid -s UUID -o value "${DATA1_MAPPED}")" |
|
|
|
|
|
# Get rid fo the mkinitcpio error, "ERROR: file not found: 'fsck.btrfs'". |
|
rm -f /bin/fsck.btrfs |
|
|
|
|
|
printf "\n\nInstalling boot control.\n" |
|
arch-chroot /mnt/arch /bin/bash <<EOF |
|
# set -x |
|
|
|
# Make sure efivars are loaded. |
|
mount -t efivarfs efivarfs /sys/firmware/efi/efivars |
|
|
|
# Regenerate initrd image |
|
mkinitcpio -p linux |
|
|
|
|
|
# Prune linux boot entries. |
|
set +e |
|
IFS=' |
|
' |
|
for ITEM in \$(efibootmgr); do |
|
echo "scanning \${ITEM}..." |
|
|
|
# If statements with []'s are not working properly here so we'll just use "test" directly. |
|
test "\${ITEM#*inux}" == "\${ITEM}" && continue |
|
|
|
BOOTNUM="\$(echo "\${ITEM}" | sed -e 's/^[Bb]oot\([a-zA-Z0-9]*\).*/\1/')" |
|
|
|
echo "Removing boot num \${BOOTNUM}, entry: \${ITEM}." |
|
efibootmgr --bootnum "\${BOOTNUM}" --delete-bootnum |
|
echo "Done removing boot entry: \${ITEM}." |
|
done |
|
set -e |
|
|
|
|
|
# # Install EFI boot image. |
|
# efibootmgr \ |
|
# --create \ |
|
# --disk ${DEV_DRIVE1} \ |
|
# --part ${PARTNUM_EFI} \ |
|
# --label "Arch Linux" \ |
|
# --loader /vmlinuz-linux \ |
|
# --timeout 2 \ |
|
# --unicode "multidecryptswap=PARTUUID=${PART_SWAP1_PARTUUID}:PARTUUID=${PART_SWAP2_PARTUUID} multidecrypt=PARTUUID=${PART_DATA1_PARTUUID}:PARTUUID=${PART_DATA2_PARTUUID} root=UUID=${ROOT_UUID} rw rootflags=subvol=@ resume=UUID=${SWAP_UUID} initrd=\\intel-ucode.img initrd=\\initramfs-linux.img" |
|
|
|
bootctl install |
|
|
|
exit 0 |
|
EOF |
|
|
|
|
|
# systemd-boot arch linux config. |
|
tee /mnt/arch/boot/loader/entries/arch.conf <<EOF > /dev/null |
|
title Arch Linux |
|
linux /vmlinuz-linux |
|
initrd /intel-ucode.img |
|
initrd /initramfs-linux.img |
|
# "iommu=pt" : to avoid DMAR errors. |
|
# "i915.enable_hd_vgaarb=1" : use this if you're not getting monitor sync when the VM starts, because there's probably a |
|
# problem with VGA arbitration or the device ROM; this addresses the former. You may need to use linux-vfio kernel. |
|
options multidecryptswap=PARTUUID=${PART_SWAP1_PARTUUID}:PARTUUID=${PART_SWAP2_PARTUUID} multidecrypt=PARTUUID=${PART_DATA1_PARTUUID}:PARTUUID=${PART_DATA2_PARTUUID} root=UUID=${ROOT_UUID} rw rootflags=subvol=@ resume=UUID=${SWAP_UUID} quiet pcie_acs_override=downstream rd.modules-load=vfio-pci iommu=pt intel_iommu=on |
|
EOF |
|
|
|
|
|
# systemd-boot loader config. |
|
tee /mnt/arch/boot/loader/loader.conf <<EOF > /dev/null |
|
timeout 0 |
|
default arch |
|
EOF |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Setup snapshot system. |
|
# http://ramsdenj.com/2016/04/05/Using-Btrfs-for-Easy-Backup-and-Rollback.html |
|
|
|
printf "\n\nSetup btrfs snapshot management.\n" |
|
|
|
arch-chroot /mnt/arch /bin/bash <<-EOC |
|
# Remove unwanted grub hook since we do not use grub, which will avoid a safe-to-ignore error that will show up each |
|
# time snap-pac is updated. |
|
rm -f /usr/share/libalpm/hooks/99_grub-config.hook |
|
|
|
# Create the snapper configuration files for root and home. |
|
snapper --no-dbus -c root create-config / |
|
snapper --no-dbus -c home create-config /home |
|
|
|
# Snapper makes unwanted subvols. |
|
btrfs sub delete /.snapshots |
|
btrfs sub delete /home/.snapshots |
|
|
|
# Create desirable snapshot subvols for root & home. |
|
btrfs sub create /mnt/btrfs-pool/@snapshots/root |
|
btrfs sub create /mnt/btrfs-pool/@snapshots/home |
|
|
|
# Create the paths snapper will be looking for & mount the above subvols to them. |
|
mkdir /home/.snapshots |
|
mkdir /.snapshots |
|
mount -t btrfs -o defaults,compress=lzo,subvol=@snapshots/home "${DATA1_MAPPED}" /home/.snapshots |
|
mount -t btrfs -o defaults,compress=lzo,subvol=@snapshots/root "${DATA1_MAPPED}" /.snapshots |
|
EOC |
|
|
|
# Regen fstab, pruning out efivars, gvfsd-fuse & external media. |
|
printf "\n\nRegenerating fstab.\n" |
|
# # Breakdown of actions: |
|
# # 1. Generates the new fstab. |
|
# # 2. Inverse the file. |
|
# # 3. Removes all lines containing "efivars", "gvfsd-fuse" or "/run/media", as well as the line below them. |
|
# # 4. Inverse the file again. |
|
# # 5. Write the file to /etc/fstab. |
|
# genfstab -pU /mnt/arch | tac | sed '/(efivarfs|gvfsd-fuse|\/run\/media)/I,+2 d' | tac | tee /mnt/arch/etc/fstab |
|
genfstab -pU /mnt/arch > /mnt/arch/etc/fstab |
|
cat /mnt/arch/etc/fstab |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Setup the users. |
|
|
|
printf "\n\nPlease enter below the desired root password.\n" |
|
arch-chroot /mnt/arch /bin/bash -c 'passwd' |
|
|
|
printf "\n\nAdding user '%s'.\n" "${DESIRED_USERNAME}" |
|
arch-chroot /mnt/arch /bin/bash -c "groups '${DESIRED_USERNAME}' > /dev/null 2>&1 || useradd --create-home --groups wheel,storage,power,users,audio,video,optical --shell /bin/bash ${DESIRED_USERNAME}" |
|
printf "\n\nPlease enter below the desired password for ${DESIRED_USERNAME}.\n" |
|
arch-chroot /mnt/arch /bin/bash -c "passwd ${DESIRED_USERNAME}" |
|
|
|
printf "\n\nAllowing ${DESIRED_USERNAME} to sudo without a password.\n" |
|
sudo tee "/mnt/arch/etc/sudoers.d/${DESIRED_USERNAME}" <<EOF > /dev/null |
|
${DESIRED_USERNAME} ALL=NOPASSWD: ALL |
|
EOF |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Add a convenience script. |
|
|
|
# NOTE: Short URL resolves to: https://gist.github.com/redeemed2011/3387d18d5e8f0274b0e3/raw/post-install-additions.sh |
|
wget https://goo.gl/HGlSC3 -O "/mnt/arch/home/${DESIRED_USERNAME}/post-install-additions.sh" |
|
arch-chroot /mnt/arch /bin/bash <<EOC |
|
chown '${DESIRED_USERNAME}:${DESIRED_USERNAME}' '/home/${DESIRED_USERNAME}/post-install-additions.sh' |
|
chmod +x '/home/${DESIRED_USERNAME}/post-install-additions.sh' |
|
EOC |
|
|
|
|
|
|
|
#----------------------------------------------------------------------------------------------------------------------- |
|
# Cleanup. |
|
|
|
unmount_all |
I expect that every time I try to update the URL for
wget ... installer.sh, that the hash will change. Just know that at this time the link in the document is correct.I've not updated this code in years.