I've written a bash script that creates a root filesystem on ZFS for installing Debian or Arch. The purpose of this script is to make it easier installing e.g. Arch without the need to make a ZFS pool and create datasets one by one manually.
Below is my bash script. Any advice on what you would improve if you were the author of that script is appreciated. Thanks!
lib/utils
#!/usr/bin/env bash
die() {
echo "Error: $1. Exiting..." 1>&2
exit 1
}
info() {
echo "Info: $1"
}
warn() {
echo "Warning: $1"
}
require_binary() {
local binaries=("$@")
for binary in "${binaries[@]}"; do
if ! command -v "${binary}" &> /dev/null; then
die "${binary} binary does not exist"
fi
done
}
is_mounted() { # Copied from https://www.baeldung.com/linux/bash-is-directory-mounted
mount | awk -v DIR="$1" '{if ($3 == DIR) { exit 0}} ENDFILE{exit -1}'
}
run_as_root() {
if [ "$EUID" -ne 0 ]; then
echo "Please run as root"
exit 1
fi
}
create_lock() {
readonly lockdir=/tmp/$1.lock
if ! mkdir "$lockdir"; then
die "Lock file already exists"
fi
trap 'stty echo; rm -rf "${lockdir}"; exit $?' EXIT
}
read_password() {
local passwd confirm_passwd
until
stty -echo
read -rp "Password: " passwd
echo
read -rp "Confirm password: " confirm_passwd
echo
stty echo
[[ "$passwd" = "$confirm_passwd" ]]
do
echo "Error: passwords don't match." >&2
done
echo "${passwd}"
}
prepare_zfs_rootfs:
#!/usr/bin/env bash
. ./lib/utils
run_as_root
require_binary "zpool" "zfs" "sgdisk"
create_lock "prepare_zfs_rootfs"
ZFS_AVAILABLE_ENC_TYPES=( "password" "keyfile" )
ZFS_AVAILABLE_PRESETS=( "gentoo" "gnome" "libvirt" "lxc" "docker" "nfs" "webserver" "mailserver" "snap" "systemd" )
ZFS_AVAILABLE_BOOT_MODES=( "uefi" "legacy_bios" )
usage() {
cat <<EOF
$0 - Prepare ZFS root pool and create datasets for the new rootfs
Usage:
$0 [ options ]
$0 --help
Available presets:
${ZFS_AVAILABLE_PRESETS[*]}
Options:
--device|--devices value - target device or quoted device list like /dev/sda,
"/dev/sda /dev/sdb" when setting up raid, required
-m|--mnt value - rootfs mount path, required
-u|--user value - target user name, required (default: user)
--boot-pool value - boot pool name (default: bpool)
--root-pool value - root pool name (default: rpool)
--raid-type (none|raid0|raid1) - raid type (default: none)
--presets "quoted list of values" - instructs script how to configure ZFS for user needs, required
--b|-boot-mode (uefi|legacy_bios) - specifies target system boot mode (default: uefi)
--encrypt - encrypts ZFS root pool (default: unset)
--key-type (password|keyfile) - specifies encryption type
--key-path value - specifies keyfile path, required when key type is keyfile
--rpool-size value - specifies root partition size (default: unset)
--swap-size value - specifies swap size (default: unset)
--enable-swap - specifies whether swap should be enabled (default: set)
--swap-on-zfs - specifies whether swap should be put onto ZFS (default: unset)
--encrypt-swap - specifies whether swap should be encrypted with LUKS (default: unset)
--swap-hibernate - specifies wheter will be used hibernation (default: unset)
--auto-mount y|n - specifies if rootfs should be automatically mounted (default: y)
-c|--config value - specifies config file path
--apply - tells script that partitioning and preparing ZFS pools should be applied, use with caution
-h|--help - displays this help
EOF
exit 0
}
[ $# -eq 0 ] && usage
while [ "$#" -gt 0 ]; do
case $1 in
--device|--devices)
ZFS_TARGET_DEVICES="$2"
shift
shift
;;
-m|--mnt)
ZFS_MNT_PATH="$2"
shift
shift
;;
-u|--user)
ZFS_TARGET_USER="$2"
shift
shift
;;
--boot-pool)
ZFS_BOOT_POOL="$2"
shift
shift
;;
--root-pool)
ZFS_ROOT_POOL="$2"
shift
shift
;;
--raid-type)
ZFS_RAID_TYPE="$2"
shift
shift
;;
--presets)
ZFS_PRESETS="$2"
shift
shift
;;
-b|--boot-mode)
ZFS_BOOT_MODE="$2"
shift
shift
;;
--encrypt)
ZFS_ENC_ENABLED="y"
shift
;;
--key-type)
ZFS_KEY_TYPE="$2"
shift
shift
;;
--key-path)
ZFS_KEY_PATH="$2"
shift
shift
;;
--swap-size)
INST_PARTSIZE_SWAP="$2"
shift
shift
;;
--enable-swap)
SWAP_ENABLED="y"
shift
;;
--swap-on-zfs)
SWAP_ON_ZFS="y"
shift
;;
--encrypt-swap)
SWAP_ENCRYPT="y"
shift
;;
--swap-hibernate)
SWAP_HIBERNATE="y"
shift
;;
--auto-mount)
AUTO_MOUNT="$2"
shift
shift
;;
-c|--config)
CONFIG_FILE="$2"
shift
shift
;;
--apply)
APPLY="y"
shift
;;
-h|--help)
usage
;;
*)
echo "Error: command '$1' not recognized."
usage
;;
esac
done
# shellcheck source=/dev/null
if [[ -f "${CONFIG_FILE}" ]]; then
. "${CONFIG_FILE}"
else
die "config file does not exist"
fi
# assign default values to variables
ZFS_TARGET_DEVICES=${ZFS_TARGET_DEVICES:-}
ZFS_MNT_PATH=${ZFS_MNT_PATH:-}
ZFS_TARGET_USER=${ZFS_TARGET_USER:-"user"}
ZFS_BOOT_POOL=${ZFS_BOOT_POOL:-"bpool"}
ZFS_ROOT_POOL=${ZFS_ROOT_POOL:-"rpool"}
ZFS_RAID_TYPE=${ZFS_RAID_TYPE:-"none"}
ZFS_PRESETS=${ZFS_PRESETS:-}
ZFS_BOOT_MODE=${ZFS_BOOT_MODE:-"uefi"}
ZFS_ENC_ENABLED=${ZFS_ENC_ENABLED:-}
ZFS_KEY_TYPE=${ZFS_KEY_TYPE:-}
ZFS_KEY_PATH=${ZFS_KEY_PATH:-}
ZFS_ENC_PASSWD=${ZFS_ENC_PASSWD:-}
INST_PARTSIZE_RPOOL=${INST_PARTSIZE_RPOOL:-}
INST_PARTSIZE_SWAP=${INST_PARTSIZE_SWAP:-}
SWAP_ENABLED=${SWAP_ENABLED:-"y"}
SWAP_ON_ZFS=${SWAP_ON_ZFS:-}
SWAP_ENCRYPT=${SWAP_ENCRYPT:-}
SWAP_HIBERNATE=${SWAP_HIBERNATE:-}
AUTO_MOUNT=${AUTO_MOUNT:-"y"}
APPLY=${APPLY:-}
# check if options specified to the script are correct
if [[ -n "${ZFS_TARGET_DEVICES[*]}" ]]; then
for device in "${ZFS_TARGET_DEVICES[@]}"; do
if [[ ! -b "${device}" ]]; then
die "'${device}' is not a block device"
fi
done
else
die "target devices not specified"
fi
if [[ -n "${ZFS_MNT_PATH}" ]]; then
if [[ ! -d "${ZFS_MNT_PATH}" ]]; then
die "directory '${ZFS_MNT_PATH}' does not exist"
else
if is_mounted "${ZFS_MNT_PATH}"; then
die "directory '${ZFS_MNT_PATH}' is already mounted"
fi
fi
else
die "mount path not specified"
fi
[[ -z "${ZFS_TARGET_USER}" ]] && die "target user name is not specified"
[[ -z "${ZFS_BOOT_POOL}" ]] && die "boot pool name is not specified"
[[ -z "${ZFS_ROOT_POOL}" ]] && die "root pool name is not specified"
if [[ -n "${ZFS_RAID_TYPE}" ]]; then
case ${ZFS_RAID_TYPE} in
none)
[[ ${#ZFS_TARGET_DEVICES[@]} -gt 1 ]] && die "too many devices, specified raid type is '${ZFS_RAID_TYPE}'"
;;
raid0|raid1)
[[ ${#ZFS_TARGET_DEVICES[@]} -lt 2 ]] && die "required at least 2 devices, not a raid"
;;
*)
die "unknown raid type '${ZFS_RAID_TYPE}'"
;;
esac
else
die "raid type list is empty"
fi
if [[ -n "${ZFS_PRESETS[*]}" ]]; then
for preset in "${ZFS_PRESETS[@]}"; do
if [[ ! ${ZFS_AVAILABLE_PRESETS[*]} =~ ${preset} ]]; then
die "unknown preset '${preset}'"
fi
done
else
die "preset list is empty"
fi
if [[ -n "${ZFS_BOOT_MODE[*]}" ]]; then
for boot_mode in "${ZFS_BOOT_MODE[@]}"; do
if [[ ! ${ZFS_AVAILABLE_BOOT_MODES[*]} =~ ${boot_mode} ]]; then
die "unknown boot mode '${boot_mode}'"
fi
done
else
die "boot mode list is empty"
fi
if [[ -n "${ZFS_ENC_ENABLED}" ]]; then
if [[ ! ${ZFS_AVAILABLE_ENC_TYPES[*]} =~ ${ZFS_KEY_TYPE} ]]; then
die "unknown encryption type '${ZFS_KEY_TYPE}'"
fi
if [[ "${ZFS_KEY_TYPE}" = "keyfile" ]] && [[ -z "${ZFS_KEY_PATH}" ]]; then
die "encryption key path not specified"
fi
fi
declare -a SWAP_PARTITION=""
calculate_ashift() {
local device
device=$1
local zpool_ashift
local sector_size
sector_size=$(blockdev --getpbsz "${device}")
case ${sector_size} in
"512")
zpool_ashift=9
;;
"4096")
zpool_ashift=12
;;
"8192")
zpool_ashift=13
;;
*)
die "calculate_ashift: cannot calculate ashift for device '${device}'"
;;
esac
echo "${zpool_ashift}"
}
check_ashift() {
local devices
devices=( "$@" )
local zpool_ashift
local prev
read -r -a devices <<< "$@"
for part in "${devices[@]}"; do
zpool_ashift=$(calculate_ashift "${part}")
if [[ ${prev} && ${zpool_ashift} != $(calculate_ashift "${prev}") ]]; then
die "check_ashift: devices ashifts don't match"
fi
prev=${part}
done
echo "${zpool_ashift}"
}
calculate_swap_size() {
local swap_size
local total_memory
total_memory=$(free -m | awk '/^Mem:/{print $2}')
if [ "${total_memory}" -le 2048 ]; then
[[ -n "${SWAP_HIBERNATE}" ]] && swap_size=$(( 3 * total_memory )) || swap_size=$(( 2 * total_memory ))
elif [ "${total_memory}" -gt 2048 ] && [ "${total_memory}" -le 8192 ]; then
[[ -n "${SWAP_HIBERNATE}" ]] && swap_size=$(( 2 * total_memory )) || swap_size=${total_memory}
elif [ "${total_memory}" -gt 8192 ] && [ "${total_memory}" -le 65536 ]; then
[[ -n "${SWAP_HIBERNATE}" ]] && swap_size=$(perl -w -e "use POSIX; print ceil(1.5 * ${total_memory}), qq{\n}") || swap_size=4096
else
swap_size=4096
fi
echo "${swap_size}M"
}
create_swap_on_zfs() {
echo "Creating swap dataset"
zfs create -V "$(calculate_swap_size)" -b 4096 -o logbias=throughput -o sync=always -o primarycache=metadata\
-o com.sun:auto-snapshot=false "${ZFS_ROOT_POOL}"/swap
mkswap -f /dev/zvol/"${ZFS_ROOT_POOL}"/swap
}
generate_keyfile() {
local target
target=$1
tr -d '\n' < /dev/urandom | head -c 512 > "${target}"
echo "Successfully created encryption key"
}
create_efi_dir() {
if [[ "${ZFS_BOOT_MODE}" = "uefi" ]]; then
mkdir -p "${ZFS_MNT_PATH}"/boot/efi
[[ ${#ZFS_TARGET_DEVICES[@]} -gt 1 ]] || mkdir -p "${ZFS_MNT_PATH}"/boot/efis
for device in "${ZFS_TARGET_DEVICES[@]}"; do
if [[ "${device}" = /dev/disk/by-id* ]]; then
mkdir -p "${ZFS_MNT_PATH}"/boot/efis/"${device##*/}"-part1
else
mkdir -p "${ZFS_MNT_PATH}"/boot/efis/"${device##*/}"1
fi
done
fi
}
mount_efi_dir() {
if [[ "${ZFS_BOOT_MODE}" = "uefi" ]]; then
if [[ "${ZFS_TARGET_DEVICES[0]}" = /dev/disk/by-id* ]]; then
mount -t vfat "${ZFS_TARGET_DEVICES[0]}-part1" "${ZFS_MNT_PATH}"/boot/efi
else
mount -t vfat "${ZFS_TARGET_DEVICES[0]}1" "${ZFS_MNT_PATH}"/boot/efi
fi
for device in "${ZFS_TARGET_DEVICES[@]}"; do
if [[ "${device}" = /dev/disk/by-id* ]]; then
mount -t vfat "${device}-part1" "${ZFS_MNT_PATH}"/boot/efis/"${device##*/}"-part1
else
mount -t vfat "${device}1" "${ZFS_MNT_PATH}"/boot/efis/"${device##*/}"1
fi
done
fi
}
create_bpool() {
echo "Creating bpool"
local devices
devices=( "$@" )
local bpool_args
bpool_args=(
"-d"
"-f"
"-o feature@allocation_classes=enabled"
"-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@project_quota=enabled"
"-o feature@resilver_defer=enabled"
"-o feature@spacemap_histogram=enabled"
"-o feature@spacemap_v2=enabled"
"-o feature@userobj_accounting=enabled"
"-o feature@zpool_checkpoint=enabled"
"-o ashift=$(check_ashift "${devices[*]}")"
"-o cachefile=/etc/zfs/zpool.cache"
"-o autotrim=on"
"-O acltype=posixacl"
"-O canmount=off"
"-O compression=off"
"-O devices=off"
"-O normalization=formD"
"-O relatime=on"
"-O xattr=sa"
"-O mountpoint=/boot"
"-R ${ZFS_MNT_PATH}"
)
# shellcheck disable=SC2048
# shellcheck disable=SC2086
case ${ZFS_RAID_TYPE} in
none)
zpool create ${bpool_args[*]} "${ZFS_BOOT_POOL}" ${devices[*]}
;;
raid0)
zpool create ${bpool_args[*]} "${ZFS_BOOT_POOL}" ${devices[*]}
;;
raid1)
zpool create ${bpool_args[*]} "${ZFS_BOOT_POOL}" mirror ${devices[*]}
;;
esac
zfs create -o canmount=off -o mountpoint=none "${ZFS_BOOT_POOL}"/BOOT
zfs create -o mountpoint=/boot "${ZFS_BOOT_POOL}"/BOOT/default
create_efi_dir
zpool export "${ZFS_BOOT_POOL}"
rmdir "${ZFS_MNT_PATH}"/boot || true
}
create_rpool() {
echo "Creating rpool"
local devices
devices=( "$@" )
local rpool_args
rpool_args=(
"-f"
"-o ashift=$(check_ashift "${devices[@]}")"
"-o cachefile=/etc/zfs/zpool.cache"
"-O acltype=posixacl"
"-O relatime=on"
"-O xattr=sa"
"-O dnodesize=legacy"
"-O normalization=formD"
"-O mountpoint=none"
"-O canmount=off"
"-O devices=off"
"-O compression=lz4"
"-m none"
"-R ${ZFS_MNT_PATH}"
)
if [[ -n "${ZFS_ENC_ENABLED}" ]]; then
rpool_args+=( "-O encryption=aes-256-gcm" "-O keyformat=passphrase" )
case ${ZFS_KEY_TYPE} in
"password")
rpool_args+=( "-O keylocation=prompt" )
;;
"keyfile")
mkdir -p "$(dirname "${ZFS_KEY_PATH}")"
generate_keyfile "${ZFS_KEY_PATH}"
rpool_args+=( "-O keylocation=file://${ZFS_KEY_PATH}" )
;;
esac
fi
[[ -n "${SWAP_HIBERNATE}" ]] && warn "hibernation on ZFS is not recommended"
# shellcheck disable=SC2048
# shellcheck disable=SC2086
case ${ZFS_RAID_TYPE} in
none)
zpool create ${rpool_args[*]} "${ZFS_ROOT_POOL}" ${devices[*]} <<< "${ZFS_ENC_PASSWD}"
;;
raid0)
zpool create ${rpool_args[*]} "${ZFS_ROOT_POOL}" ${devices[*]} <<< "${ZFS_ENC_PASSWD}"
;;
raid1)
zpool create ${rpool_args[*]} "${ZFS_ROOT_POOL}" mirror ${devices[*]} <<< "${ZFS_ENC_PASSWD}"
;;
esac
zfs create -o mountpoint=none -o compression=lz4 "${ZFS_ROOT_POOL}"/ROOT
zfs create -o mountpoint=/ "${ZFS_ROOT_POOL}"/ROOT/default
zfs create -o canmount=off -o mountpoint=/var -o xattr=sa "${ZFS_ROOT_POOL}"/ROOT/var
zfs create -o canmount=off -o mountpoint=/var/lib "${ZFS_ROOT_POOL}"/ROOT/var/lib
if [[ ${ZFS_PRESETS[*]} =~ "gentoo" ]]; then
# Create portage directories
zfs create -o mountpoint=/var/cache/distfiles "${ZFS_ROOT_POOL}"/ROOT/distfiles
# Create portage build directory
zfs create -o mountpoint=/var/tmp/portage -o compression=lz4 -o sync=disabled "${ZFS_ROOT_POOL}"/ROOT/build_dir
# Create optional packages directory
zfs create -o mountpoint=/var/cache/binpkgs "${ZFS_ROOT_POOL}"/ROOT/binpkgs
# Create optional ccache directory
zfs create -o mountpoint=/var/tmp/ccache -o compression=lz4 "${ZFS_ROOT_POOL}"/ROOT/ccache
fi
[[ "${ZFS_PRESETS[*]}" =~ "gnome" ]] && zfs create -o canmount=on -o mountpoint=/var/lib/AccountsService "${ZFS_ROOT_POOL}"/ROOT/var/lib/AccountsService
[[ "${ZFS_PRESETS[*]}" =~ "libvirt" ]] && zfs create -o canmount=on -o mountpoint=/var/lib/libvirt "${ZFS_ROOT_POOL}"/ROOT/var/lib/libvirt
[[ "${ZFS_PRESETS[*]}" =~ "lxc" ]] && zfs create -o canmount=on -o mountpoint=/var/lib/lxc "${ZFS_ROOT_POOL}"/ROOT/var/lib/lxc
[[ "${ZFS_PRESETS[*]}" =~ "docker" ]] && zfs create -o canmount=on -o mountpoint=/var/lib/docker "${ZFS_ROOT_POOL}"/ROOT/var/lib/docker
[[ "${ZFS_PRESETS[*]}" =~ "nfs" ]] && zfs create -o canmount=on -o mountpoint=/var/lib/nfs "${ZFS_ROOT_POOL}"/ROOT/var/lib/nfs
[[ "${ZFS_PRESETS[*]}" =~ "webserver" ]] && zfs create -o canmount=on -o mountpoint=/var/www "${ZFS_ROOT_POOL}"/ROOT/var/www
[[ "${ZFS_PRESETS[*]}" =~ "mailserver" ]] && zfs create -o canmount=on -o mountpoint=/var/mail "${ZFS_ROOT_POOL}"/ROOT/var/mail
[[ "${ZFS_PRESETS[*]}" =~ "snap" ]] && zfs create -o canmount=on -o mountpoint=/var/snap "${ZFS_ROOT_POOL}"/ROOT/var/snap
[[ "${ZFS_PRESETS[*]}" =~ "systemd" ]] && zfs create -o canmount=off -o mountpoint=/var/lib/systemd "${ZFS_ROOT_POOL}"/ROOT/var/lib/systemd
zfs create -o canmount=off -o mountpoint=/usr "${ZFS_ROOT_POOL}"/ROOT/usr
zfs create -o mountpoint=/usr/local "${ZFS_ROOT_POOL}"/ROOT/usr/local
zfs create -o mountpoint=/opt "${ZFS_ROOT_POOL}"/ROOT/opt
[[ "${ZFS_PRESETS[*]}" =~ "systemd" ]] && zfs create -o mountpoint=/var/lib/systemd/coredump "${ZFS_ROOT_POOL}"/ROOT/var/lib/systemd/coredump
zfs create -o mountpoint=/var/log "${ZFS_ROOT_POOL}"/ROOT/var/log
[[ "${ZFS_PRESETS[*]}" =~ "systemd" ]] && zfs create -o acltype=posixacl -o mountpoint=/var/log/journal "${ZFS_ROOT_POOL}"/ROOT/var/log/journal
zfs create -o mountpoint=/home "${ZFS_ROOT_POOL}"/home
zfs create -o mountpoint=/root "${ZFS_ROOT_POOL}"/home/root
zfs create -o mountpoint=/home/"${ZFS_TARGET_USER}" "${ZFS_ROOT_POOL}"/home/"${ZFS_TARGET_USER}"
zpool set bootfs="${ZFS_ROOT_POOL}" "${ZFS_ROOT_POOL}"
zfs set relatime=on "${ZFS_ROOT_POOL}"
zfs set compression=lz4 "${ZFS_ROOT_POOL}"
[[ -n "${SWAP_ON_ZFS}" ]] && create_swap_on_zfs
zpool export "${ZFS_ROOT_POOL}"
}
create_partitions() {
echo "Creating partitions"
for device in "${ZFS_TARGET_DEVICES[@]}"; do
sgdisk --zap-all "${device}"
case ${ZFS_BOOT_MODE} in
"legacy_bios")
sgdisk -n 0:0:+1MiB -t 0:ef02 "${device}"
;;
"uefi")
sgdisk -n 0:1M:+1G -t 0:ef00 "${device}"
sleep 3
if [[ "${device}" = /dev/disk/by-id* ]]; then
mkfs.vfat -n EFI "${device}"-part1
else
mkfs.vfat -n EFI "${device}"1
fi
;;
esac
sgdisk -n 0:0:+4GiB -t 0:be00 "${device}"
if [[ -n "${SWAP_ENABLED}" ]]; then
if [[ -z "${INST_PARTSIZE_SWAP}" ]]; then
sgdisk -n 0:0:+"$(calculate_swap_size)"G -t 0:8200 "${device}"
else
sgdisk -n 0:0:+"${INST_PARTSIZE_SWAP}"G -t 0:8200 "${device}"
fi
fi
if test -z "${INST_PARTSIZE_RPOOL}"; then
sgdisk -n 0:0:0 -t 0:bf00 "${device}"
else
sgdisk -n 0:0:+"${INST_PARTSIZE_RPOOL}"G -t 0:bf00 "${device}"
fi
done
sleep 3
# shellcheck disable=SC2048
# shellcheck disable=SC2086
if [[ -n "${SWAP_ENABLED}" ]] && [[ -z "${SWAP_ON_ZFS}" ]]; then
for device in "${ZFS_TARGET_DEVICES[@]}"; do
if [[ "${device}" = /dev/disk/by-id* ]]; then
SWAP_PARTITION+=( "${device}-part3" )
else
SWAP_PARTITION+=( "${device}3" )
fi
done
case ${ZFS_RAID_TYPE} in
"none")
[[ -z "${SWAP_ENCRYPT}" ]] && mkswap ${SWAP_PARTITION[*]}
;;
"raid1")
mdadm --create --verbose --level=1 --metadata=1.2 --raid-devices=2 /dev/md/swap ${SWAP_PARTITION[*]}
[[ -z "${SWAP_ENCRYPT}" ]] && mkswap /dev/md/swap
;;
**)
die "create_partitions: unsupported raid type '${ZFS_RAID_TYPE}'"
;;
esac
info "If SWAP_ENCRYPT option is enabled without SWAP_ON_ZFS, you have to"
info "manually enable swap encryption in /etc/crypttab on the target system."
info "For raid configurations you must append /dev/md/swap in /etc/crypttab,"
info "and /dev/mapper/swap_device_name to /etc/fstab."
fi
sleep 3
}
create_rootfs() {
echo "Setting up ZFS pools"
local partitions=( )
for device in "${ZFS_TARGET_DEVICES[@]}"; do
if [[ "${device}" = /dev/disk/by-id* ]]; then
partitions+=( "${device}-part2" )
else
partitions+=( "${device}2" )
fi
done
create_bpool "${partitions[@]}"
partitions=( )
for device in "${ZFS_TARGET_DEVICES[@]}"; do
if [[ "${device}" = /dev/disk/by-id* ]]; then
partitions+=( "${device}-part4" )
else
partitions+=( "${device}4" )
fi
done
create_rpool "${partitions[@]}"
}
mount_rootfs() {
echo "Mounting filesystem"
zpool import -o cachefile=/etc/zfs/zpool.cache -R "${ZFS_MNT_PATH}" "${ZFS_ROOT_POOL}"
if [[ -n "${ZFS_ENC_ENABLED}" ]]; then
zfs load-key "${ZFS_ROOT_POOL}" <<< "${ZFS_ENC_PASSWD}"
zfs mount -a
fi
if [[ -n "${SWAP_PARTITION[*]}" ]] && [[ -z "${SWAP_ENCRYPT}" ]]; then
case ${ZFS_RAID_TYPE} in
"none")
swapon "${SWAP_PARTITION[*]}"
;;
"raid1")
swapon /dev/md/swap
;;
**)
die "mount_rootfs: unsupported raid type '${ZFS_RAID_TYPE}'"
;;
esac
fi
zpool import -o cachefile=/etc/zfs/zpool.cache -R "${ZFS_MNT_PATH}" "${ZFS_BOOT_POOL}"
mkdir -p "${ZFS_MNT_PATH}"/etc/zfs
cp /etc/zfs/zpool.cache "${ZFS_MNT_PATH}"/etc/zfs/zpool.cache
mount_efi_dir
echo "Successfully mounted rootfs"
}
dump_config() {
echo "ZFS_TARGET_DEVICES=\"${ZFS_TARGET_DEVICES[*]}\""
echo "ZFS_MNT_PATH=\"${ZFS_MNT_PATH}\""
echo "ZFS_TARGET_USER=\"${ZFS_TARGET_USER}\""
echo "ZFS_BOOT_POOL=\"${ZFS_BOOT_POOL}\""
echo "ZFS_ROOT_POOL=\"${ZFS_ROOT_POOL}\""
echo "ZFS_RAID_TYPE=\"${ZFS_RAID_TYPE}\""
echo "ZFS_PRESETS=\"${ZFS_PRESETS[*]}\""
echo "ZFS_ENC_ENABLED=\"${ZFS_ENC_ENABLED}\""
echo "ZFS_KEY_TYPE=\"${ZFS_KEY_TYPE}\""
echo "ZFS_KEY_PATH=\"${ZFS_KEY_PATH}\""
echo "SWAP_ENABLED=\"${SWAP_ENABLED}\""
echo "SWAP_ENCRYPT=\"${SWAP_ENCRYPT}\""
echo "SWAP_ON_ZFS=\"${SWAP_ON_ZFS}\""
echo "SWAP_HIBERNATE=\"${SWAP_HIBERNATE}\""
}
if [[ -n "${APPLY}" ]]; then
if [[ -n "${ZFS_ENC_ENABLED}" ]] && [[ "${ZFS_KEY_TYPE}" = "password" ]] && [[ -z "${ZFS_ENC_PASSWD}" ]]; then
read_password ZFS_ENC_PASSWD
fi
create_partitions
create_rootfs
[[ "${AUTO_MOUNT}" = "y" ]] && mount_rootfs
else
echo "Execute script with --apply option to confirm destructive action"
echo "Actual config:"
dump_config
fi