|
#!/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='China' |
|
DESIRED_TIMEZONE='Asia/Shanghai' |
|
DESIRED_LOCALE='en_US.UTF-8 UTF-8' |
|
DESIRED_LOCALE2='en_US.UTF-8' |
|
DESIRED_LANGUAGE='en_US' |
|
DESIRED_HOSTNAME='Jesse-Arch' |
|
DESIRED_USERNAME='jesse' |
|
# 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() { |
|
reflector --country ${DESIRED_COUNTRY} --latest 5 --protocol https --sort rate --save /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 |
|
tee -a /etc/pacman.conf <<'EOF' > /dev/null |
|
|
|
[multilib] |
|
Include = /etc/pacman.d/mirrorlist |
|
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 |