Compare commits

..

8 Commits

Author SHA1 Message Date
kris ead7a9f24e Fix mirror zpool installation 2022-11-29 02:02:14 -05:00
kris 5e6dc73ce5 Allow word splitting for mirror use case 2022-11-28 02:17:04 -05:00
kris c4cf616f7b Convert disk paths for zpool creation 2022-11-28 02:07:55 -05:00
kris aaa74697a5 Quote variables in zfsenv 2022-11-28 01:21:10 -05:00
kris babc015294 Add disk_by_id function 2022-11-28 00:53:09 -05:00
kris 087070a3d4 Add post-install helper script for GRUB mirror 2022-11-27 20:50:20 -05:00
kris 0d99930fa7 Minor touchups 2022-11-27 19:51:30 -05:00
kris e96a557d9a Use tabs over spaces 2022-11-27 19:48:44 -05:00
+195 -115
View File
@@ -7,92 +7,135 @@
### Functions ### ### Functions ###
################# #################
function usage () { function usage () {
echo "Usage: ./$(basename "$0") [-mpPr] <DISK> [hostname]" echo "Usage: ./$(basename "$0") [-mpPr] <DISK> <HOSTNAME>"
} }
function disk_check () { function disk_check () {
DISK_TYPE=$(file "$1" | awk '{ print $2$3 }') DISK_TYPE=$(file "$1" | awk '{ print $2$3 }')
if [ "$DISK_TYPE" != "blockspecial" ]; then if [ "$DISK_TYPE" != "blockspecial" ]; then
echo "ERROR: Disk '$1' is not a block device" echo "ERROR: Disk '$1' is not a block device"
exit 1 exit 1
fi fi
} }
function disk_status () { function disk_status () {
OUTPUT=$(wipefs "$1") OUTPUT=$(wipefs "$1")
if [ -n "$OUTPUT" ]; then if [ -n "$OUTPUT" ]; then
echo "ERROR: $1 is not empty" echo "ERROR: $1 is not empty"
echo "$OUTPUT" echo "$OUTPUT"
exit 1 exit 1
fi fi
} }
function password_prompt () { function password_prompt () {
unset PASSWORD_PROMPT_RESULT unset PASSWORD_PROMPT_RESULT
while true; do while true; do
read -r -s -p "${1}: " password read -r -s -p "${1}: " password
echo '' echo ''
read -r -s -p "${1} (confirm): " password_confirm read -r -s -p "${1} (confirm): " password_confirm
echo '' echo ''
if [ "$password" == "$password_confirm" ]; then if [ "$password" == "$password_confirm" ]; then
if [ -z "$password" ]; then if [ -z "$password" ]; then
echo "Password can not be empty, try again." echo "Password can not be empty, try again."
else else
break break
fi fi
else else
echo "Passwords did not match, try again." echo "Passwords did not match, try again."
fi fi
done done
PASSWORD_PROMPT_RESULT="$password" PASSWORD_PROMPT_RESULT="$password"
export PASSWORD_PROMPT_RESULT export PASSWORD_PROMPT_RESULT
} }
function disk_format () { function disk_format () {
sgdisk -n2:1M:+512M -t2:EF00 "$1" sgdisk -n2:1M:+512M -t2:EF00 "$1"
sgdisk -n3:0:+1G -t3:BF01 "$1" sgdisk -n3:0:+1G -t3:BF01 "$1"
sgdisk -n4:0:0 -t4:BF00 "$1" sgdisk -n4:0:0 -t4:BF00 "$1"
} }
function create_boot_pool () { function create_boot_pool () {
zpool create -f \ # shellcheck disable=SC2086
-o ashift=12 \ zpool create -f \
-o autotrim=on -d \ -o ashift=12 \
-o cachefile=/etc/zfs/zpool.cache \ -o autotrim=on -d \
-o feature@async_destroy=enabled \ -o cachefile=/etc/zfs/zpool.cache \
-o feature@bookmarks=enabled \ -o feature@async_destroy=enabled \
-o feature@embedded_data=enabled \ -o feature@bookmarks=enabled \
-o feature@empty_bpobj=enabled \ -o feature@embedded_data=enabled \
-o feature@enabled_txg=enabled \ -o feature@empty_bpobj=enabled \
-o feature@extensible_dataset=enabled \ -o feature@enabled_txg=enabled \
-o feature@filesystem_limits=enabled \ -o feature@extensible_dataset=enabled \
-o feature@hole_birth=enabled \ -o feature@filesystem_limits=enabled \
-o feature@large_blocks=enabled \ -o feature@hole_birth=enabled \
-o feature@livelist=enabled \ -o feature@large_blocks=enabled \
-o feature@lz4_compress=enabled \ -o feature@livelist=enabled \
-o feature@spacemap_histogram=enabled \ -o feature@lz4_compress=enabled \
-o feature@zpool_checkpoint=enabled \ -o feature@spacemap_histogram=enabled \
-O devices=off \ -o feature@zpool_checkpoint=enabled \
-O acltype=posixacl -O xattr=sa \ -O devices=off \
-O compression=lz4 \ -O acltype=posixacl -O xattr=sa \
-O normalization=formD \ -O compression=lz4 \
-O relatime=on \ -O normalization=formD \
-O canmount=off -O mountpoint=/boot -R "$1" \ -O relatime=on \
bpool "$2" -O canmount=off -O mountpoint=/boot -R "$1" \
bpool $2
} }
function create_root_pool () { function create_root_pool () {
echo "$3" | zpool create -f \ # shellcheck disable=SC2086
-o ashift=12 \ echo "$3" | zpool create -f \
-o autotrim=on \ -o ashift=12 \
-O encryption=on -O keylocation=prompt -O keyformat=passphrase \ -o autotrim=on \
-O acltype=posixacl -O xattr=sa -O dnodesize=auto \ -O encryption=on -O keylocation=prompt -O keyformat=passphrase \
-O compression=lz4 \ -O acltype=posixacl -O xattr=sa -O dnodesize=auto \
-O normalization=formD \ -O compression=lz4 \
-O relatime=on \ -O normalization=formD \
-O canmount=off -O mountpoint=/ -R "$1" \ -O relatime=on \
rpool "$2" -O canmount=off -O mountpoint=/ -R "$1" \
rpool $2
}
function part_path () {
DISK="$1"
PART="$2"
[ "$(disk_check "$DISK")" == 1 ] && exit 1
if [ "${DISK:0:7}" == "/dev/sd" ]; then
DISK_PART="${DISK}${PART}"
elif [ "${DISK:0:9}" == "/dev/nvme" ]; then
DISK_PART="${DISK}p${PART}"
else
echo "ERROR: Disk not recognized"
exit 1
fi
[ "$(disk_check "$DISK_PART")" == 1 ] && exit 1
echo "$DISK_PART"
exit 0
}
function part_by_uuid () {
OUTPUT=$(
blkid -s UUID | grep -e "^${1}.*${2}: UUID=" | \
awk '{ print substr($2, 7, length($2)-7) }'
)
if [ -z "$OUTPUT" ]; then
echo "ERROR: No disk by-uuid label found for: ${1}, partition ${2}"
exit 1
fi
echo "/dev/disk/by-uuid/$OUTPUT"
}
function mirror_grub () {
DISK1_PART2="$(part_by_uuid "$1" 2)"
DISK2_PART2="$(part_by_uuid "$2" 2)"
umount /boot/efi
dd if="$DISK1_PART2" of="$DISK2_PART2"
efibootmgr -c -g -d "$DISK2" -p 2 \
-L "debian-${3}" -l '\EFI\debian\grubx64.efi'
mount /boot/efi
} }
################ ################
@@ -103,16 +146,17 @@ export DEBIAN_FRONTEND=noninteractive
CODENAME="bullseye" CODENAME="bullseye"
# Options # Options
while getopts ':m:p:P:r:' OPTION; do while getopts ':gm:p:P:r:' OPTION; do
case "$OPTION" in case "$OPTION" in
m) MIRROR="$OPTARG";; g) GRUB_MIRROR="true";;
p) ROOTPW="$OPTARG";; m) MIRROR="$OPTARG";;
P) RPOOLPW="$OPTARG";; p) ROOTPW="$OPTARG";;
r) ZFSROOT="$OPTARG";; P) RPOOLPW="$OPTARG";;
?) r) ZFSROOT="$OPTARG";;
usage ?)
exit 1;; usage
esac exit 1;;
esac
done done
shift "$((OPTIND -1))" shift "$((OPTIND -1))"
@@ -120,59 +164,77 @@ shift "$((OPTIND -1))"
DISK=$1 DISK=$1
ZFSHOST=$2 ZFSHOST=$2
# Post-boot grub mirror?
if [ "$GRUB_MIRROR" == "true" ]; then
while true; do
echo -e "ORIGINAL GRUB: $DISK\nMIRROR TO: $MIRROR"
read -r -p "Would you like to mirror GRUB? [y/N]: " yn
case $yn in
[Yy]*)
disk_check "$DISK"
disk_check "$MIRROR"
mirror_grub "$DISK" "$MIRROR" 2
exit 0;;
?)
echo "ABORTED: User did not confirm mirroring"
exit 1;;
esac
done
fi
# Verify variables # Verify variables
[ -z "$ZFSROOT" ] && ZFSROOT="/mnt" [ -z "$ZFSROOT" ] && ZFSROOT="/mnt"
if [ -z "$DISK" ]; then if [ -z "$DISK" ]; then
echo "ERROR: DISK not set" echo "ERROR: DISK not set"
usage usage
exit 1 exit 1
fi fi
if [ -z "$ZFSHOST" ]; then if [ -z "$ZFSHOST" ]; then
echo "ERROR: HOSTNAME not set" echo "ERROR: HOSTNAME not set"
usage usage
exit 1 exit 1
fi fi
if [ -z "$ROOTPW" ]; then if [ -z "$ROOTPW" ]; then
password_prompt "Root Passphrase" password_prompt "Root Passphrase"
ROOTPW="$PASSWORD_PROMPT_RESULT" ROOTPW="$PASSWORD_PROMPT_RESULT"
unset PASSWORD_PROMPT_RESULT unset PASSWORD_PROMPT_RESULT
fi fi
if [ -z "$RPOOLPW" ]; then if [ -z "$RPOOLPW" ]; then
password_prompt "ZFS Encryption Passphrase" password_prompt "ZFS Encryption Passphrase"
RPOOLPW="$PASSWORD_PROMPT_RESULT" RPOOLPW="$PASSWORD_PROMPT_RESULT"
unset PASSWORD_PROMPT_RESULT unset PASSWORD_PROMPT_RESULT
fi fi
if [ "$DEBUG" == "true" ]; then if [ "$DEBUG" == "true" ]; then
echo "CODENAME=${CODENAME}" echo "CODENAME=${CODENAME}"
echo "DISK=${DISK}" echo "DISK=${DISK}"
echo "ZFSHOST=${ZFSHOST}" echo "ZFSHOST=${ZFSHOST}"
echo "ZFSROOT=${ZFSROOT}" echo "ZFSROOT=${ZFSROOT}"
echo "MIRROR=${MIRROR}" echo "MIRROR=${MIRROR}"
echo "ROOTPW=${ROOTPW}" echo "ROOTPW=${ROOTPW}"
echo "RPOOLPW=${RPOOLPW}" echo "RPOOLPW=${RPOOLPW}"
fi fi
# Display commands
set -x
# Are the DISK paths block devices? AND # Are the DISK paths block devices? AND
# Are the DISK pathes empty devices? i.e., no filesystem signatures # Are the DISK pathes empty devices? i.e., no filesystem signatures
disk_check "$DISK" disk_check "$DISK"
disk_status "$DISK" disk_status "$DISK"
if [ -n "$MIRROR" ]; then if [ -n "$MIRROR" ]; then
disk_check "$MIRROR" disk_check "$MIRROR"
disk_status "$MIRROR" disk_status "$MIRROR"
fi fi
############################################### ###############################################
### Step 1: Prepare The Install Environment ### ### Step 1: Prepare The Install Environment ###
############################################### ###############################################
# Display commands
set -xe
# 1. Boot the Debian GNU/Linux Live CD... done # 1. Boot the Debian GNU/Linux Live CD... done
# 2. Setup and update the repositories # 2. Setup and update the repositories
SOURCES_LIST="/etc/apt/sources.list" SOURCES_LIST="/etc/apt/sources.list"
@@ -198,20 +260,21 @@ swapoff --all
# 3. Partition your disk(s) # 3. Partition your disk(s)
# UEFI booting + boot pool + ZFS native encryption # UEFI booting + boot pool + ZFS native encryption
disk_format "$DISK" disk_format "$DISK"
[ -n "$MIRROR" ] && disk_format "$MIRROR" if [ -n "$MIRROR" ]; then
disk_format "$MIRROR"
fi
sleep 5
# 4. Create the boot pool # 4. Create the boot pool
if [ -z "$MIRROR" ]; then
create_boot_pool "$ZFSROOT" "${DISK}3"
else
create_boot_pool "$ZFSROOT" "mirror ${DISK}3 ${MIRROR}3"
fi
# 5. Create the root pool # 5. Create the root pool
if [ -z "$MIRROR" ]; then if [ -z "$MIRROR" ]; then
create_root_pool "$ZFSROOT" "${DISK}4" "$RPOOLPW" create_boot_pool "$ZFSROOT" "$(part_path "$DISK" 3)"
create_root_pool "$ZFSROOT" "$(part_path "$DISK" 4)" "$RPOOLPW"
else else
create_root_pool "$ZFSROOT" "mirror ${DISK}4 ${MIRROR}4" "$RPOOLPW" create_boot_pool "$ZFSROOT" \
"mirror $(part_path "$DISK" 3) $(part_path "$MIRROR" 3)"
create_root_pool "$ZFSROOT" \
"mirror $(part_path "$DISK" 4) $(part_path "$MIRROR" 4)" "$RPOOLPW"
fi fi
################################### ###################################
@@ -301,7 +364,21 @@ EOF
# 4. Bind the virtual filesystems from the LiveCD environment to the new system and chroot into it # 4. Bind the virtual filesystems from the LiveCD environment to the new system and chroot into it
# Copy DISK/MIRROR vars under ZFSROOT # Copy DISK/MIRROR vars under ZFSROOT
echo -e "DISK=${DISK}\nROOTPW=${ROOTPW}" > "$ZFSROOT/var/tmp/zfsenv" echo -e "DISK=\"$(part_path "$DISK" 2)\"\nROOTPW=\"${ROOTPW}\"" > "$ZFSROOT/var/tmp/zfsenv"
# Copy self and GRUB mirror helper script into chroot
if [ -n "$MIRROR" ]; then
cp "$0" "$ZFSROOT/usr/local/bin/debianzfs"
chmod u+x "$ZFSROOT/usr/local/bin/debianzfs"
HELPER_SCRIPT="/root/MIRROR_GRUB_POSTINSTALL.sh"
cat <<-GRUBMIRROR > "${ZFSROOT}${HELPER_SCRIPT}"
#!/bin/bash
# Post-install GRUB mirror helper script
/usr/local/bin/debianzfs \
-gm $(disk_by_id "$MIRROR") \
$(disk_by_id "$DISK")
GRUBMIRROR
fi
# Bind # Bind
mount --make-private --rbind /dev /mnt/dev mount --make-private --rbind /dev /mnt/dev
@@ -316,6 +393,7 @@ export LC_CTYPE=en_US.UTF-8
export LC_ALL=en_US.UTF-8 export LC_ALL=en_US.UTF-8
set -ex set -ex
. /var/tmp/zfsenv . /var/tmp/zfsenv
rm -f /var/tmp/zfsenv
unset CDPATH unset CDPATH
cd cd
@@ -336,9 +414,9 @@ echo REMAKE_INITRD=yes > /etc/dkms/zfs.conf
# Install GRUB for UEFI booting # Install GRUB for UEFI booting
apt-get install -y dosfstools apt-get install -y dosfstools
mkdosfs -F 32 -s 1 -n EFI "\${DISK}2" mkdosfs -F 32 -s 1 -n EFI "\${DISK}"
mkdir /boot/efi mkdir /boot/efi
BLKID_BOOT="/dev/disk/by-uuid/\$(blkid -s UUID -o value \${DISK}2)" BLKID_BOOT="/dev/disk/by-uuid/\$(blkid -s UUID -o value \${DISK})"
echo "\${BLKID_BOOT} /boot/efi vfat defaults 0 0" >> /etc/fstab echo "\${BLKID_BOOT} /boot/efi vfat defaults 0 0" >> /etc/fstab
mount /boot/efi mount /boot/efi
apt-get install -y grub-efi-amd64 shim-signed apt-get install -y grub-efi-amd64 shim-signed
@@ -403,7 +481,7 @@ update-grub
# 6. Install the boot loader # 6. Install the boot loader
# For UEFI booting, install GRUB to the ESP # For UEFI booting, install GRUB to the ESP
grub-install --target=x86_64-efi --efi-directory=/boot/efi \ grub-install --target=x86_64-efi --efi-directory=/boot/efi \
--bootloader-id=debian --recheck --no-floppy --bootloader-id=debian --recheck --no-floppy
# 7. Fix filesystem mount ordering # 7. Fix filesystem mount ordering
mkdir /etc/zfs/zfs-list.cache mkdir /etc/zfs/zfs-list.cache
@@ -432,9 +510,11 @@ CHROOT
# 3. Run these commands in the LiveCD environment to unmount all filesystems # 3. Run these commands in the LiveCD environment to unmount all filesystems
mount | grep -v zfs | tac | awk '/\/mnt/ {print $3}' | \ mount | grep -v zfs | tac | awk '/\/mnt/ {print $3}' | \
xargs -I{} umount -lf {} xargs -I{} umount -lf {}
# 4. If this fails for rpool, mounting it on boot will fail and you will need to # 4. If this fails for rpool, mounting it on boot will fail and you will need to
# zpool import -f rpool, then exit in the initamfs prompt # zpool import -f rpool, then exit in the initamfs prompt
zpool export -a || exit 0 zpool export -a || exit 0
[ -n "$HELPER_SCRIPT" ] && \
echo "NOTICE: A GRUB mirror helper script was placed at $HELPER_SCRIPT"
exit 0 exit 0