summaryrefslogtreecommitdiff
path: root/assets/zfs/stage1.sh
diff options
context:
space:
mode:
Diffstat (limited to 'assets/zfs/stage1.sh')
-rwxr-xr-xassets/zfs/stage1.sh210
1 files changed, 210 insertions, 0 deletions
diff --git a/assets/zfs/stage1.sh b/assets/zfs/stage1.sh
new file mode 100755
index 0000000..392ff74
--- /dev/null
+++ b/assets/zfs/stage1.sh
@@ -0,0 +1,210 @@
+#!/usr/bin/env bash
+# install arch linux on zfs root, stage one
+# Craig Jennings <c@cjennings.net>
+#
+# https://openzfs.github.io/openzfs-docs/Getting%20Started/Arch%20Linux/Root%20on%20ZFS.html
+#
+
+set -e # halt on any error
+
+# -------------------------- Prerequisites --------------------------
+
+sed -i "s/^#ParallelDownloads = 5$/ParallelDownloads = 15/" /etc/pacman.conf
+# These are now done in stage 0
+# pacman-key --init
+# pacman-key --refresh-keys
+# pacman --noconfirm -Sy archlinux-keyring
+loadkeys us
+timedatectl set-ntp true
+
+### --------------------------- Choose Disk ---------------------------
+
+all_disk_ids=( $(ls /dev/disk/by-id/) )
+echo ""; echo "Select the disk id to use. All data will be erased."
+select disk_id in "${all_disk_ids[@]}"; do
+ # ensure valid selection
+ if [[ -n $disk_id ]]; then
+ selection=$disk_id
+ break
+ else
+ echo "Invalid. Try again."
+ fi
+done
+
+# Confirm the selected disk
+read -p "Confirm: '$selection' [y/n]? " choice
+if [[ "$choice" != "y" ]]; then
+ echo "Exiting..."
+ exit 1
+fi
+
+DISK="/dev/disk/by-id/$selection"
+MNT=/mnt # Set a mount point
+SWAPSIZE=4 # Set swap size in GB
+RESERVE=1 # Set how much space to leave at the end of disk, minimum 1GB
+
+### --------------------------- Erase Disk -------------------------
+echo ""; echo "### Erasing Disk"
+blkdiscard -f "${DISK}" || true # discard all sectors on flash-based storage
+sgdisk --zap-all "${DISK}" # clear the disk
+
+### ------------------------- Partition Disk ------------------------
+echo ""; echo "### Partitioning Disk"
+parted --script --align=optimal "${DISK}" -- \
+ mklabel gpt \
+ mkpart EFI 2MiB 1GiB \
+ mkpart bpool 1GiB 5GiB \
+ mkpart rpool 5GiB -$((SWAPSIZE + RESERVE))GiB \
+ mkpart swap -$((SWAPSIZE + RESERVE))GiB -"${RESERVE}"GiB \
+ mkpart BIOS 1MiB 2MiB \
+ set 1 esp on \
+ set 5 bios_grub on \
+ set 5 legacy_boot on
+
+### ---------------------- Setup Encrypted Swap ---------------------
+echo ""; echo "### Encrypted Swap"
+for i in ${DISK}; do
+ cryptsetup open --type plain --key-file /dev/random "${i}"-part4 "${i##*/}"-part4
+ mkswap /dev/mapper/"${i##*/}"-part4
+ swapon /dev/mapper/"${i##*/}"-part4
+done
+
+# ------------------- Create Boot And Root Pools ------------------
+
+# This step creates a separate boot pool for /boot with the features limited to
+# only those that GRUB supports, allowing the root pool to use any/all features.
+
+echo ""; echo "### Checking ZFS Module"
+modprobe zfs # ensure zfs module is loaded
+
+echo ""; echo "### Creating Boot Pool"
+# shellcheck disable=SC2046
+zpool create -d \
+ -o feature@async_destroy=enabled \
+ -o feature@bookmarks=enabled \
+ -o feature@embedded_data=enabled \
+ -o feature@empty_bpobj=enabled \
+ -o feature@enabled_txg=enabled \
+ -o feature@extensible_dataset=enabled \
+ -o feature@filesystem_limits=enabled \
+ -o feature@hole_birth=enabled \
+ -o feature@large_blocks=enabled \
+ -o feature@lz4_compress=enabled \
+ -o feature@spacemap_histogram=enabled \
+ -o ashift=12 \
+ -o autotrim=on \
+ -O acltype=posixacl \
+ -O canmount=off \
+ -O compression=lz4 \
+ -O devices=off \
+ -O normalization=formD \
+ -O relatime=on \
+ -O xattr=sa \
+ -O mountpoint=/boot \
+ -R "${MNT}" \
+ bpool \
+ $(for i in ${DISK}; do
+ printf '%s ' "${i}-part2";
+ done)
+
+echo ""; echo "### Creating Root Pool"
+# shellcheck disable=SC2046
+zpool create \
+ -o ashift=12 \
+ -o autotrim=on \
+ -R "${MNT}" \
+ -O acltype=posixacl \
+ -O canmount=off \
+ -O compression=zstd \
+ -O dnodesize=auto \
+ -O normalization=formD \
+ -O relatime=on \
+ -O xattr=sa \
+ -O mountpoint=/ \
+ rpool \
+ $(for i in ${DISK}; do
+ printf '%s ' "${i}-part3";
+ done)
+
+echo ""; echo "### Creating Unencrypted Root System Container"
+# create UNENCRYPTED root system container
+zfs create \
+ -o canmount=off \
+ -o mountpoint=none \
+rpool/archlinux
+
+# --------------------- Create System Datasets --------------------
+echo ""; echo "### Creating System Datasets"
+zfs create -o canmount=noauto -o mountpoint=/ rpool/archlinux/root
+zfs mount rpool/archlinux/root
+zfs create -o mountpoint=legacy rpool/archlinux/home
+mkdir "${MNT}"/home
+mount -t zfs rpool/archlinux/home "${MNT}"/home
+zfs create -o mountpoint=legacy rpool/archlinux/var
+zfs create -o mountpoint=legacy rpool/archlinux/var/lib
+zfs create -o mountpoint=legacy rpool/archlinux/var/log
+zfs create -o mountpoint=none bpool/archlinux
+zfs create -o mountpoint=legacy bpool/archlinux/root
+mkdir "${MNT}"/boot
+mount -t zfs bpool/archlinux/root "${MNT}"/boot
+mkdir -p "${MNT}"/var/log
+mkdir -p "${MNT}"/var/lib
+mount -t zfs rpool/archlinux/var/lib "${MNT}"/var/lib
+mount -t zfs rpool/archlinux/var/log "${MNT}"/var/log
+
+# ---------------------- Format And Mount ESP ---------------------
+echo ""; echo "### Format And Mount ESP"
+for i in ${DISK}; do
+ mkfs.vfat -n EFI "${i}"-part1
+ mkdir -p "${MNT}"/boot/efis/"${i##*/}"-part1
+ mount -t vfat -o iocharset=iso8859-1 "${i}"-part1 "${MNT}"/boot/efis/"${i##*/}"-part1
+done
+
+mkdir -p "${MNT}"/boot/efi
+mount -t vfat -o iocharset=iso8859-1 "$(echo "${DISK}" | sed "s|^ *||" | cut -f1 -d' '|| true)"-part1 "${MNT}"/boot/efi
+
+### -------------------------- Install Base -------------------------
+echo ""; echo "### Installing Base"
+# install packages with pacstrap
+pacstrap "${MNT}" \
+ base \
+ base-devel \
+ dkms \
+ efibootmgr \
+ git \
+ grub \
+ intel-ucode \
+ linux-firmware \
+ linux-lts \
+ linux-lts-headers \
+ man-db \
+ man-pages \
+ vi
+
+# create fstab and remove all zroot entries
+genfstab -U -p "${MNT}" >> "${MNT}"/etc/fstab
+sed -i '/^# zroot/d' "${MNT}"/etc/fstab
+sed -i '/^zroot/d' "${MNT}"/etc/fstab
+sed -i '/^$/d' "${MNT}"/etc/fstab
+echo "" >> "${MNT}"/etc/fstab # one blank line at the end
+
+# copy over dns settings to the new system
+cp -v /etc/resolv.conf "${MNT}"/etc
+
+# copy stage2 script to the new system
+cp ./stage2.sh "${MNT}"/root
+
+# ----------------------------- Chroot ----------------------------
+
+echo ""; echo "Done with Stage One"
+chroot "${MNT}" /usr/bin/env DISK="${DISK}" /root/stage2.sh
+
+# -------------------------- After Chroot -------------------------
+
+umount -Rl "${MNT}"
+zfs snapshot -r rpool@initial-installation
+zfs snapshot -r bpool@initial-installation
+
+zpool export -a
+
+echo ""; echo "Done with Stage Two"