mirror of
https://github.com/terem42/zfs-hetzner-vm.git
synced 2025-12-22 23:08:36 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd395798a4 | ||
|
|
eeb4f33154 | ||
|
|
d911bab768 | ||
|
|
01cc08383d | ||
|
|
5e254ccdd1 | ||
|
|
54d97134e2 | ||
|
|
deeb74d45d | ||
|
|
473643ca74 | ||
|
|
4e7540f014 | ||
|
|
2ee5ba5a9e | ||
|
|
2da5a92743 | ||
|
|
2bc53ff84f | ||
|
|
77b6069a44 | ||
|
|
1d5c0a3faa | ||
|
|
42434f1578 | ||
|
|
edc32f0585 | ||
|
|
8a4ecef1c8 | ||
|
|
21e3c872cb | ||
|
|
879feb651f | ||
|
|
0f53cabb6d | ||
|
|
fa584aeea8 | ||
|
|
28ff4a2f55 |
11
.github/workflows/shellcheck.yml
vendored
11
.github/workflows/shellcheck.yml
vendored
@@ -1,11 +0,0 @@
|
||||
name: shellcheck
|
||||
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run shellcheck
|
||||
run: ci/run_shellcheck.sh
|
||||
39
README.md
39
README.md
@@ -1,8 +1,6 @@
|
||||
# zfs-hetzner-vm
|
||||
|
||||
[](https://github.com/terem42/zfs-hetzner-vm/actions/workflows/shellcheck.yml)
|
||||
|
||||
Scripts to install Debian 10, 11, 12 or Ubuntu 18 LTS, 20 LTS, 22 LTS with ZFS root on Hetzner root servers (virtual and dedicated).<br/>
|
||||
Scripts to install Debian 10 or Ubuntu 18 with ZFS root on Hetzner root servers (virtual and dedicated).<br/>
|
||||
__WARNING:__ all data on the disk will be destroyed.
|
||||
|
||||
## How to use:
|
||||
@@ -14,52 +12,25 @@ __WARNING:__ all data on the disk will be destroyed.
|
||||
|
||||
Debian 10 minimal setup with SSH server
|
||||
|
||||
````bash
|
||||
wget -qO- https://raw.githubusercontent.com/terem42/zfs-hetzner-vm/master/hetzner-debian10-zfs-setup.sh | bash -
|
||||
````
|
||||
|
||||
Debian 11 minimal setup with SSH server
|
||||
|
||||
````bash
|
||||
wget -qO- https://raw.githubusercontent.com/terem42/zfs-hetzner-vm/master/hetzner-debian11-zfs-setup.sh | bash -
|
||||
````
|
||||
|
||||
Debian 12 minimal setup with SSH server
|
||||
|
||||
````bash
|
||||
wget -qO- https://raw.githubusercontent.com/terem42/zfs-hetzner-vm/master/hetzner-debian12-zfs-setup.sh | bash -
|
||||
wget -qO- https://raw.githubusercontent.com/andrey42/zfs-hetzner-vm/master/hetzner-debian10-zfs-setup.sh | bash -
|
||||
````
|
||||
|
||||
Ubuntu 18.04 LTS minimal setup with SSH server
|
||||
|
||||
````bash
|
||||
wget -qO- https://raw.githubusercontent.com/terem42/zfs-hetzner-vm/master/hetzner-ubuntu18-zfs-setup.sh | bash -
|
||||
````
|
||||
|
||||
Ubuntu 20 LTS minimal setup with SSH server
|
||||
|
||||
````bash
|
||||
wget -qO- https://raw.githubusercontent.com/terem42/zfs-hetzner-vm/master/hetzner-ubuntu20-zfs-setup.sh | bash -
|
||||
````
|
||||
|
||||
Ubuntu 22 LTS minimal setup with SSH server
|
||||
|
||||
````bash
|
||||
wget -qO- https://raw.githubusercontent.com/terem42/zfs-hetzner-vm/master/hetzner-ubuntu22-zfs-setup.sh | bash -
|
||||
wget -qO- https://raw.githubusercontent.com/andrey42/zfs-hetzner-vm/master/hetzner-ubuntu18-zfs-setup.sh | bash -
|
||||
````
|
||||
|
||||
Answer script questions about desired hostname and ZFS ARC cache size.
|
||||
|
||||
To cope with network failures its higly recommended to run the commands above inside screen console, type `man screen` for more info.
|
||||
Example of screen utility usage:
|
||||
|
||||
````bash
|
||||
export LC_ALL=en_US.UTF-8 && screen -S zfs
|
||||
````
|
||||
screen -S zfs
|
||||
````
|
||||
To detach from screen console, hit Ctrl-d then a
|
||||
To reattach, type `screen -r zfs`
|
||||
|
||||
Upon succesfull run, the script will reboot system, and you will be able to login into it, using the same SSH key you have used within rescue console
|
||||
|
||||
Please note that the drives you intend to format can not be in use,
|
||||
you can execute `mdadm --stop --scan` before running the script to halt default software raid operations.
|
||||
|
||||
1
authorized_keys
Normal file
1
authorized_keys
Normal file
@@ -0,0 +1 @@
|
||||
ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAqK6rUM7EfLlMPPHGyLsOFswtvWKXxzo6DRLZdY9bSMUfB4TlgjaOE/VxQphzpfd47xELMixja03DmQKLcJAgUeuL2UXJQY7FlPqNzbJaXikju60YWy0GzPAMmG/DXsA9qneJ1iv2jmCovG+3EtbsDc2xKLEawvM9G0viWF84Z0/6swLqRDUARQlJkrxKPTDDyc0ixEUNpjwrTRupogqlHeQ1xOriEewCEfXIKv+CVlU86o9t1+R+lN54cJ/U+EyP3YF20JNHIjQMsQm0j2R8wNgr7xXK+9NEDHdMApsfkDBpHfpJt1Nrf4qmct/RMukwPr/Oqdwe7JJ09UjyZTb1KQ==
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -o pipefail
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
set -o errtrace
|
||||
shopt -s inherit_errexit
|
||||
|
||||
# Always download the latest version:
|
||||
#
|
||||
# - it's fast and stable enough not to worry about it;
|
||||
# - the workflow is basically single-person, so there's no risk of a new dev encountering an error found
|
||||
# by a new shellcheck version.
|
||||
|
||||
mkdir -p /opt/shellcheck
|
||||
|
||||
wget -qO- https://github.com/koalaman/shellcheck/releases/download/stable/shellcheck-stable.linux.x86_64.tar.xz \
|
||||
| tar xJv -O shellcheck-stable/shellcheck \
|
||||
> /opt/shellcheck/shellcheck
|
||||
|
||||
chmod +x /opt/shellcheck/shellcheck
|
||||
|
||||
/opt/shellcheck/shellcheck --version
|
||||
|
||||
grep -lZP '^#!/bin/\w+sh' -R | xargs -0 /opt/shellcheck/shellcheck
|
||||
@@ -17,8 +17,6 @@ set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
export TMPDIR=/tmp
|
||||
|
||||
# Variables
|
||||
v_bpool_name=
|
||||
v_bpool_tweaks=
|
||||
@@ -42,7 +40,7 @@ c_deb_security_repo=http://mirror.hetzner.de/debian/security
|
||||
|
||||
c_default_zfs_arc_max_mb=250
|
||||
c_default_bpool_tweaks="-o ashift=12 -O compression=lz4"
|
||||
c_default_rpool_tweaks="-o ashift=12 -O acltype=posixacl -O compression=zstd-9 -O dnodesize=auto -O relatime=on -O xattr=sa -O normalization=formD"
|
||||
c_default_rpool_tweaks="-o ashift=12 -O acltype=posixacl -O compression=lz4 -O dnodesize=auto -O relatime=on -O xattr=sa -O normalization=formD"
|
||||
c_default_hostname=terem
|
||||
c_zfs_mount_dir=/mnt
|
||||
c_log_dir=$(dirname "$(mktemp)")/zfs-hetzner-vm
|
||||
@@ -64,9 +62,7 @@ function print_step_info_header {
|
||||
###############################################################################
|
||||
# ${FUNCNAME[1]}"
|
||||
|
||||
if [[ "${1:-}" != "" ]]; then
|
||||
echo -n " $1"
|
||||
fi
|
||||
[[ "${1:-}" != "" ]] && echo -n " $1" || true
|
||||
|
||||
echo "
|
||||
###############################################################################
|
||||
@@ -110,7 +106,7 @@ This script will prepare the ZFS pools, then install and configure minimal Debia
|
||||
The script with minimal changes may be used on any other hosting provider supporting KVM virtualization and offering Debian-based rescue system.
|
||||
In order to stop the procedure, hit Esc twice during dialogs (excluding yes/no ones), or Ctrl+C while any operation is running.
|
||||
'
|
||||
dialog --msgbox "$dialog_message" 30 100
|
||||
dialog --ascii-lines --msgbox "$dialog_message" 30 100
|
||||
}
|
||||
|
||||
function store_os_distro_information {
|
||||
@@ -138,20 +134,20 @@ function check_prerequisites {
|
||||
|
||||
function initial_load_debian_zed_cache {
|
||||
chroot_execute "mkdir /etc/zfs/zfs-list.cache"
|
||||
chroot_execute "touch /etc/zfs/zfs-list.cache/$v_rpool_name"
|
||||
chroot_execute "ln -sf /usr/lib/zfs-linux/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d/"
|
||||
chroot_execute "touch /etc/zfs/zfs-list.cache/rpool"
|
||||
chroot_execute "ln -s /usr/lib/zfs-linux/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d/"
|
||||
|
||||
chroot_execute "zed -F &"
|
||||
|
||||
local success=0
|
||||
|
||||
if [[ ! -e "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name" ]] || [[ -e "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name" && (( $(find "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name" -type f -printf '%s' 2> /dev/null) == 0 )) ]]; then
|
||||
chroot_execute "zfs set canmount=noauto $v_rpool_name"
|
||||
if [[ ! -e /mnt/etc/zfs/zfs-list.cache/rpool ]] || [[ -e /mnt/etc/zfs/zfs-list.cache/rpool && (( $(ls -l /mnt/etc/zfs/zfs-list.cache/rpool 2> /dev/null | cut -d ' ' -f 5) == 0 )) ]]; then
|
||||
chroot_execute "zfs set canmount=noauto rpool"
|
||||
|
||||
SECONDS=0
|
||||
|
||||
while (( SECONDS++ <= 120 )); do
|
||||
if [[ -e "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name" ]] && (( $(find "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name" -type f -printf '%s' 2> /dev/null) > 0 )); then
|
||||
if [[ -e /mnt/etc/zfs/zfs-list.cache/rpool ]] && (( "$(ls -l /mnt/etc/zfs/zfs-list.cache/rpool | cut -d ' ' -f 5)" > 0 )); then
|
||||
success=1
|
||||
break
|
||||
else
|
||||
@@ -169,7 +165,7 @@ function initial_load_debian_zed_cache {
|
||||
|
||||
chroot_execute "pkill zed"
|
||||
|
||||
sed -Ei "s|/$c_zfs_mount_dir/?|/|g" "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name"
|
||||
sed -Ei 's|/mnt/?|/|g' /mnt/etc/zfs/zfs-list.cache/rpool
|
||||
}
|
||||
|
||||
function find_suitable_disks {
|
||||
@@ -214,7 +210,7 @@ LOG
|
||||
|
||||
If you think this is a bug, please open an issue on https://github.com/terem42/zfs-hetzner-vm/issues, and attach the file `'"$c_disks_log"'`.
|
||||
'
|
||||
dialog --msgbox "$dialog_message" 30 100
|
||||
dialog --ascii-lines --msgbox "$dialog_message" 30 100
|
||||
|
||||
exit 1
|
||||
fi
|
||||
@@ -243,7 +239,7 @@ function select_disks {
|
||||
|
||||
Devices with mounted partitions, cdroms, and removable devices are not displayed!
|
||||
"
|
||||
mapfile -t v_selected_disks < <(dialog --separate-output --checklist "$dialog_message" 30 100 $((${#menu_entries_option[@]} / 3)) "${menu_entries_option[@]}" 3>&1 1>&2 2>&3)
|
||||
mapfile -t v_selected_disks < <(dialog --ascii-lines --separate-output --checklist "$dialog_message" 30 100 $((${#menu_entries_option[@]} / 3)) "${menu_entries_option[@]}" 3>&1 1>&2 2>&3)
|
||||
|
||||
if [[ ${#v_selected_disks[@]} -gt 0 ]]; then
|
||||
break
|
||||
@@ -260,7 +256,7 @@ function ask_swap_size {
|
||||
local swap_size_invalid_message=
|
||||
|
||||
while [[ ! $v_swap_size =~ ^[0-9]+$ ]]; do
|
||||
v_swap_size=$(dialog --inputbox "${swap_size_invalid_message}Enter the swap size in GiB (0 for no swap):" 30 100 2 3>&1 1>&2 2>&3)
|
||||
v_swap_size=$(dialog --ascii-lines --inputbox "${swap_size_invalid_message}Enter the swap size in GiB (0 for no swap):" 30 100 2 3>&1 1>&2 2>&3)
|
||||
|
||||
swap_size_invalid_message="Invalid swap size! "
|
||||
done
|
||||
@@ -275,7 +271,7 @@ function ask_free_tail_space {
|
||||
local tail_space_invalid_message=
|
||||
|
||||
while [[ ! $v_free_tail_space =~ ^[0-9]+$ ]]; do
|
||||
v_free_tail_space=$(dialog --inputbox "${tail_space_invalid_message}Enter the space to leave at the end of each disk (0 for none):" 30 100 0 3>&1 1>&2 2>&3)
|
||||
v_free_tail_space=$(dialog --ascii-lines --inputbox "${tail_space_invalid_message}Enter the space to leave at the end of each disk (0 for none):" 30 100 0 3>&1 1>&2 2>&3)
|
||||
|
||||
tail_space_invalid_message="Invalid size! "
|
||||
done
|
||||
@@ -290,7 +286,7 @@ function ask_zfs_arc_max_size {
|
||||
local zfs_arc_max_invalid_message=
|
||||
|
||||
while [[ ! $v_zfs_arc_max_mb =~ ^[0-9]+$ ]]; do
|
||||
v_zfs_arc_max_mb=$(dialog --inputbox "${zfs_arc_max_invalid_message}Enter ZFS ARC cache max size in Mb (minimum 64Mb, enter 0 for ZFS default value, the default will take up to 50% of memory):" 30 100 "$c_default_zfs_arc_max_mb" 3>&1 1>&2 2>&3)
|
||||
v_zfs_arc_max_mb=$(dialog --ascii-lines --inputbox "${zfs_arc_max_invalid_message}Enter ZFS ARC cache max size in Mb (minimum 64Mb, enter 0 for ZFS default value, the default will take up to 50% of memory):" 30 100 "$c_default_zfs_arc_max_mb" 3>&1 1>&2 2>&3)
|
||||
|
||||
zfs_arc_max_invalid_message="Invalid size! "
|
||||
done
|
||||
@@ -306,14 +302,14 @@ function ask_pool_names {
|
||||
local bpool_name_invalid_message=
|
||||
|
||||
while [[ ! $v_bpool_name =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_bpool_name=$(dialog --inputbox "${bpool_name_invalid_message}Insert the name for the boot pool" 30 100 bpool 3>&1 1>&2 2>&3)
|
||||
v_bpool_name=$(dialog --ascii-lines --inputbox "${bpool_name_invalid_message}Insert the name for the boot pool" 30 100 bpool 3>&1 1>&2 2>&3)
|
||||
|
||||
bpool_name_invalid_message="Invalid pool name! "
|
||||
done
|
||||
local rpool_name_invalid_message=
|
||||
|
||||
while [[ ! $v_rpool_name =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_rpool_name=$(dialog --inputbox "${rpool_name_invalid_message}Insert the name for the root pool" 30 100 rpool 3>&1 1>&2 2>&3)
|
||||
v_rpool_name=$(dialog --ascii-lines --inputbox "${rpool_name_invalid_message}Insert the name for the root pool" 30 100 rpool 3>&1 1>&2 2>&3)
|
||||
|
||||
rpool_name_invalid_message="Invalid pool name! "
|
||||
done
|
||||
@@ -325,8 +321,8 @@ function ask_pool_tweaks {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
v_bpool_tweaks=$(dialog --inputbox "Insert the tweaks for the boot pool" 30 100 -- "$c_default_bpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
v_rpool_tweaks=$(dialog --inputbox "Insert the tweaks for the root pool" 30 100 -- "$c_default_rpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
v_bpool_tweaks=$(dialog --ascii-lines --inputbox "Insert the tweaks for the boot pool" 30 100 -- "$c_default_bpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
v_rpool_tweaks=$(dialog --ascii-lines --inputbox "Insert the tweaks for the root pool" 30 100 -- "$c_default_rpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
|
||||
print_variables v_bpool_tweaks v_rpool_tweaks
|
||||
}
|
||||
@@ -341,8 +337,8 @@ function ask_root_password {
|
||||
local password_repeat=-
|
||||
|
||||
while [[ "$v_root_password" != "$password_repeat" || "$v_root_password" == "" ]]; do
|
||||
v_root_password=$(dialog --passwordbox "${password_invalid_message}Please enter the root account password (can't be empty):" 30 100 3>&1 1>&2 2>&3)
|
||||
password_repeat=$(dialog --passwordbox "Please repeat the password:" 30 100 3>&1 1>&2 2>&3)
|
||||
v_root_password=$(dialog --ascii-lines --passwordbox "${password_invalid_message}Please enter the root account password (can't be empty):" 30 100 3>&1 1>&2 2>&3)
|
||||
password_repeat=$(dialog --ascii-lines --passwordbox "Please repeat the password:" 30 100 3>&1 1>&2 2>&3)
|
||||
|
||||
password_invalid_message="Passphrase empty, or not matching! "
|
||||
done
|
||||
@@ -352,7 +348,7 @@ function ask_root_password {
|
||||
function ask_encryption {
|
||||
print_step_info_header
|
||||
|
||||
if dialog --defaultno --yesno 'Do you want to encrypt the root pool?' 30 100; then
|
||||
if dialog --ascii-lines --yesno 'Do you want to encrypt the root pool?' 30 100; then
|
||||
v_encrypt_rpool=1
|
||||
fi
|
||||
set +x
|
||||
@@ -360,8 +356,8 @@ function ask_encryption {
|
||||
local passphrase_invalid_message=
|
||||
local passphrase_repeat=-
|
||||
while [[ "$v_passphrase" != "$passphrase_repeat" || ${#v_passphrase} -lt 8 ]]; do
|
||||
v_passphrase=$(dialog --passwordbox "${passphrase_invalid_message}Please enter the passphrase for the root pool (8 chars min.):" 30 100 3>&1 1>&2 2>&3)
|
||||
passphrase_repeat=$(dialog --passwordbox "Please repeat the passphrase:" 30 100 3>&1 1>&2 2>&3)
|
||||
v_passphrase=$(dialog --ascii-lines --passwordbox "${passphrase_invalid_message}Please enter the passphrase for the root pool (8 chars min.):" 30 100 3>&1 1>&2 2>&3)
|
||||
passphrase_repeat=$(dialog --ascii-lines --passwordbox "Please repeat the passphrase:" 30 100 3>&1 1>&2 2>&3)
|
||||
|
||||
passphrase_invalid_message="Passphrase too short, or not matching! "
|
||||
done
|
||||
@@ -372,7 +368,7 @@ function ask_encryption {
|
||||
function ask_zfs_experimental {
|
||||
print_step_info_header
|
||||
|
||||
if dialog --defaultno --yesno 'Do you want to use experimental zfs module build?' 30 100; then
|
||||
if dialog --ascii-lines --yesno 'Do you want to use experimental zfs module build?' 30 100; then
|
||||
v_zfs_experimental=1
|
||||
fi
|
||||
}
|
||||
@@ -383,8 +379,8 @@ function ask_hostname {
|
||||
|
||||
local hostname_invalid_message=
|
||||
|
||||
while [[ ! $v_hostname =~ ^[a-z][a-zA-Z0-9_:.-]+$ ]]; do
|
||||
v_hostname=$(dialog --inputbox "${hostname_invalid_message}Set the host name" 30 100 "$c_default_hostname" 3>&1 1>&2 2>&3)
|
||||
while [[ ! $v_hostname =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_hostname=$(dialog --ascii-lines --inputbox "${hostname_invalid_message}Set the host name" 30 100 "$c_default_hostname" 3>&1 1>&2 2>&3)
|
||||
|
||||
hostname_invalid_message="Invalid host name! "
|
||||
done
|
||||
@@ -399,7 +395,7 @@ function determine_kernel_variant {
|
||||
}
|
||||
|
||||
function chroot_execute {
|
||||
chroot $c_zfs_mount_dir bash -c "DEBIAN_FRONTEND=noninteractive $1"
|
||||
chroot $c_zfs_mount_dir bash -c "$1"
|
||||
}
|
||||
|
||||
function unmount_and_export_fs {
|
||||
@@ -435,8 +431,9 @@ function unmount_and_export_fs {
|
||||
zpools_exported=99
|
||||
echo "===========exporting zfs pools============="
|
||||
set +e
|
||||
while (( zpools_exported == 99 )) && (( SECONDS++ <= 60 )); do
|
||||
if zpool export -a 2> /dev/null; then
|
||||
while (( zpools_exported == 99 )) && (( SECONDS++ <= 60 )); do
|
||||
zpool export -a 2> /dev/null
|
||||
if [[ $? == 0 ]]; then
|
||||
zpools_exported=1
|
||||
echo "all zfs pools were succesfully exported"
|
||||
break;
|
||||
@@ -453,7 +450,6 @@ function unmount_and_export_fs {
|
||||
|
||||
#################### MAIN ################################
|
||||
export LC_ALL=en_US.UTF-8
|
||||
export NCURSES_NO_UTF8_ACS=1
|
||||
|
||||
check_prerequisites
|
||||
|
||||
@@ -494,20 +490,11 @@ for kver in $(find /lib/modules/* -maxdepth 0 -type d | grep -v "$(uname -r)" |
|
||||
done
|
||||
|
||||
echo "======= installing zfs on rescue system =========="
|
||||
echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections
|
||||
# echo "y" | zfs
|
||||
# linux-headers-generic linux-image-generic
|
||||
apt install --yes software-properties-common dpkg-dev dkms
|
||||
rm -f "$(which zfs)"
|
||||
rm -f "$(which zpool)"
|
||||
echo -e "deb http://deb.debian.org/debian/ testing main contrib non-free\ndeb http://deb.debian.org/debian/ testing main contrib non-free\n" >/etc/apt/sources.list.d/bookworm-testing.list
|
||||
echo -e "Package: src:zfs-linux\nPin: release n=testing\nPin-Priority: 990\n" > /etc/apt/preferences.d/90_zfs
|
||||
apt update
|
||||
apt install -t testing --yes zfs-dkms zfsutils-linux
|
||||
rm /etc/apt/sources.list.d/bookworm-testing.list
|
||||
rm /etc/apt/preferences.d/90_zfs
|
||||
echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections
|
||||
|
||||
apt update
|
||||
export PATH=$PATH:/usr/sbin
|
||||
apt install --yes -t buster-backports libelf-dev zfs-dkms
|
||||
modprobe zfs
|
||||
zfs --version
|
||||
|
||||
echo "======= partitioning the disk =========="
|
||||
@@ -519,9 +506,9 @@ echo "======= partitioning the disk =========="
|
||||
fi
|
||||
|
||||
for selected_disk in "${v_selected_disks[@]}"; do
|
||||
wipefs --all --force "$selected_disk"
|
||||
wipefs --all "$selected_disk"
|
||||
sgdisk -a1 -n1:24K:+1000K -t1:EF02 "$selected_disk"
|
||||
sgdisk -n2:0:+2G -t2:BF01 "$selected_disk" # Boot pool
|
||||
sgdisk -n2:0:+512M -t2:BF01 "$selected_disk" # Boot pool
|
||||
sgdisk -n3:0:"$tail_space_parameter" -t3:BF01 "$selected_disk" # Root pool
|
||||
done
|
||||
|
||||
@@ -548,16 +535,12 @@ echo "======= create zfs pools and datasets =========="
|
||||
pools_mirror_option=
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
zpool create \
|
||||
$v_bpool_tweaks -O canmount=off -O devices=off \
|
||||
-o cachefile=/etc/zpool.cache \
|
||||
-O mountpoint=/boot -R $c_zfs_mount_dir -f \
|
||||
$v_bpool_name $pools_mirror_option "${bpool_disks_partitions[@]}"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
echo -n "$v_passphrase" | zpool create \
|
||||
-o cachefile=/etc/zpool.cache \
|
||||
$v_rpool_tweaks \
|
||||
"${encryption_options[@]}" \
|
||||
-O mountpoint=/ -R $c_zfs_mount_dir -f \
|
||||
@@ -569,11 +552,13 @@ zfs create -o canmount=off -o mountpoint=none "$v_bpool_name/BOOT"
|
||||
zfs create -o canmount=noauto -o mountpoint=/ "$v_rpool_name/ROOT/debian"
|
||||
zfs mount "$v_rpool_name/ROOT/debian"
|
||||
|
||||
zfs create -o canmount=noauto -o mountpoint=/boot "$v_bpool_name/BOOT/debian"
|
||||
zfs mount "$v_bpool_name/BOOT/debian"
|
||||
zfs create -o canmount=noauto -o mountpoint=/boot "$v_bpool_name/BOOT/ubuntu"
|
||||
zfs mount "$v_bpool_name/BOOT/ubuntu"
|
||||
|
||||
zfs create "$v_rpool_name/home"
|
||||
zfs create -o mountpoint=/root "$v_rpool_name/home/root"
|
||||
zfs create -o canmount=off "$v_rpool_name/var"
|
||||
zfs create -o canmount=off "$v_rpool_name/var/lib"
|
||||
zfs create "$v_rpool_name/var/log"
|
||||
zfs create "$v_rpool_name/var/spool"
|
||||
|
||||
@@ -624,7 +609,7 @@ ff02::2 ip6-allrouters
|
||||
ff02::3 ip6-allhosts
|
||||
CONF
|
||||
|
||||
ip6addr_prefix=$(ip -6 a s | grep -E "inet6.+global" | sed -nE 's/.+inet6\s(([0-9a-z]{1,4}:){4,4}).+/\1/p' | head -n 1)
|
||||
ip6addr_prefix=$(ip -6 a s | grep -E "inet6.+global" | sed -nE 's/.+inet6\s(([0-9a-z]{1,4}:){4,4}).+/\1/p')
|
||||
|
||||
cat <<CONF > /mnt/etc/systemd/network/10-eth0.network
|
||||
[Match]
|
||||
@@ -636,7 +621,9 @@ Address=${ip6addr_prefix}:1/64
|
||||
Gateway=fe80::1
|
||||
CONF
|
||||
chroot_execute "systemctl enable systemd-networkd.service"
|
||||
chroot_execute "systemctl enable systemd-resolved.service"
|
||||
|
||||
|
||||
cp /etc/resolv.conf $c_zfs_mount_dir/etc/resolv.conf
|
||||
|
||||
echo "======= preparing the jail for chroot =========="
|
||||
for virtual_fs_dir in proc sys dev; do
|
||||
@@ -711,23 +698,20 @@ echo "======= installing aux packages =========="
|
||||
chroot_execute "apt install --yes man wget curl software-properties-common nano htop gnupg"
|
||||
|
||||
echo "======= installing zfs packages =========="
|
||||
chroot_execute 'echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections'
|
||||
|
||||
if [[ $v_zfs_experimental == "1" ]]; then
|
||||
chroot_execute "wget -O - https://terem42.github.io/zfs-debian/apt_pub.gpg | apt-key add -"
|
||||
chroot_execute "add-apt-repository 'deb https://terem42.github.io/zfs-debian/public zfs-debian-experimental main'"
|
||||
chroot_execute "apt update"
|
||||
chroot_execute "apt install -t zfs-debian-experimental --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
else
|
||||
chroot_execute "apt install --yes -t buster-backports zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
chroot_execute "apt install --yes zfs-initramfs zfs-dkms"
|
||||
fi
|
||||
chroot_execute 'cat << DKMS > /etc/dkms/zfs.conf
|
||||
# override for /usr/src/zfs-*/dkms.conf:
|
||||
# always rebuild initrd when zfs module has been changed
|
||||
# (either by a ZFS update or a new kernel version)
|
||||
REMAKE_INITRD="yes"
|
||||
DKMS'
|
||||
chroot_execute 'echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections'
|
||||
|
||||
if [[ $v_zfs_experimental == "1" ]]; then
|
||||
chroot_execute "apt install --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
else
|
||||
chroot_execute "apt install -t zfs-debian-experimental --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
fi
|
||||
echo "======= installing OpenSSH and network tooling =========="
|
||||
chroot_execute "apt install --yes openssh-server net-tools"
|
||||
|
||||
@@ -742,22 +726,37 @@ chroot_execute "dpkg-reconfigure openssh-server -f noninteractive"
|
||||
echo "======= set root password =========="
|
||||
chroot_execute "echo root:$(printf "%q" "$v_root_password") | chpasswd"
|
||||
|
||||
echo "======= setting up zfs cache =========="
|
||||
cp /etc/zpool.cache /mnt/etc/zfs/zpool.cache
|
||||
echo "======= setting up zfs services =========="
|
||||
chroot_execute "cat > /etc/systemd/system/zfs-import-bpool.service <<UNIT
|
||||
[Unit]
|
||||
DefaultDependencies=no
|
||||
Before=zfs-import-scan.service
|
||||
Before=zfs-import-cache.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStartPre=/bin/sh -c '[ -f /etc/zfs/zpool.cache ] && mv /etc/zfs/zpool.cache /etc/zfs/preboot_zpool.cache || true'
|
||||
ExecStart=/sbin/zpool import -N -o cachefile=none $v_bpool_name
|
||||
ExecStartPost=/bin/sh -c '[ -f /etc/zfs/preboot_zpool.cache ] && mv /etc/zfs/preboot_zpool.cache /etc/zfs/zpool.cache || true'
|
||||
|
||||
[Install]
|
||||
WantedBy=zfs-import.target
|
||||
UNIT"
|
||||
|
||||
chroot_execute "systemctl enable zfs-import-bpool.service"
|
||||
|
||||
echo "========setting up zfs module parameters========"
|
||||
chroot_execute "echo options zfs zfs_arc_max=$((v_zfs_arc_max_mb * 1024 * 1024)) >> /etc/modprobe.d/zfs.conf"
|
||||
|
||||
echo "======= setting up grub =========="
|
||||
chroot_execute "echo 'grub-pc grub-pc/install_devices_empty boolean true' | debconf-set-selections"
|
||||
chroot_execute "apt install --yes grub-pc"
|
||||
for disk in ${v_selected_disks[@]}; do
|
||||
chroot_execute "grub-install $disk"
|
||||
done
|
||||
chroot_execute "DEBIAN_FRONTEND=noninteractive apt install --yes grub-pc"
|
||||
chroot_execute "grub-install ${v_selected_disks[0]}"
|
||||
|
||||
chroot_execute "sed -i 's/#GRUB_TERMINAL=console/GRUB_TERMINAL=console/g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"net.ifnames=0\"|' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX=\"\"|GRUB_CMDLINE_LINUX=\"root=ZFS=$v_rpool_name/ROOT/debian\"|g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX=\"\"|GRUB_CMDLINE_LINUX=\"root=ZFS=rpool/ROOT/debian\"|g' /etc/default/grub"
|
||||
|
||||
chroot_execute "sed -i 's/quiet//g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's/splash//g' /etc/default/grub"
|
||||
@@ -771,8 +770,7 @@ if [[ $v_encrypt_rpool == "1" ]]; then
|
||||
echo "=========set up dropbear=============="
|
||||
|
||||
chroot_execute "apt install --yes dropbear-initramfs"
|
||||
|
||||
mkdir -p "$c_zfs_mount_dir/etc/dropbear-initramfs"
|
||||
|
||||
cp /root/.ssh/authorized_keys "$c_zfs_mount_dir/etc/dropbear-initramfs/authorized_keys"
|
||||
|
||||
cp "$c_zfs_mount_dir/etc/ssh/ssh_host_rsa_key" "$c_zfs_mount_dir/etc/ssh/ssh_host_rsa_key_temp"
|
||||
@@ -789,6 +787,18 @@ if [[ $v_encrypt_rpool == "1" ]]; then
|
||||
rm -rf "$c_zfs_mount_dir/etc/dropbear-initramfs/dropbear_dss_host_key"
|
||||
fi
|
||||
|
||||
#cd "$c_zfs_mount_dir/root"
|
||||
#wget http://ftp.de.debian.org/debian/pool/main/libt/libtommath/libtommath1_1.1.0-3_amd64.deb
|
||||
#wget http://ftp.de.debian.org/debian/pool/main/d/dropbear/dropbear-bin_2018.76-5_amd64.deb
|
||||
#wget http://ftp.de.debian.org/debian/pool/main/d/dropbear/dropbear-initramfs_2018.76-5_all.deb
|
||||
|
||||
#chroot_execute "dpkg -i /root/libtommath1_1.1.0-3_amd64.deb"
|
||||
#chroot_execute "dpkg -i /root/dropbear-bin_2018.76-5_amd64.deb"
|
||||
#chroot_execute "dpkg -i /root/dropbear-initramfs_2018.76-5_all.deb"
|
||||
|
||||
#rm $c_zfs_mount_dir/root/*.deb
|
||||
#cd /root
|
||||
|
||||
echo "============setup root prompt============"
|
||||
cat > "$c_zfs_mount_dir/root/.bashrc" <<CONF
|
||||
export PS1='\[\033[01;31m\]\u\[\033[01;33m\]@\[\033[01;32m\]\h \[\033[01;33m\]\w \[\033[01;35m\]\$ \[\033[00m\]'
|
||||
@@ -799,45 +809,9 @@ CONF
|
||||
|
||||
echo "========running packages upgrade==========="
|
||||
chroot_execute "apt upgrade --yes"
|
||||
chroot_execute "apt purge cryptsetup* --yes"
|
||||
|
||||
echo "===========add static route to initramfs via hook to add default routes for Hetzner due to Debian/Ubuntu initramfs DHCP bug ========="
|
||||
mkdir -p "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount"
|
||||
cat > "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount/static-route" <<'CONF'
|
||||
#!/bin/sh
|
||||
PREREQ=""
|
||||
prereqs()
|
||||
{
|
||||
echo "$PREREQ"
|
||||
}
|
||||
|
||||
case $1 in
|
||||
prereqs)
|
||||
prereqs
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
. /scripts/functions
|
||||
# Begin real processing below this line
|
||||
|
||||
configure_networking
|
||||
|
||||
ip route add 172.31.1.1/255.255.255.255 dev eth0
|
||||
ip route add default via 172.31.1.1 dev eth0
|
||||
CONF
|
||||
|
||||
cat > "$c_zfs_mount_dir/etc/network/interfaces" <<'CONF'
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
iface lo inet6 loopback
|
||||
|
||||
allow-hotplug eth0
|
||||
iface eth0 inet dhcp
|
||||
iface eth0 inet6 dhcp
|
||||
CONF
|
||||
|
||||
chmod 755 "$c_zfs_mount_dir/etc/network/interfaces"
|
||||
#echo "===========add static route to initramfs via hook to add default routes due to initramfs DHCP bug ========="
|
||||
# removed
|
||||
|
||||
echo "======= update initramfs =========="
|
||||
chroot_execute "update-initramfs -u -k all"
|
||||
@@ -847,14 +821,14 @@ chroot_execute "update-grub"
|
||||
|
||||
echo "======= setting up zed =========="
|
||||
if [[ $v_zfs_experimental == "1" ]]; then
|
||||
chroot_execute "zfs set canmount=noauto $v_rpool_name"
|
||||
chroot_execute "zfs set canmount=noauto rpool"
|
||||
else
|
||||
initial_load_debian_zed_cache
|
||||
fi
|
||||
|
||||
echo "======= setting mountpoints =========="
|
||||
chroot_execute "zfs set mountpoint=legacy $v_bpool_name/BOOT/debian"
|
||||
chroot_execute "echo $v_bpool_name/BOOT/debian /boot zfs nodev,relatime,x-systemd.requires=zfs-mount.service,x-systemd.device-timeout=10 0 0 > /etc/fstab"
|
||||
chroot_execute "zfs set mountpoint=legacy $v_bpool_name/BOOT/ubuntu"
|
||||
chroot_execute "echo $v_bpool_name/BOOT/ubuntu /boot zfs nodev,relatime,x-systemd.requires=zfs-import-bpool.service 0 0 > /etc/fstab"
|
||||
|
||||
chroot_execute "zfs set mountpoint=legacy $v_rpool_name/var/log"
|
||||
chroot_execute "echo $v_rpool_name/var/log /var/log zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
@@ -866,9 +840,7 @@ chroot_execute "zfs set mountpoint=legacy $v_rpool_name/tmp"
|
||||
chroot_execute "echo $v_rpool_name/tmp /tmp zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
|
||||
echo "========= add swap, if defined"
|
||||
if [[ $v_swap_size -gt 0 ]]; then
|
||||
chroot_execute "echo /dev/zvol/$v_rpool_name/swap none swap discard 0 0 >> /etc/fstab"
|
||||
fi
|
||||
[[ $v_swap_size -gt 0 ]] && chroot_execute "echo /dev/zvol/$v_rpool_name/swap none swap discard 0 0 >> /etc/fstab" || true
|
||||
chroot_execute "echo RESUME=none > /etc/initramfs-tools/conf.d/resume"
|
||||
|
||||
echo "======= unmounting filesystems and zfs pools =========="
|
||||
|
||||
@@ -1,909 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
: <<'end_header_info'
|
||||
(c) Andrey Prokopenko job@terem.fr
|
||||
fully automatic script to install Debian 12 with ZFS root on Hetzner VPS
|
||||
WARNING: all data on the disk will be destroyed
|
||||
How to use: add SSH key to the rescue console, set it OS to linux64, then press "mount rescue and power cycle" button
|
||||
Next, connect via SSH to console, and run the script
|
||||
Answer script questions about desired hostname, ZFS ARC cache size et cetera
|
||||
To cope with network failures its higly recommended to run the script inside screen console
|
||||
screen -dmS zfs
|
||||
screen -r zfs
|
||||
To detach from screen console, hit Ctrl-d then a
|
||||
end_header_info
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
export TMPDIR=/tmp
|
||||
|
||||
# Variables
|
||||
v_bpool_name=
|
||||
v_bpool_tweaks=
|
||||
v_rpool_name=
|
||||
v_rpool_tweaks=
|
||||
declare -a v_selected_disks
|
||||
v_swap_size= # integer
|
||||
v_free_tail_space= # integer
|
||||
v_hostname=
|
||||
v_kernel_variant=
|
||||
v_zfs_arc_max_mb=
|
||||
v_root_password=
|
||||
v_encrypt_rpool= # 0=false, 1=true
|
||||
v_passphrase=
|
||||
v_zfs_experimental=
|
||||
v_suitable_disks=()
|
||||
|
||||
# Constants
|
||||
c_deb_packages_repo=https://deb.debian.org/debian
|
||||
c_deb_security_repo=https://deb.debian.org/debian-security
|
||||
|
||||
c_default_zfs_arc_max_mb=250
|
||||
c_default_bpool_tweaks="-o ashift=12 -O compression=lz4"
|
||||
c_default_rpool_tweaks="-o ashift=12 -O acltype=posixacl -O compression=zstd-9 -O dnodesize=auto -O relatime=on -O xattr=sa -O normalization=formD"
|
||||
c_default_hostname=terem
|
||||
c_zfs_mount_dir=/mnt
|
||||
c_log_dir=$(dirname "$(mktemp)")/zfs-hetzner-vm
|
||||
c_install_log=$c_log_dir/install.log
|
||||
c_lsb_release_log=$c_log_dir/lsb_release.log
|
||||
c_disks_log=$c_log_dir/disks.log
|
||||
c_efimode_enabled="$(if [[ -d /sys/firmware/efi/efivars ]]; then echo 1; else echo 0; fi)"
|
||||
|
||||
function activate_debug {
|
||||
mkdir -p "$c_log_dir"
|
||||
|
||||
exec 5> "$c_install_log"
|
||||
BASH_XTRACEFD="5"
|
||||
set -x
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2120
|
||||
function print_step_info_header {
|
||||
echo -n "
|
||||
###############################################################################
|
||||
# ${FUNCNAME[1]}"
|
||||
|
||||
if [[ "${1:-}" != "" ]]; then
|
||||
echo -n " $1"
|
||||
fi
|
||||
|
||||
|
||||
echo "
|
||||
###############################################################################
|
||||
"
|
||||
}
|
||||
|
||||
function print_variables {
|
||||
for variable_name in "$@"; do
|
||||
declare -n variable_reference="$variable_name"
|
||||
|
||||
echo -n "$variable_name:"
|
||||
|
||||
case "$(declare -p "$variable_name")" in
|
||||
"declare -a"* )
|
||||
for entry in "${variable_reference[@]}"; do
|
||||
echo -n " \"$entry\""
|
||||
done
|
||||
;;
|
||||
"declare -A"* )
|
||||
for key in "${!variable_reference[@]}"; do
|
||||
echo -n " $key=\"${variable_reference[$key]}\""
|
||||
done
|
||||
;;
|
||||
* )
|
||||
echo -n " $variable_reference"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo
|
||||
done
|
||||
|
||||
echo
|
||||
}
|
||||
|
||||
function display_intro_banner {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
local dialog_message='Hello!
|
||||
This script will prepare the ZFS pools, then install and configure minimal Debian 12 with ZFS root on Hetzner hosting VPS instance
|
||||
The script with minimal changes may be used on any other hosting provider supporting KVM virtualization and offering Debian-based rescue system.
|
||||
In order to stop the procedure, hit Esc twice during dialogs (excluding yes/no ones), or Ctrl+C while any operation is running.
|
||||
'
|
||||
dialog --msgbox "$dialog_message" 30 100
|
||||
}
|
||||
|
||||
function store_os_distro_information {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
lsb_release --all > "$c_lsb_release_log"
|
||||
}
|
||||
|
||||
function check_prerequisites {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
if [[ $(id -u) -ne 0 ]]; then
|
||||
echo 'This script must be run with administrative privileges!'
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -r /root/.ssh/authorized_keys ]]; then
|
||||
echo "SSH pubkey file is absent, please add it to the rescue system setting, then reboot into rescue system and run the script"
|
||||
exit 1
|
||||
fi
|
||||
if ! dpkg-query --showformat="\${Status}" -W dialog 2> /dev/null | grep -q "install ok installed"; then
|
||||
apt install --yes dialog
|
||||
fi
|
||||
}
|
||||
|
||||
function initial_load_debian_zed_cache {
|
||||
chroot_execute "mkdir /etc/zfs/zfs-list.cache"
|
||||
chroot_execute "touch /etc/zfs/zfs-list.cache/$v_rpool_name"
|
||||
chroot_execute "ln -sf /usr/lib/zfs-linux/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d/"
|
||||
|
||||
chroot_execute "zed -F &"
|
||||
|
||||
local success=0
|
||||
|
||||
if [[ ! -e "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name" ]] || [[ -e "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name" && (( $(find "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name" -type f -printf '%s' 2> /dev/null) == 0 )) ]]; then
|
||||
chroot_execute "zfs set canmount=noauto $v_rpool_name"
|
||||
|
||||
SECONDS=0
|
||||
|
||||
while (( SECONDS++ <= 120 )); do
|
||||
if [[ -e "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name" ]] && (( $(find "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name" -type f -printf '%s' 2> /dev/null) > 0 )); then
|
||||
success=1
|
||||
break
|
||||
else
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
else
|
||||
success=1
|
||||
fi
|
||||
|
||||
if (( success != 1 )); then
|
||||
echo "Fatal zed daemon error: the ZFS cache hasn't been updated by ZED!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chroot_execute "pkill zed"
|
||||
|
||||
sed -Ei "s|/$c_zfs_mount_dir/?|/|g" "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name"
|
||||
}
|
||||
|
||||
function find_suitable_disks {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
udevadm trigger
|
||||
|
||||
# shellcheck disable=SC2012
|
||||
ls -l /dev/disk/by-id | tail -n +2 | perl -lane 'print "@F[8..10]"' > "$c_disks_log"
|
||||
|
||||
local candidate_disk_ids
|
||||
local mounted_devices
|
||||
|
||||
candidate_disk_ids=$(find /dev/disk/by-id -regextype awk -regex '.+/(ata|nvme|scsi)-.+' -not -regex '.+-part[0-9]+$' | sort)
|
||||
mounted_devices="$(df | awk 'BEGIN {getline} {print $1}' | xargs -n 1 lsblk -no pkname 2> /dev/null | sort -u || true)"
|
||||
|
||||
while read -r disk_id || [[ -n "$disk_id" ]]; do
|
||||
local device_info
|
||||
|
||||
device_info="$(udevadm info --query=property "$(readlink -f "$disk_id")")"
|
||||
block_device_basename="$(basename "$(readlink -f "$disk_id")")"
|
||||
|
||||
if ! grep -q '^ID_TYPE=cd$' <<< "$device_info"; then
|
||||
if ! grep -q "^$block_device_basename\$" <<< "$mounted_devices"; then
|
||||
v_suitable_disks+=("$disk_id")
|
||||
fi
|
||||
fi
|
||||
|
||||
cat >> "$c_disks_log" << LOG
|
||||
|
||||
## DEVICE: $disk_id ################################
|
||||
|
||||
$(udevadm info --query=property "$(readlink -f "$disk_id")")
|
||||
|
||||
LOG
|
||||
|
||||
done < <(echo -n "$candidate_disk_ids")
|
||||
|
||||
if [[ ${#v_suitable_disks[@]} -eq 0 ]]; then
|
||||
local dialog_message='No suitable disks have been found!
|
||||
|
||||
If you think this is a bug, please open an issue on https://github.com/terem42/zfs-hetzner-vm/issues, and attach the file `'"$c_disks_log"'`.
|
||||
'
|
||||
dialog --msgbox "$dialog_message" 30 100
|
||||
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_variables v_suitable_disks
|
||||
}
|
||||
|
||||
function select_disks {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
while true; do
|
||||
local menu_entries_option=()
|
||||
|
||||
if [[ ${#v_suitable_disks[@]} -eq 1 ]]; then
|
||||
local disk_selection_status=ON
|
||||
else
|
||||
local disk_selection_status=OFF
|
||||
fi
|
||||
|
||||
for disk_id in "${v_suitable_disks[@]}"; do
|
||||
menu_entries_option+=("$disk_id" "($block_device_basename)" "$disk_selection_status")
|
||||
done
|
||||
|
||||
local dialog_message="Select the ZFS devices (multiple selections can be in mirror or strip).
|
||||
|
||||
Devices with mounted partitions, cdroms, and removable devices are not displayed!
|
||||
"
|
||||
mapfile -t v_selected_disks < <(dialog --separate-output --checklist "$dialog_message" 30 100 $((${#menu_entries_option[@]} / 3)) "${menu_entries_option[@]}" 3>&1 1>&2 2>&3)
|
||||
|
||||
if [[ ${#v_selected_disks[@]} -gt 0 ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
print_variables v_selected_disks
|
||||
}
|
||||
|
||||
function ask_swap_size {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
local swap_size_invalid_message=
|
||||
|
||||
while [[ ! $v_swap_size =~ ^[0-9]+$ ]]; do
|
||||
v_swap_size=$(dialog --inputbox "${swap_size_invalid_message}Enter the swap size in GiB (0 for no swap):" 30 100 2 3>&1 1>&2 2>&3)
|
||||
|
||||
swap_size_invalid_message="Invalid swap size! "
|
||||
done
|
||||
|
||||
print_variables v_swap_size
|
||||
}
|
||||
|
||||
function ask_free_tail_space {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
local tail_space_invalid_message=
|
||||
|
||||
while [[ ! $v_free_tail_space =~ ^[0-9]+$ ]]; do
|
||||
v_free_tail_space=$(dialog --inputbox "${tail_space_invalid_message}Enter the space to leave at the end of each disk (0 for none):" 30 100 0 3>&1 1>&2 2>&3)
|
||||
|
||||
tail_space_invalid_message="Invalid size! "
|
||||
done
|
||||
|
||||
print_variables v_free_tail_space
|
||||
}
|
||||
|
||||
function ask_zfs_arc_max_size {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
local zfs_arc_max_invalid_message=
|
||||
|
||||
while [[ ! $v_zfs_arc_max_mb =~ ^[0-9]+$ ]]; do
|
||||
v_zfs_arc_max_mb=$(dialog --inputbox "${zfs_arc_max_invalid_message}Enter ZFS ARC cache max size in Mb (minimum 64Mb, enter 0 for ZFS default value, the default will take up to 50% of memory):" 30 100 "$c_default_zfs_arc_max_mb" 3>&1 1>&2 2>&3)
|
||||
|
||||
zfs_arc_max_invalid_message="Invalid size! "
|
||||
done
|
||||
|
||||
print_variables v_zfs_arc_max_mb
|
||||
}
|
||||
|
||||
|
||||
function ask_pool_names {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
local bpool_name_invalid_message=
|
||||
|
||||
while [[ ! $v_bpool_name =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_bpool_name=$(dialog --inputbox "${bpool_name_invalid_message}Insert the name for the boot pool" 30 100 bpool 3>&1 1>&2 2>&3)
|
||||
|
||||
bpool_name_invalid_message="Invalid pool name! "
|
||||
done
|
||||
local rpool_name_invalid_message=
|
||||
|
||||
while [[ ! $v_rpool_name =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_rpool_name=$(dialog --inputbox "${rpool_name_invalid_message}Insert the name for the root pool" 30 100 rpool 3>&1 1>&2 2>&3)
|
||||
|
||||
rpool_name_invalid_message="Invalid pool name! "
|
||||
done
|
||||
|
||||
print_variables v_bpool_name v_rpool_name
|
||||
}
|
||||
|
||||
function ask_pool_tweaks {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
v_bpool_tweaks=$(dialog --inputbox "Insert the tweaks for the boot pool" 30 100 -- "$c_default_bpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
v_rpool_tweaks=$(dialog --inputbox "Insert the tweaks for the root pool" 30 100 -- "$c_default_rpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
|
||||
print_variables v_bpool_tweaks v_rpool_tweaks
|
||||
}
|
||||
|
||||
|
||||
function ask_root_password {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
set +x
|
||||
local password_invalid_message=
|
||||
local password_repeat=-
|
||||
|
||||
while [[ "$v_root_password" != "$password_repeat" || "$v_root_password" == "" ]]; do
|
||||
v_root_password=$(dialog --passwordbox "${password_invalid_message}Please enter the root account password (can't be empty):" 30 100 3>&1 1>&2 2>&3)
|
||||
password_repeat=$(dialog --passwordbox "Please repeat the password:" 30 100 3>&1 1>&2 2>&3)
|
||||
|
||||
password_invalid_message="Passphrase empty, or not matching! "
|
||||
done
|
||||
set -x
|
||||
}
|
||||
|
||||
function ask_encryption {
|
||||
print_step_info_header
|
||||
|
||||
if dialog --defaultno --yesno 'Do you want to encrypt the root pool?' 30 100; then
|
||||
v_encrypt_rpool=1
|
||||
fi
|
||||
set +x
|
||||
if [[ $v_encrypt_rpool == "1" ]]; then
|
||||
local passphrase_invalid_message=
|
||||
local passphrase_repeat=-
|
||||
while [[ "$v_passphrase" != "$passphrase_repeat" || ${#v_passphrase} -lt 8 ]]; do
|
||||
v_passphrase=$(dialog --passwordbox "${passphrase_invalid_message}Please enter the passphrase for the root pool (8 chars min.):" 30 100 3>&1 1>&2 2>&3)
|
||||
passphrase_repeat=$(dialog --passwordbox "Please repeat the passphrase:" 30 100 3>&1 1>&2 2>&3)
|
||||
|
||||
passphrase_invalid_message="Passphrase too short, or not matching! "
|
||||
done
|
||||
fi
|
||||
set -x
|
||||
}
|
||||
|
||||
function ask_zfs_experimental {
|
||||
print_step_info_header
|
||||
|
||||
if dialog --defaultno --yesno 'Do you want to use experimental zfs module build?' 30 100; then
|
||||
v_zfs_experimental=1
|
||||
fi
|
||||
}
|
||||
|
||||
function ask_hostname {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
local hostname_invalid_message=
|
||||
|
||||
while [[ ! $v_hostname =~ ^[a-z][a-zA-Z0-9_:.-]+$ ]]; do
|
||||
v_hostname=$(dialog --inputbox "${hostname_invalid_message}Set the host name" 30 100 "$c_default_hostname" 3>&1 1>&2 2>&3)
|
||||
|
||||
hostname_invalid_message="Invalid host name! "
|
||||
done
|
||||
|
||||
print_variables v_hostname
|
||||
}
|
||||
|
||||
function determine_kernel_variant {
|
||||
if dmidecode | grep -q vServer; then
|
||||
v_kernel_variant="-cloud"
|
||||
fi
|
||||
}
|
||||
|
||||
function chroot_execute {
|
||||
chroot $c_zfs_mount_dir bash -c "DEBIAN_FRONTEND=noninteractive $1"
|
||||
}
|
||||
|
||||
function unmount_and_export_fs {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
for virtual_fs_dir in dev sys proc; do
|
||||
umount --recursive --force --lazy "$c_zfs_mount_dir/$virtual_fs_dir"
|
||||
done
|
||||
|
||||
local max_unmount_wait=5
|
||||
echo -n "Waiting for virtual filesystems to unmount "
|
||||
|
||||
SECONDS=0
|
||||
|
||||
for virtual_fs_dir in dev sys proc; do
|
||||
while mountpoint -q "$c_zfs_mount_dir/$virtual_fs_dir" && [[ $SECONDS -lt $max_unmount_wait ]]; do
|
||||
sleep 0.5
|
||||
echo -n .
|
||||
done
|
||||
done
|
||||
|
||||
echo
|
||||
|
||||
for virtual_fs_dir in dev sys proc; do
|
||||
if mountpoint -q "$c_zfs_mount_dir/$virtual_fs_dir"; then
|
||||
echo "Re-issuing umount for $c_zfs_mount_dir/$virtual_fs_dir"
|
||||
umount --recursive --force --lazy "$c_zfs_mount_dir/$virtual_fs_dir"
|
||||
fi
|
||||
done
|
||||
|
||||
SECONDS=0
|
||||
zpools_exported=99
|
||||
echo "===========exporting zfs pools============="
|
||||
set +e
|
||||
while (( zpools_exported == 99 )) && (( SECONDS++ <= 60 )); do
|
||||
if zpool export -a 2> /dev/null; then
|
||||
zpools_exported=1
|
||||
echo "all zfs pools were succesfully exported"
|
||||
break;
|
||||
else
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
set -e
|
||||
if (( zpools_exported != 1 )); then
|
||||
echo "failed to export zfs pools"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
#################### MAIN ################################
|
||||
export LC_ALL=en_US.UTF-8
|
||||
export NCURSES_NO_UTF8_ACS=1
|
||||
|
||||
check_prerequisites
|
||||
|
||||
activate_debug
|
||||
|
||||
display_intro_banner
|
||||
|
||||
find_suitable_disks
|
||||
|
||||
select_disks
|
||||
|
||||
ask_swap_size
|
||||
|
||||
ask_free_tail_space
|
||||
|
||||
ask_pool_names
|
||||
|
||||
ask_pool_tweaks
|
||||
|
||||
ask_encryption
|
||||
|
||||
ask_zfs_arc_max_size
|
||||
|
||||
ask_zfs_experimental
|
||||
|
||||
ask_root_password
|
||||
|
||||
ask_hostname
|
||||
|
||||
determine_kernel_variant
|
||||
|
||||
clear
|
||||
|
||||
echo "===========remove unused kernels in rescue system========="
|
||||
for kver in $(find /lib/modules/* -maxdepth 0 -type d | grep -v "$(uname -r)" | cut -s -d "/" -f 4); do
|
||||
apt purge --yes "linux-headers-$kver"
|
||||
apt purge --yes "linux-image-$kver"
|
||||
done
|
||||
|
||||
echo "======= installing zfs on rescue system =========="
|
||||
|
||||
echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections
|
||||
# echo "y" | zfs
|
||||
# linux-headers-generic linux-image-generic
|
||||
apt install --yes software-properties-common dpkg-dev dkms
|
||||
rm -f "$(which zfs)"
|
||||
rm -f "$(which zpool)"
|
||||
echo -e "deb http://deb.debian.org/debian/ testing main contrib non-free\ndeb http://deb.debian.org/debian/ testing main contrib non-free\n" >/etc/apt/sources.list.d/bookworm-testing.list
|
||||
echo -e "Package: src:zfs-linux\nPin: release n=testing\nPin-Priority: 990\n" > /etc/apt/preferences.d/90_zfs
|
||||
apt update
|
||||
apt install -t testing --yes zfs-dkms zfsutils-linux
|
||||
rm /etc/apt/sources.list.d/bookworm-testing.list
|
||||
rm /etc/apt/preferences.d/90_zfs
|
||||
apt update
|
||||
export PATH=$PATH:/usr/sbin
|
||||
zfs --version
|
||||
|
||||
echo "======= partitioning the disk =========="
|
||||
|
||||
if [[ $v_free_tail_space -eq 0 ]]; then
|
||||
tail_space_parameter=0
|
||||
else
|
||||
tail_space_parameter="-${v_free_tail_space}G"
|
||||
fi
|
||||
|
||||
for selected_disk in "${v_selected_disks[@]}"; do
|
||||
wipefs --all --force "$selected_disk"
|
||||
if (( c_efimode_enabled == 1 )); then
|
||||
sgdisk -a1 -n1:24K:+1G -t1:EF00 "$selected_disk" # EFI partition
|
||||
else
|
||||
sgdisk -a1 -n1:24K:+1000K -t1:EF02 "$selected_disk"
|
||||
fi
|
||||
sgdisk -n2:0:+2G -t2:BF01 "$selected_disk" # Boot pool
|
||||
sgdisk -n3:0:"$tail_space_parameter" -t3:BF01 "$selected_disk" # Root pool
|
||||
done
|
||||
|
||||
udevadm settle
|
||||
|
||||
echo "======= create zfs pools and datasets =========="
|
||||
|
||||
encryption_options=()
|
||||
rpool_disks_partitions=()
|
||||
bpool_disks_partitions=()
|
||||
|
||||
if [[ $v_encrypt_rpool == "1" ]]; then
|
||||
encryption_options=(-O "encryption=aes-256-gcm" -O "keylocation=prompt" -O "keyformat=passphrase")
|
||||
fi
|
||||
|
||||
for selected_disk in "${v_selected_disks[@]}"; do
|
||||
rpool_disks_partitions+=("${selected_disk}-part3")
|
||||
bpool_disks_partitions+=("${selected_disk}-part2")
|
||||
done
|
||||
|
||||
pools_mirror_option=
|
||||
if [[ ${#v_selected_disks[@]} -gt 1 ]]; then
|
||||
if dialog --defaultno --yesno "Do you want to use mirror mode for ${v_selected_disks[*]}?" 30 100; then
|
||||
pools_mirror_option=mirror
|
||||
fi
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
zpool create \
|
||||
-o cachefile=/etc/zpool.cache \
|
||||
-o compatibility=grub2 \
|
||||
-O mountpoint=/boot -R $c_zfs_mount_dir -f \
|
||||
$v_bpool_name $pools_mirror_option "${bpool_disks_partitions[@]}"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
echo -n "$v_passphrase" | zpool create \
|
||||
$v_rpool_tweaks \
|
||||
-o cachefile=/etc/zpool.cache \
|
||||
"${encryption_options[@]}" \
|
||||
-O mountpoint=/ -R $c_zfs_mount_dir -f \
|
||||
$v_rpool_name $pools_mirror_option "${rpool_disks_partitions[@]}"
|
||||
|
||||
zfs create -o canmount=off -o mountpoint=none "$v_rpool_name/ROOT"
|
||||
zfs create -o canmount=off -o mountpoint=none "$v_bpool_name/BOOT"
|
||||
|
||||
zfs create -o canmount=noauto -o mountpoint=/ "$v_rpool_name/ROOT/debian"
|
||||
zfs mount "$v_rpool_name/ROOT/debian"
|
||||
|
||||
zfs create -o canmount=noauto -o mountpoint=/boot "$v_bpool_name/BOOT/debian"
|
||||
zfs mount "$v_bpool_name/BOOT/debian"
|
||||
|
||||
zfs create "$v_rpool_name/home"
|
||||
#zfs create -o mountpoint=/root "$v_rpool_name/home/root"
|
||||
zfs create -o canmount=off "$v_rpool_name/var"
|
||||
zfs create "$v_rpool_name/var/log"
|
||||
zfs create "$v_rpool_name/var/spool"
|
||||
|
||||
zfs create -o com.sun:auto-snapshot=false "$v_rpool_name/var/cache"
|
||||
zfs create -o com.sun:auto-snapshot=false "$v_rpool_name/var/tmp"
|
||||
chmod 1777 "$c_zfs_mount_dir/var/tmp"
|
||||
|
||||
zfs create "$v_rpool_name/srv"
|
||||
|
||||
zfs create -o canmount=off "$v_rpool_name/usr"
|
||||
zfs create "$v_rpool_name/usr/local"
|
||||
|
||||
zfs create "$v_rpool_name/var/mail"
|
||||
|
||||
zfs create -o com.sun:auto-snapshot=false -o canmount=on -o mountpoint=/tmp "$v_rpool_name/tmp"
|
||||
chmod 1777 "$c_zfs_mount_dir/tmp"
|
||||
|
||||
if [[ $v_swap_size -gt 0 ]]; then
|
||||
zfs create \
|
||||
-V "${v_swap_size}G" -b "$(getconf PAGESIZE)" \
|
||||
-o compression=zle -o logbias=throughput -o sync=always -o primarycache=metadata -o secondarycache=none -o com.sun:auto-snapshot=false \
|
||||
"$v_rpool_name/swap"
|
||||
|
||||
udevadm settle
|
||||
|
||||
mkswap -f "/dev/zvol/$v_rpool_name/swap"
|
||||
fi
|
||||
|
||||
if (( c_efimode_enabled == 1 )); then
|
||||
echo "======= create filesystem on EFI partition(s) =========="
|
||||
|
||||
for selected_disk in "${v_selected_disks[@]}"; do
|
||||
mkfs.fat -F32 "${selected_disk}-part1"
|
||||
done
|
||||
mkdir -p "$c_zfs_mount_dir/boot/efi"
|
||||
mount "${v_selected_disks[0]}-part1" "$c_zfs_mount_dir/boot/efi"
|
||||
fi
|
||||
|
||||
echo "======= setting up initial system packages =========="
|
||||
debootstrap --arch=amd64 bookworm "$c_zfs_mount_dir" "$c_deb_packages_repo"
|
||||
|
||||
zfs set devices=off "$v_rpool_name"
|
||||
|
||||
echo "======= setting up the network =========="
|
||||
|
||||
echo "$v_hostname" > $c_zfs_mount_dir/etc/hostname
|
||||
|
||||
cat > "$c_zfs_mount_dir/etc/hosts" <<CONF
|
||||
127.0.1.1 ${v_hostname}
|
||||
127.0.0.1 localhost
|
||||
|
||||
# The following lines are desirable for IPv6 capable hosts
|
||||
::1 ip6-localhost ip6-loopback
|
||||
fe00::0 ip6-localnet
|
||||
ff00::0 ip6-mcastprefix
|
||||
ff02::1 ip6-allnodes
|
||||
ff02::2 ip6-allrouters
|
||||
ff02::3 ip6-allhosts
|
||||
CONF
|
||||
|
||||
ip6addr_prefix=$(ip -6 a s | grep -E "inet6.+global" | sed -nE 's/.+inet6\s(([0-9a-z]{1,4}:){4,4}).+/\1/p' | head -n 1)
|
||||
|
||||
cat <<CONF > "$c_zfs_mount_dir/etc/systemd/network/10-eth0.network"
|
||||
[Match]
|
||||
Name=eth0
|
||||
|
||||
[Network]
|
||||
DHCP=ipv4
|
||||
Address=${ip6addr_prefix}:1/64
|
||||
Gateway=fe80::1
|
||||
CONF
|
||||
chroot_execute "systemctl enable systemd-networkd.service"
|
||||
|
||||
echo "======= preparing the jail for chroot =========="
|
||||
for virtual_fs_dir in proc sys dev; do
|
||||
mount --rbind "/$virtual_fs_dir" "$c_zfs_mount_dir/$virtual_fs_dir"
|
||||
done
|
||||
|
||||
echo "======= setting apt repos =========="
|
||||
cat > "$c_zfs_mount_dir/etc/apt/sources.list" <<CONF
|
||||
deb $c_deb_packages_repo bookworm main contrib non-free non-free-firmware
|
||||
deb $c_deb_packages_repo bookworm-updates main contrib non-free non-free-firmware
|
||||
deb $c_deb_security_repo bookworm-security main contrib non-free non-free-firmware
|
||||
deb $c_deb_packages_repo bookworm-backports main contrib non-free non-free-firmware
|
||||
CONF
|
||||
|
||||
chroot_execute "apt update"
|
||||
|
||||
echo "======= setting locale, console and language =========="
|
||||
chroot_execute "apt install --yes -qq locales debconf-i18n apt-utils"
|
||||
sed -i 's/# en_US.UTF-8/en_US.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
sed -i 's/# fr_FR.UTF-8/fr_FR.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
sed -i 's/# fr_FR.UTF-8/fr_FR.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
sed -i 's/# de_AT.UTF-8/de_AT.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
sed -i 's/# de_DE.UTF-8/de_DE.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
|
||||
chroot_execute 'cat <<CONF | debconf-set-selections
|
||||
locales locales/default_environment_locale select en_US.UTF-8
|
||||
keyboard-configuration keyboard-configuration/store_defaults_in_debconf_db boolean true
|
||||
keyboard-configuration keyboard-configuration/variant select German
|
||||
keyboard-configuration keyboard-configuration/unsupported_layout boolean true
|
||||
keyboard-configuration keyboard-configuration/modelcode string pc105
|
||||
keyboard-configuration keyboard-configuration/unsupported_config_layout boolean true
|
||||
keyboard-configuration keyboard-configuration/layout select German
|
||||
keyboard-configuration keyboard-configuration/layoutcode string de
|
||||
keyboard-configuration keyboard-configuration/optionscode string
|
||||
keyboard-configuration keyboard-configuration/toggle select No toggling
|
||||
keyboard-configuration keyboard-configuration/xkb-keymap select de
|
||||
keyboard-configuration keyboard-configuration/switch select No temporary switch
|
||||
keyboard-configuration keyboard-configuration/unsupported_config_options boolean true
|
||||
keyboard-configuration keyboard-configuration/ctrl_alt_bksp boolean false
|
||||
keyboard-configuration keyboard-configuration/variantcode string
|
||||
keyboard-configuration keyboard-configuration/model select Generic 105-key PC (intl.)
|
||||
keyboard-configuration keyboard-configuration/altgr select The default for the keyboard layout
|
||||
keyboard-configuration keyboard-configuration/compose select No compose key
|
||||
keyboard-configuration keyboard-configuration/unsupported_options boolean true
|
||||
console-setup console-setup/fontsize-fb47 select 8x16
|
||||
console-setup console-setup/store_defaults_in_debconf_db boolean true
|
||||
console-setup console-setup/codeset47 select # Latin1 and Latin5 - western Europe and Turkic languages
|
||||
console-setup console-setup/fontface47 select Fixed
|
||||
console-setup console-setup/fontsize string 8x16
|
||||
console-setup console-setup/charmap47 select UTF-8
|
||||
console-setup console-setup/fontsize-text47 select 8x16
|
||||
console-setup console-setup/codesetcode string Lat15
|
||||
tzdata tzdata/Areas select Europe
|
||||
tzdata tzdata/Zones/Europe select Vienna
|
||||
CONF'
|
||||
|
||||
chroot_execute "dpkg-reconfigure locales -f noninteractive"
|
||||
echo -e "LC_ALL=en_US.UTF-8\nLANG=en_US.UTF-8\n" >> "$c_zfs_mount_dir/etc/environment"
|
||||
chroot_execute "apt install -qq --yes keyboard-configuration console-setup"
|
||||
chroot_execute "dpkg-reconfigure keyboard-configuration -f noninteractive"
|
||||
chroot_execute "dpkg-reconfigure console-setup -f noninteractive"
|
||||
chroot_execute "setupcon"
|
||||
|
||||
chroot_execute "rm -f /etc/localtime /etc/timezone"
|
||||
chroot_execute "dpkg-reconfigure tzdata -f noninteractive"
|
||||
|
||||
echo "======= installing latest kernel============="
|
||||
# linux-headers-generic linux-image-generic
|
||||
chroot_execute "apt install --yes linux-image${v_kernel_variant}-amd64 linux-headers${v_kernel_variant}-amd64 dpkg-dev"
|
||||
|
||||
echo "======= installing aux packages =========="
|
||||
chroot_execute "apt install --yes man wget curl software-properties-common nano htop gnupg"
|
||||
|
||||
echo "======= installing zfs packages =========="
|
||||
chroot_execute 'echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections'
|
||||
|
||||
if [[ $v_zfs_experimental == "1" ]]; then
|
||||
chroot_execute "wget -O - https://terem42.github.io/zfs-debian/apt_pub.gpg | apt-key add -"
|
||||
chroot_execute "add-apt-repository 'deb https://terem42.github.io/zfs-debian/public zfs-debian-experimental main'"
|
||||
chroot_execute "apt update"
|
||||
chroot_execute "apt install -t zfs-debian-experimental --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
else
|
||||
chroot_execute "apt install -t bookworm-backports --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
fi
|
||||
chroot_execute 'cat << DKMS > /etc/dkms/zfs.conf
|
||||
# override for /usr/src/zfs-*/dkms.conf:
|
||||
# always rebuild initrd when zfs module has been changed
|
||||
# (either by a ZFS update or a new kernel version)
|
||||
REMAKE_INITRD="yes"
|
||||
DKMS'
|
||||
|
||||
echo "======= installing OpenSSH and network tooling =========="
|
||||
chroot_execute "apt install --yes openssh-server net-tools"
|
||||
|
||||
echo "======= setup OpenSSH =========="
|
||||
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' "$c_zfs_mount_dir/etc/ssh/sshd_config"
|
||||
sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/g' "$c_zfs_mount_dir/etc/ssh/sshd_config"
|
||||
chroot_execute "rm /etc/ssh/ssh_host_*"
|
||||
chroot_execute "dpkg-reconfigure openssh-server -f noninteractive"
|
||||
|
||||
echo "======= set root password =========="
|
||||
chroot_execute "echo root:$(printf "%q" "$v_root_password") | chpasswd"
|
||||
|
||||
echo "======= setting up zfs cache =========="
|
||||
|
||||
cp /etc/zpool.cache "$c_zfs_mount_dir/etc/zfs/zpool.cache"
|
||||
|
||||
echo "========setting up zfs module parameters========"
|
||||
chroot_execute "echo options zfs zfs_arc_max=$((v_zfs_arc_max_mb * 1024 * 1024)) >> /etc/modprobe.d/zfs.conf"
|
||||
|
||||
echo "======= setting up grub =========="
|
||||
if (( c_efimode_enabled == 1 )); then
|
||||
chroot_execute "apt install --yes grub-efi-amd64"
|
||||
else
|
||||
chroot_execute "echo 'grub-pc grub-pc/install_devices_empty boolean true' | debconf-set-selections"
|
||||
chroot_execute "apt install --yes grub-legacy"
|
||||
chroot_execute "apt install --yes grub-pc"
|
||||
fi
|
||||
|
||||
if (( c_efimode_enabled == 1 )); then
|
||||
#chroot_execute grub-probe /boot
|
||||
chroot_execute grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=debian --recheck
|
||||
else
|
||||
for disk in ${v_selected_disks[@]}; do
|
||||
chroot_execute "grub-install --recheck $disk"
|
||||
done
|
||||
fi
|
||||
|
||||
chroot_execute "sed -i 's/#GRUB_TERMINAL=console/GRUB_TERMINAL=console/g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"net.ifnames=0\"|' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX=\"\"|GRUB_CMDLINE_LINUX=\"root=ZFS=$v_rpool_name/ROOT/debian\"|g' /etc/default/grub"
|
||||
|
||||
chroot_execute "sed -i 's/quiet//g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's/splash//g' /etc/default/grub"
|
||||
chroot_execute "echo 'GRUB_DISABLE_OS_PROBER=true' >> /etc/default/grub"
|
||||
|
||||
for ((i = 1; i < ${#v_selected_disks[@]}; i++)); do
|
||||
dd if="${v_selected_disks[0]}-part1" of="${v_selected_disks[i]}-part1"
|
||||
done
|
||||
|
||||
if [[ $v_encrypt_rpool == "1" ]]; then
|
||||
echo "=========set up dropbear=============="
|
||||
|
||||
chroot_execute "apt install --yes dropbear-initramfs"
|
||||
|
||||
mkdir -p "$c_zfs_mount_dir/etc/dropbear/initramfs"
|
||||
cp /root/.ssh/authorized_keys "$c_zfs_mount_dir/etc/dropbear/initramfs/authorized_keys"
|
||||
|
||||
cp "$c_zfs_mount_dir/etc/ssh/ssh_host_rsa_key" "$c_zfs_mount_dir/etc/ssh/ssh_host_rsa_key_temp"
|
||||
chroot_execute "ssh-keygen -p -i -m pem -N '' -f /etc/ssh/ssh_host_rsa_key_temp"
|
||||
chroot_execute "/usr/lib/dropbear/dropbearconvert openssh dropbear /etc/ssh/ssh_host_rsa_key_temp /etc/dropbear/initramfs/dropbear_rsa_host_key"
|
||||
rm -rf "$c_zfs_mount_dir/etc/ssh/ssh_host_rsa_key_temp"
|
||||
|
||||
cp "$c_zfs_mount_dir/etc/ssh/ssh_host_ecdsa_key" "$c_zfs_mount_dir/etc/ssh/ssh_host_ecdsa_key_temp"
|
||||
chroot_execute "ssh-keygen -p -i -m pem -N '' -f /etc/ssh/ssh_host_ecdsa_key_temp"
|
||||
chroot_execute "/usr/lib/dropbear/dropbearconvert openssh dropbear /etc/ssh/ssh_host_ecdsa_key_temp /etc/dropbear/initramfs/dropbear_ecdsa_host_key"
|
||||
chroot_execute "rm -rf /etc/ssh/ssh_host_ecdsa_key_temp"
|
||||
rm -rf "$c_zfs_mount_dir/etc/ssh/ssh_host_ecdsa_key_temp"
|
||||
|
||||
rm -rf "$c_zfs_mount_dir/etc/dropbear/initramfs/dropbear_dss_host_key"
|
||||
fi
|
||||
|
||||
echo "============setup root prompt============"
|
||||
cat > "$c_zfs_mount_dir/root/.bashrc" <<CONF
|
||||
export PS1='\[\033[01;31m\]\u\[\033[01;33m\]@\[\033[01;32m\]\h \[\033[01;33m\]\w \[\033[01;35m\]\$ \[\033[00m\]'
|
||||
umask 022
|
||||
export LS_OPTIONS='--color=auto -h'
|
||||
eval "\$(dircolors)"
|
||||
CONF
|
||||
|
||||
echo "========= add root pubkey for login via SSH"
|
||||
mkdir -p "$c_zfs_mount_dir/root/.ssh/"
|
||||
cp /root/.ssh/authorized_keys "$c_zfs_mount_dir/root/.ssh/authorized_keys"
|
||||
|
||||
echo "========running packages upgrade and autoremove==========="
|
||||
chroot_execute "apt upgrade --yes"
|
||||
chroot_execute "apt purge cryptsetup* --yes"
|
||||
|
||||
echo "===========add static route to initramfs via hook to add default routes for Hetzner due to Debian/Ubuntu initramfs DHCP bug ========="
|
||||
mkdir -p "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount"
|
||||
cat > "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount/static-route" <<'CONF'
|
||||
#!/bin/sh
|
||||
PREREQ=""
|
||||
prereqs()
|
||||
{
|
||||
echo "$PREREQ"
|
||||
}
|
||||
|
||||
case $1 in
|
||||
prereqs)
|
||||
prereqs
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
. /scripts/functions
|
||||
# Begin real processing below this line
|
||||
|
||||
configure_networking
|
||||
|
||||
ip route add 172.31.1.1/255.255.255.255 dev eth0
|
||||
ip route add default via 172.31.1.1 dev eth0
|
||||
CONF
|
||||
|
||||
chmod 755 "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount/static-route"
|
||||
|
||||
chmod 755 "$c_zfs_mount_dir/etc/network/interfaces"
|
||||
|
||||
echo "======= update initramfs =========="
|
||||
chroot_execute "update-initramfs -u -k all"
|
||||
|
||||
chroot_execute "apt remove cryptsetup* --yes"
|
||||
|
||||
echo "======= update grub =========="
|
||||
chroot_execute "update-grub"
|
||||
|
||||
echo "======= setting up zed =========="
|
||||
if [[ $v_zfs_experimental == "1" ]]; then
|
||||
chroot_execute "zfs set canmount=noauto $v_rpool_name"
|
||||
else
|
||||
initial_load_debian_zed_cache
|
||||
fi
|
||||
|
||||
echo "======= setting mountpoints =========="
|
||||
if (( c_efimode_enabled == 1 )); then
|
||||
umount "$c_zfs_mount_dir/boot/efi"
|
||||
fi
|
||||
|
||||
chroot_execute "zfs set mountpoint=legacy $v_bpool_name/BOOT/debian"
|
||||
chroot_execute "echo $v_bpool_name/BOOT/debian /boot zfs nodev,relatime,x-systemd.requires=zfs-mount.service,x-systemd.device-timeout=10 0 0 > /etc/fstab"
|
||||
|
||||
chroot_execute "zfs set mountpoint=legacy $v_rpool_name/var/log"
|
||||
chroot_execute "echo $v_rpool_name/var/log /var/log zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
chroot_execute "zfs set mountpoint=legacy $v_rpool_name/var/spool"
|
||||
chroot_execute "echo $v_rpool_name/var/spool /var/spool zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
chroot_execute "zfs set mountpoint=legacy $v_rpool_name/var/tmp"
|
||||
chroot_execute "echo $v_rpool_name/var/tmp /var/tmp zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
chroot_execute "zfs set mountpoint=legacy $v_rpool_name/tmp"
|
||||
chroot_execute "echo $v_rpool_name/tmp /tmp zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
|
||||
echo "========= add swap, if defined"
|
||||
if [[ $v_swap_size -gt 0 ]]; then
|
||||
chroot_execute "echo /dev/zvol/$v_rpool_name/swap none swap discard 0 0 >> /etc/fstab"
|
||||
fi
|
||||
|
||||
chroot_execute "echo RESUME=none > /etc/initramfs-tools/conf.d/resume"
|
||||
|
||||
echo "======= unmounting filesystems and zfs pools =========="
|
||||
unmount_and_export_fs
|
||||
|
||||
echo "======== setup complete, rebooting ==============="
|
||||
reboot
|
||||
@@ -17,8 +17,6 @@ set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
export TMPDIR=/tmp
|
||||
|
||||
# Variables
|
||||
v_bpool_name=
|
||||
v_bpool_tweaks=
|
||||
@@ -42,7 +40,7 @@ c_deb_security_repo=http://mirror.hetzner.de/ubuntu/security
|
||||
|
||||
c_default_zfs_arc_max_mb=250
|
||||
c_default_bpool_tweaks="-o ashift=12 -O compression=lz4"
|
||||
c_default_rpool_tweaks="-o ashift=12 -O acltype=posixacl -O compression=zstd-9 -O dnodesize=auto -O relatime=on -O xattr=sa -O normalization=formD"
|
||||
c_default_rpool_tweaks="-o ashift=12 -O acltype=posixacl -O compression=lz4 -O dnodesize=auto -O relatime=on -O xattr=sa -O normalization=formD"
|
||||
c_default_hostname=terem
|
||||
c_zfs_mount_dir=/mnt
|
||||
c_log_dir=$(dirname "$(mktemp)")/zfs-hetzner-vm
|
||||
@@ -64,9 +62,7 @@ function print_step_info_header {
|
||||
###############################################################################
|
||||
# ${FUNCNAME[1]}"
|
||||
|
||||
if [[ "${1:-}" != "" ]]; then
|
||||
echo -n " $1"
|
||||
fi
|
||||
[[ "${1:-}" != "" ]] && echo -n " $1" || true
|
||||
|
||||
echo "
|
||||
###############################################################################
|
||||
@@ -110,7 +106,7 @@ This script will prepare the ZFS pools, then install and configure minimal Ubunt
|
||||
The script with minimal changes may be used on any other hosting provider supporting KVM virtualization and offering Debian-based rescue system.
|
||||
In order to stop the procedure, hit Esc twice during dialogs (excluding yes/no ones), or Ctrl+C while any operation is running.
|
||||
'
|
||||
dialog --msgbox "$dialog_message" 30 100
|
||||
dialog --ascii-lines --msgbox "$dialog_message" 30 100
|
||||
}
|
||||
|
||||
function store_os_distro_information {
|
||||
@@ -179,7 +175,7 @@ LOG
|
||||
|
||||
If you think this is a bug, please open an issue on https://github.com/terem42/zfs-hetzner-vm/issues, and attach the file `'"$c_disks_log"'`.
|
||||
'
|
||||
dialog --msgbox "$dialog_message" 30 100
|
||||
dialog --ascii-lines --msgbox "$dialog_message" 30 100
|
||||
|
||||
exit 1
|
||||
fi
|
||||
@@ -208,7 +204,7 @@ function select_disks {
|
||||
|
||||
Devices with mounted partitions, cdroms, and removable devices are not displayed!
|
||||
"
|
||||
mapfile -t v_selected_disks < <(dialog --separate-output --checklist "$dialog_message" 30 100 $((${#menu_entries_option[@]} / 3)) "${menu_entries_option[@]}" 3>&1 1>&2 2>&3)
|
||||
mapfile -t v_selected_disks < <(dialog --ascii-lines --separate-output --checklist "$dialog_message" 30 100 $((${#menu_entries_option[@]} / 3)) "${menu_entries_option[@]}" 3>&1 1>&2 2>&3)
|
||||
|
||||
if [[ ${#v_selected_disks[@]} -gt 0 ]]; then
|
||||
break
|
||||
@@ -225,7 +221,7 @@ function ask_swap_size {
|
||||
local swap_size_invalid_message=
|
||||
|
||||
while [[ ! $v_swap_size =~ ^[0-9]+$ ]]; do
|
||||
v_swap_size=$(dialog --inputbox "${swap_size_invalid_message}Enter the swap size in GiB (0 for no swap):" 30 100 2 3>&1 1>&2 2>&3)
|
||||
v_swap_size=$(dialog --ascii-lines --inputbox "${swap_size_invalid_message}Enter the swap size in GiB (0 for no swap):" 30 100 2 3>&1 1>&2 2>&3)
|
||||
|
||||
swap_size_invalid_message="Invalid swap size! "
|
||||
done
|
||||
@@ -240,7 +236,7 @@ function ask_free_tail_space {
|
||||
local tail_space_invalid_message=
|
||||
|
||||
while [[ ! $v_free_tail_space =~ ^[0-9]+$ ]]; do
|
||||
v_free_tail_space=$(dialog --inputbox "${tail_space_invalid_message}Enter the space to leave at the end of each disk (0 for none):" 30 100 0 3>&1 1>&2 2>&3)
|
||||
v_free_tail_space=$(dialog --ascii-lines --inputbox "${tail_space_invalid_message}Enter the space to leave at the end of each disk (0 for none):" 30 100 0 3>&1 1>&2 2>&3)
|
||||
|
||||
tail_space_invalid_message="Invalid size! "
|
||||
done
|
||||
@@ -255,7 +251,7 @@ function ask_zfs_arc_max_size {
|
||||
local zfs_arc_max_invalid_message=
|
||||
|
||||
while [[ ! $v_zfs_arc_max_mb =~ ^[0-9]+$ ]]; do
|
||||
v_zfs_arc_max_mb=$(dialog --inputbox "${zfs_arc_max_invalid_message}Enter ZFS ARC cache max size in Mb (minimum 64Mb, enter 0 for ZFS default value, the default will take up to 50% of memory):" 30 100 "$c_default_zfs_arc_max_mb" 3>&1 1>&2 2>&3)
|
||||
v_zfs_arc_max_mb=$(dialog --ascii-lines --inputbox "${zfs_arc_max_invalid_message}Enter ZFS ARC cache max size in Mb (minimum 64Mb, enter 0 for ZFS default value, the default will take up to 50% of memory):" 30 100 "$c_default_zfs_arc_max_mb" 3>&1 1>&2 2>&3)
|
||||
|
||||
zfs_arc_max_invalid_message="Invalid size! "
|
||||
done
|
||||
@@ -271,14 +267,14 @@ function ask_pool_names {
|
||||
local bpool_name_invalid_message=
|
||||
|
||||
while [[ ! $v_bpool_name =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_bpool_name=$(dialog --inputbox "${bpool_name_invalid_message}Insert the name for the boot pool" 30 100 bpool 3>&1 1>&2 2>&3)
|
||||
v_bpool_name=$(dialog --ascii-lines --inputbox "${bpool_name_invalid_message}Insert the name for the boot pool" 30 100 bpool 3>&1 1>&2 2>&3)
|
||||
|
||||
bpool_name_invalid_message="Invalid pool name! "
|
||||
done
|
||||
local rpool_name_invalid_message=
|
||||
|
||||
while [[ ! $v_rpool_name =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_rpool_name=$(dialog --inputbox "${rpool_name_invalid_message}Insert the name for the root pool" 30 100 rpool 3>&1 1>&2 2>&3)
|
||||
v_rpool_name=$(dialog --ascii-lines --inputbox "${rpool_name_invalid_message}Insert the name for the root pool" 30 100 rpool 3>&1 1>&2 2>&3)
|
||||
|
||||
rpool_name_invalid_message="Invalid pool name! "
|
||||
done
|
||||
@@ -290,8 +286,8 @@ function ask_pool_tweaks {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
v_bpool_tweaks=$(dialog --inputbox "Insert the tweaks for the boot pool" 30 100 -- "$c_default_bpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
v_rpool_tweaks=$(dialog --inputbox "Insert the tweaks for the root pool" 30 100 -- "$c_default_rpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
v_bpool_tweaks=$(dialog --ascii-lines --inputbox "Insert the tweaks for the boot pool" 30 100 -- "$c_default_bpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
v_rpool_tweaks=$(dialog --ascii-lines --inputbox "Insert the tweaks for the root pool" 30 100 -- "$c_default_rpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
|
||||
print_variables v_bpool_tweaks v_rpool_tweaks
|
||||
}
|
||||
@@ -306,8 +302,8 @@ function ask_root_password {
|
||||
local password_repeat=-
|
||||
|
||||
while [[ "$v_root_password" != "$password_repeat" || "$v_root_password" == "" ]]; do
|
||||
v_root_password=$(dialog --passwordbox "${password_invalid_message}Please enter the root account password (can't be empty):" 30 100 3>&1 1>&2 2>&3)
|
||||
password_repeat=$(dialog --passwordbox "Please repeat the password:" 30 100 3>&1 1>&2 2>&3)
|
||||
v_root_password=$(dialog --ascii-lines --passwordbox "${password_invalid_message}Please enter the root account password (can't be empty):" 30 100 3>&1 1>&2 2>&3)
|
||||
password_repeat=$(dialog --ascii-lines --passwordbox "Please repeat the password:" 30 100 3>&1 1>&2 2>&3)
|
||||
|
||||
password_invalid_message="Passphrase empty, or not matching! "
|
||||
done
|
||||
@@ -317,7 +313,7 @@ function ask_root_password {
|
||||
function ask_encryption {
|
||||
print_step_info_header
|
||||
|
||||
if dialog --defaultno --yesno 'Do you want to encrypt the root pool?' 30 100; then
|
||||
if dialog --ascii-lines --yesno 'Do you want to encrypt the root pool?' 30 100; then
|
||||
v_encrypt_rpool=1
|
||||
fi
|
||||
set +x
|
||||
@@ -325,8 +321,8 @@ function ask_encryption {
|
||||
local passphrase_invalid_message=
|
||||
local passphrase_repeat=-
|
||||
while [[ "$v_passphrase" != "$passphrase_repeat" || ${#v_passphrase} -lt 8 ]]; do
|
||||
v_passphrase=$(dialog --passwordbox "${passphrase_invalid_message}Please enter the passphrase for the root pool (8 chars min.):" 30 100 3>&1 1>&2 2>&3)
|
||||
passphrase_repeat=$(dialog --passwordbox "Please repeat the passphrase:" 30 100 3>&1 1>&2 2>&3)
|
||||
v_passphrase=$(dialog --ascii-lines --passwordbox "${passphrase_invalid_message}Please enter the passphrase for the root pool (8 chars min.):" 30 100 3>&1 1>&2 2>&3)
|
||||
passphrase_repeat=$(dialog --ascii-lines --passwordbox "Please repeat the passphrase:" 30 100 3>&1 1>&2 2>&3)
|
||||
|
||||
passphrase_invalid_message="Passphrase too short, or not matching! "
|
||||
done
|
||||
@@ -337,7 +333,7 @@ function ask_encryption {
|
||||
function ask_zfs_experimental {
|
||||
print_step_info_header
|
||||
|
||||
if dialog --defaultno --yesno 'Do you want to use experimental zfs module build?' 30 100; then
|
||||
if dialog --ascii-lines --yesno 'Do you want to use experimental zfs module build?' 30 100; then
|
||||
v_zfs_experimental=1
|
||||
fi
|
||||
}
|
||||
@@ -348,8 +344,8 @@ function ask_hostname {
|
||||
|
||||
local hostname_invalid_message=
|
||||
|
||||
while [[ ! $v_hostname =~ ^[a-z][a-zA-Z0-9_:.-]+$ ]]; do
|
||||
v_hostname=$(dialog --inputbox "${hostname_invalid_message}Set the host name" 30 100 "$c_default_hostname" 3>&1 1>&2 2>&3)
|
||||
while [[ ! $v_hostname =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_hostname=$(dialog --ascii-lines --inputbox "${hostname_invalid_message}Set the host name" 30 100 "$c_default_hostname" 3>&1 1>&2 2>&3)
|
||||
|
||||
hostname_invalid_message="Invalid host name! "
|
||||
done
|
||||
@@ -366,7 +362,7 @@ function determine_kernel_variant {
|
||||
}
|
||||
|
||||
function chroot_execute {
|
||||
chroot $c_zfs_mount_dir bash -c "DEBIAN_FRONTEND=noninteractive $1"
|
||||
chroot $c_zfs_mount_dir bash -c "$1"
|
||||
}
|
||||
|
||||
function unmount_and_export_fs {
|
||||
@@ -403,8 +399,8 @@ function unmount_and_export_fs {
|
||||
echo "===========exporting zfs pools============="
|
||||
set +e
|
||||
while (( zpools_exported == 99 )) && (( SECONDS++ <= 60 )); do
|
||||
|
||||
if zpool export -a 2> /dev/null; then
|
||||
zpool export -a 2> /dev/null
|
||||
if [[ $? == 0 ]]; then
|
||||
zpools_exported=1
|
||||
echo "all zfs pools were succesfully exported"
|
||||
break;
|
||||
@@ -421,7 +417,6 @@ function unmount_and_export_fs {
|
||||
|
||||
#################### MAIN ################################
|
||||
export LC_ALL=en_US.UTF-8
|
||||
export NCURSES_NO_UTF8_ACS=1
|
||||
|
||||
check_prerequisites
|
||||
|
||||
@@ -462,20 +457,11 @@ for kver in $(find /lib/modules/* -maxdepth 0 -type d | grep -v "$(uname -r)" |
|
||||
done
|
||||
|
||||
echo "======= installing zfs on rescue system =========="
|
||||
echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections
|
||||
# echo "y" | zfs
|
||||
# linux-headers-generic linux-image-generic
|
||||
apt install --yes software-properties-common dpkg-dev dkms
|
||||
rm -f "$(which zfs)"
|
||||
rm -f "$(which zpool)"
|
||||
echo -e "deb http://deb.debian.org/debian/ testing main contrib non-free\ndeb http://deb.debian.org/debian/ testing main contrib non-free\n" >/etc/apt/sources.list.d/bookworm-testing.list
|
||||
echo -e "Package: src:zfs-linux\nPin: release n=testing\nPin-Priority: 990\n" > /etc/apt/preferences.d/90_zfs
|
||||
apt update
|
||||
apt install -t testing --yes zfs-dkms zfsutils-linux
|
||||
rm /etc/apt/sources.list.d/bookworm-testing.list
|
||||
rm /etc/apt/preferences.d/90_zfs
|
||||
echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections
|
||||
|
||||
apt update
|
||||
export PATH=$PATH:/usr/sbin
|
||||
apt install --yes -t buster-backports libelf-dev zfs-dkms
|
||||
modprobe zfs
|
||||
zfs --version
|
||||
|
||||
echo "======= partitioning the disk =========="
|
||||
@@ -487,9 +473,9 @@ echo "======= partitioning the disk =========="
|
||||
fi
|
||||
|
||||
for selected_disk in "${v_selected_disks[@]}"; do
|
||||
wipefs --all --force "$selected_disk"
|
||||
wipefs --all "$selected_disk"
|
||||
sgdisk -a1 -n1:24K:+1000K -t1:EF02 "$selected_disk"
|
||||
sgdisk -n2:0:+2G -t2:BF01 "$selected_disk" # Boot pool
|
||||
sgdisk -n2:0:+512M -t2:BF01 "$selected_disk" # Boot pool
|
||||
sgdisk -n3:0:"$tail_space_parameter" -t3:BF01 "$selected_disk" # Root pool
|
||||
done
|
||||
|
||||
@@ -516,17 +502,13 @@ echo "======= create zfs pools and datasets =========="
|
||||
pools_mirror_option=
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
zpool create \
|
||||
$v_bpool_tweaks -O canmount=off -O devices=off \
|
||||
-o cachefile=/etc/zpool.cache \
|
||||
-O mountpoint=/boot -R $c_zfs_mount_dir -f \
|
||||
$v_bpool_name $pools_mirror_option "${bpool_disks_partitions[@]}"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
echo -n "$v_passphrase" | zpool create \
|
||||
$v_rpool_tweaks \
|
||||
-o cachefile=/etc/zpool.cache \
|
||||
"${encryption_options[@]}" \
|
||||
-O mountpoint=/ -R $c_zfs_mount_dir -f \
|
||||
$v_rpool_name $pools_mirror_option "${rpool_disks_partitions[@]}"
|
||||
@@ -541,7 +523,9 @@ zfs create -o canmount=noauto -o mountpoint=/boot "$v_bpool_name/BOOT/ubuntu"
|
||||
zfs mount "$v_bpool_name/BOOT/ubuntu"
|
||||
|
||||
zfs create "$v_rpool_name/home"
|
||||
zfs create -o mountpoint=/root "$v_rpool_name/home/root"
|
||||
zfs create -o canmount=off "$v_rpool_name/var"
|
||||
zfs create -o canmount=off "$v_rpool_name/var/lib"
|
||||
zfs create "$v_rpool_name/var/log"
|
||||
zfs create "$v_rpool_name/var/spool"
|
||||
|
||||
@@ -592,7 +576,7 @@ ff02::2 ip6-allrouters
|
||||
ff02::3 ip6-allhosts
|
||||
CONF
|
||||
|
||||
ip6addr_prefix=$(ip -6 a s | grep -E "inet6.+global" | sed -nE 's/.+inet6\s(([0-9a-z]{1,4}:){4,4}).+/\1/p' | head -n 1)
|
||||
ip6addr_prefix=$(ip -6 a s | grep -E "inet6.+global" | sed -nE 's/.+inet6\s(([0-9a-z]{1,4}:){4,4}).+/\1/p')
|
||||
|
||||
cat <<CONF > /mnt/etc/systemd/network/10-eth0.network
|
||||
[Match]
|
||||
@@ -605,9 +589,7 @@ Gateway=fe80::1
|
||||
CONF
|
||||
|
||||
chroot_execute "systemctl enable systemd-networkd.service"
|
||||
chroot_execute "systemctl enable systemd-resolved.service"
|
||||
|
||||
#cp /etc/resolv.conf $c_zfs_mount_dir/etc/resolv.conf
|
||||
|
||||
mkdir -p "$c_zfs_mount_dir/etc/cloud/cloud.cfg.d/"
|
||||
cat > "$c_zfs_mount_dir/etc/cloud/cloud.cfg.d/99-disable-network-config.cfg" <<CONF
|
||||
@@ -617,6 +599,7 @@ CONF
|
||||
|
||||
rm -rf $c_zfs_mount_dir/etc/network/interfaces.d/50-cloud-init.cfg
|
||||
|
||||
cp /etc/resolv.conf $c_zfs_mount_dir/etc/resolv.conf
|
||||
|
||||
echo "======= preparing the jail for chroot =========="
|
||||
for virtual_fs_dir in proc sys dev; do
|
||||
@@ -635,7 +618,7 @@ CONF
|
||||
chroot_execute "apt update"
|
||||
|
||||
echo "======= setting locale, console and language =========="
|
||||
chroot_execute "apt install --yes -qq locales debconf-i18n apt-utils keyboard-configuration console-setup"
|
||||
chroot_execute "apt install --yes -qq locales debconf-i18n apt-utils"
|
||||
sed -i 's/# en_US.UTF-8/en_US.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
sed -i 's/# fr_FR.UTF-8/fr_FR.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
sed -i 's/# fr_FR.UTF-8/fr_FR.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
@@ -677,6 +660,7 @@ CONF'
|
||||
|
||||
chroot_execute "dpkg-reconfigure locales -f noninteractive"
|
||||
echo -e "LC_ALL=en_US.UTF-8\nLANG=en_US.UTF-8\n" >> "$c_zfs_mount_dir/etc/environment"
|
||||
chroot_execute "apt install -qq --yes keyboard-configuration console-setup"
|
||||
chroot_execute "dpkg-reconfigure keyboard-configuration -f noninteractive"
|
||||
chroot_execute "dpkg-reconfigure console-setup -f noninteractive"
|
||||
chroot_execute "setupcon"
|
||||
@@ -685,35 +669,32 @@ chroot_execute "rm -f /etc/localtime /etc/timezone"
|
||||
chroot_execute "dpkg-reconfigure tzdata -f noninteractive "
|
||||
|
||||
echo "======= installing latest kernel============="
|
||||
chroot_execute "apt install --yes linux-headers${v_kernel_variant}-hwe-18.04 linux-image${v_kernel_variant}-hwe-18.04"
|
||||
chroot_execute "DEBIAN_FRONTEND=noninteractive apt install --yes linux-headers${v_kernel_variant}-hwe-18.04 linux-image${v_kernel_variant}-hwe-18.04"
|
||||
if [[ $v_kernel_variant == "-virtual" ]]; then
|
||||
# linux-image-extra is only available for virtual hosts
|
||||
chroot_execute "apt install --yes linux-image-extra-virtual-hwe-18.04"
|
||||
chroot_execute "DEBIAN_FRONTEND=noninteractive apt install --yes linux-image-extra-virtual-hwe-18.04"
|
||||
fi
|
||||
|
||||
|
||||
echo "======= installing aux packages =========="
|
||||
chroot_execute "apt install --yes man wget curl software-properties-common nano htop gnupg"
|
||||
chroot_execute "systemctl disable thermald"
|
||||
|
||||
echo "======= installing zfs packages =========="
|
||||
chroot_execute 'echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections'
|
||||
|
||||
if [[ $v_zfs_experimental == "1" ]]; then
|
||||
chroot_execute "wget -O - https://terem42.github.io/zfs-debian/apt_pub.gpg | apt-key add -"
|
||||
chroot_execute "add-apt-repository 'deb https://terem42.github.io/zfs-debian/public zfs-debian-experimental main'"
|
||||
chroot_execute "apt update"
|
||||
chroot_execute "apt install -t zfs-debian-experimental --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
else
|
||||
chroot_execute "add-apt-repository --yes ppa:jonathonf/zfs"
|
||||
fi
|
||||
chroot_execute 'echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections'
|
||||
|
||||
if [[ $v_zfs_experimental == "1" ]]; then
|
||||
chroot_execute "apt install -t zfs-debian-experimental --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
else
|
||||
chroot_execute "apt install --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
fi
|
||||
chroot_execute 'cat << DKMS > /etc/dkms/zfs.conf
|
||||
# override for /usr/src/zfs-*/dkms.conf:
|
||||
# always rebuild initrd when zfs module has been changed
|
||||
# (either by a ZFS update or a new kernel version)
|
||||
REMAKE_INITRD="yes"
|
||||
DKMS'
|
||||
|
||||
echo "======= installing OpenSSH and network tooling =========="
|
||||
chroot_execute "apt install --yes openssh-server net-tools"
|
||||
|
||||
@@ -728,22 +709,37 @@ chroot_execute "dpkg-reconfigure openssh-server -f noninteractive"
|
||||
echo "======= set root password =========="
|
||||
chroot_execute "echo root:$(printf "%q" "$v_root_password") | chpasswd"
|
||||
|
||||
echo "======= setting up zfs cache =========="
|
||||
cp /etc/zpool.cache /mnt/etc/zfs/zpool.cache
|
||||
echo "======= setting up zfs services =========="
|
||||
chroot_execute "cat > /etc/systemd/system/zfs-import-bpool.service <<UNIT
|
||||
[Unit]
|
||||
DefaultDependencies=no
|
||||
Before=zfs-import-scan.service
|
||||
Before=zfs-import-cache.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStartPre=/bin/sh -c '[ -f /etc/zfs/zpool.cache ] && mv /etc/zfs/zpool.cache /etc/zfs/preboot_zpool.cache || true'
|
||||
ExecStart=/sbin/zpool import -N -o cachefile=none $v_bpool_name
|
||||
ExecStartPost=/bin/sh -c '[ -f /etc/zfs/preboot_zpool.cache ] && mv /etc/zfs/preboot_zpool.cache /etc/zfs/zpool.cache || true'
|
||||
|
||||
[Install]
|
||||
WantedBy=zfs-import.target
|
||||
UNIT"
|
||||
|
||||
chroot_execute "systemctl enable zfs-import-bpool.service"
|
||||
|
||||
echo "========setting up zfs module parameters========"
|
||||
chroot_execute "echo options zfs zfs_arc_max=$((v_zfs_arc_max_mb * 1024 * 1024)) >> /etc/modprobe.d/zfs.conf"
|
||||
|
||||
echo "======= setting up grub =========="
|
||||
chroot_execute "echo 'grub-pc grub-pc/install_devices_empty boolean true' | debconf-set-selections"
|
||||
chroot_execute "apt install --yes grub-pc"
|
||||
for disk in ${v_selected_disks[@]}; do
|
||||
chroot_execute "grub-install $disk"
|
||||
done
|
||||
chroot_execute "DEBIAN_FRONTEND=noninteractive apt install --yes grub-pc"
|
||||
chroot_execute "grub-install ${v_selected_disks[0]}"
|
||||
|
||||
chroot_execute "sed -i 's/#GRUB_TERMINAL=console/GRUB_TERMINAL=console/g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"net.ifnames=0\"|' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX=\"\"|GRUB_CMDLINE_LINUX=\"root=ZFS=$v_rpool_name/ROOT/ubuntu\"|g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX=\"\"|GRUB_CMDLINE_LINUX=\"root=ZFS=rpool/ROOT/ubuntu\"|g' /etc/default/grub"
|
||||
|
||||
chroot_execute "sed -i 's/quiet//g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's/splash//g' /etc/default/grub"
|
||||
@@ -771,6 +767,18 @@ if [[ $v_encrypt_rpool == "1" ]]; then
|
||||
rm -rf "$c_zfs_mount_dir/etc/ssh/ssh_host_ecdsa_key_temp"
|
||||
|
||||
rm -rf "$c_zfs_mount_dir/etc/dropbear-initramfs/dropbear_dss_host_key"
|
||||
|
||||
cd "$c_zfs_mount_dir/root"
|
||||
wget http://ftp.de.debian.org/debian/pool/main/libt/libtommath/libtommath1_1.1.0-3_amd64.deb
|
||||
wget http://ftp.de.debian.org/debian/pool/main/d/dropbear/dropbear-bin_2018.76-5_amd64.deb
|
||||
wget http://ftp.de.debian.org/debian/pool/main/d/dropbear/dropbear-initramfs_2018.76-5_all.deb
|
||||
|
||||
chroot_execute "dpkg -i /root/libtommath1_1.1.0-3_amd64.deb"
|
||||
chroot_execute "dpkg -i /root/dropbear-bin_2018.76-5_amd64.deb"
|
||||
chroot_execute "dpkg -i /root/dropbear-initramfs_2018.76-5_all.deb"
|
||||
|
||||
rm $c_zfs_mount_dir/root/*.deb
|
||||
cd /root
|
||||
fi
|
||||
|
||||
echo "============setup root prompt============"
|
||||
@@ -783,7 +791,6 @@ CONF
|
||||
|
||||
echo "========running packages upgrade==========="
|
||||
chroot_execute "apt upgrade --yes"
|
||||
chroot_execute "apt purge cryptsetup* --yes"
|
||||
|
||||
echo "===========add static route to initramfs via hook to add default routes due to Ubuntu initramfs DHCP bug ========="
|
||||
mkdir -p "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount"
|
||||
@@ -807,8 +814,8 @@ esac
|
||||
|
||||
configure_networking
|
||||
|
||||
ip route add 172.31.1.1/255.255.255.255 dev eth0
|
||||
ip route add default via 172.31.1.1 dev eth0
|
||||
ip route add 172.31.1.1/255.255.255.255 dev ens3
|
||||
ip route add default via 172.31.1.1 dev ens3
|
||||
CONF
|
||||
|
||||
chmod 755 "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount/static-route"
|
||||
@@ -821,11 +828,11 @@ chroot_execute "update-grub"
|
||||
|
||||
echo "======= setting up zed =========="
|
||||
|
||||
chroot_execute "zfs set canmount=noauto $v_rpool_name"
|
||||
chroot_execute "zfs set canmount=noauto rpool"
|
||||
|
||||
echo "======= setting mountpoints =========="
|
||||
chroot_execute "zfs set mountpoint=legacy $v_bpool_name/BOOT/ubuntu"
|
||||
chroot_execute "echo $v_bpool_name/BOOT/ubuntu /boot zfs nodev,relatime,x-systemd.requires=zfs-mount.service,x-systemd.device-timeout=10 0 0 > /etc/fstab"
|
||||
chroot_execute "echo $v_bpool_name/BOOT/ubuntu /boot zfs nodev,relatime,x-systemd.requires=zfs-import-bpool.service 0 0 > /etc/fstab"
|
||||
|
||||
chroot_execute "zfs set mountpoint=legacy $v_rpool_name/var/log"
|
||||
chroot_execute "echo $v_rpool_name/var/log /var/log zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
@@ -837,10 +844,7 @@ chroot_execute "zfs set mountpoint=legacy $v_rpool_name/tmp"
|
||||
chroot_execute "echo $v_rpool_name/tmp /tmp zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
|
||||
echo "========= add swap, if defined"
|
||||
if [[ $v_swap_size -gt 0 ]]; then
|
||||
chroot_execute "echo /dev/zvol/$v_rpool_name/swap none swap discard 0 0 >> /etc/fstab"
|
||||
fi
|
||||
|
||||
[[ $v_swap_size -gt 0 ]] && chroot_execute "echo /dev/zvol/$v_rpool_name/swap none swap discard 0 0 >> /etc/fstab" || true
|
||||
chroot_execute "echo RESUME=none > /etc/initramfs-tools/conf.d/resume"
|
||||
|
||||
echo "======= unmounting filesystems and zfs pools =========="
|
||||
|
||||
@@ -1,852 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
: <<'end_header_info'
|
||||
(c) Andrey Prokopenko job@terem.fr
|
||||
fully automatic script to install Ubuntu 20 LTS with ZFS root on Hetzner VPS
|
||||
WARNING: all data on the disk will be destroyed
|
||||
How to use: add SSH key to the rescue console, set it OS to linux64, then press "mount rescue and power cycle" button
|
||||
Next, connect via SSH to console, and run the script
|
||||
Answer script questions about desired hostname and ZFS ARC cache size
|
||||
To cope with network failures its higly recommended to run the script inside screen console
|
||||
screen -dmS zfs
|
||||
screen -r zfs
|
||||
To detach from screen console, hit Ctrl-d then a
|
||||
end_header_info
|
||||
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
export TMPDIR=/tmp
|
||||
|
||||
# Variables
|
||||
v_bpool_name=
|
||||
v_bpool_tweaks=
|
||||
v_rpool_name=
|
||||
v_rpool_tweaks=
|
||||
declare -a v_selected_disks
|
||||
v_swap_size= # integer
|
||||
v_free_tail_space= # integer
|
||||
v_hostname=
|
||||
v_kernel_variant=
|
||||
v_zfs_arc_max_mb=
|
||||
v_root_password=
|
||||
v_encrypt_rpool= # 0=false, 1=true
|
||||
v_passphrase=
|
||||
v_zfs_experimental=
|
||||
v_suitable_disks=()
|
||||
|
||||
# Constants
|
||||
c_deb_packages_repo=http://mirror.hetzner.de/ubuntu/packages
|
||||
c_deb_security_repo=http://mirror.hetzner.de/ubuntu/security
|
||||
|
||||
c_default_zfs_arc_max_mb=250
|
||||
c_default_bpool_tweaks="-o ashift=12 -O compression=lz4"
|
||||
c_default_rpool_tweaks="-o ashift=12 -O acltype=posixacl -O compression=zstd-9 -O dnodesize=auto -O relatime=on -O xattr=sa -O normalization=formD"
|
||||
c_default_hostname=terem
|
||||
c_zfs_mount_dir=/mnt
|
||||
c_log_dir=$(dirname "$(mktemp)")/zfs-hetzner-vm
|
||||
c_install_log=$c_log_dir/install.log
|
||||
c_lsb_release_log=$c_log_dir/lsb_release.log
|
||||
c_disks_log=$c_log_dir/disks.log
|
||||
|
||||
function activate_debug {
|
||||
mkdir -p "$c_log_dir"
|
||||
|
||||
exec 5> "$c_install_log"
|
||||
BASH_XTRACEFD="5"
|
||||
set -x
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2120
|
||||
function print_step_info_header {
|
||||
echo -n "
|
||||
###############################################################################
|
||||
# ${FUNCNAME[1]}"
|
||||
|
||||
if [[ "${1:-}" != "" ]]; then
|
||||
echo -n " $1"
|
||||
fi
|
||||
|
||||
echo "
|
||||
###############################################################################
|
||||
"
|
||||
}
|
||||
|
||||
function print_variables {
|
||||
for variable_name in "$@"; do
|
||||
declare -n variable_reference="$variable_name"
|
||||
|
||||
echo -n "$variable_name:"
|
||||
|
||||
case "$(declare -p "$variable_name")" in
|
||||
"declare -a"* )
|
||||
for entry in "${variable_reference[@]}"; do
|
||||
echo -n " \"$entry\""
|
||||
done
|
||||
;;
|
||||
"declare -A"* )
|
||||
for key in "${!variable_reference[@]}"; do
|
||||
echo -n " $key=\"${variable_reference[$key]}\""
|
||||
done
|
||||
;;
|
||||
* )
|
||||
echo -n " $variable_reference"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo
|
||||
done
|
||||
|
||||
echo
|
||||
}
|
||||
|
||||
function display_intro_banner {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
local dialog_message='Hello!
|
||||
This script will prepare the ZFS pools, then install and configure minimal Ubuntu 20 LTS with ZFS root on Hetzner hosting VPS instance
|
||||
The script with minimal changes may be used on any other hosting provider supporting KVM virtualization and offering Debian-based rescue system.
|
||||
In order to stop the procedure, hit Esc twice during dialogs (excluding yes/no ones), or Ctrl+C while any operation is running.
|
||||
'
|
||||
dialog --msgbox "$dialog_message" 30 100
|
||||
}
|
||||
|
||||
function store_os_distro_information {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
lsb_release --all > "$c_lsb_release_log"
|
||||
}
|
||||
|
||||
function check_prerequisites {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
if [[ $(id -u) -ne 0 ]]; then
|
||||
echo 'This script must be run with administrative privileges!'
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -r /root/.ssh/authorized_keys ]]; then
|
||||
echo "SSH pubkey file is absent, please add it to the rescue system setting, then reboot into rescue system and run the script"
|
||||
exit 1
|
||||
fi
|
||||
if ! dpkg-query --showformat="\${Status}" -W dialog 2> /dev/null | grep -q "install ok installed"; then
|
||||
apt install --yes dialog
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
function find_suitable_disks {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
udevadm trigger
|
||||
|
||||
# shellcheck disable=SC2012
|
||||
ls -l /dev/disk/by-id | tail -n +2 | perl -lane 'print "@F[8..10]"' > "$c_disks_log"
|
||||
|
||||
local candidate_disk_ids
|
||||
local mounted_devices
|
||||
|
||||
candidate_disk_ids=$(find /dev/disk/by-id -regextype awk -regex '.+/(ata|nvme|scsi)-.+' -not -regex '.+-part[0-9]+$' | sort)
|
||||
mounted_devices="$(df | awk 'BEGIN {getline} {print $1}' | xargs -n 1 lsblk -no pkname 2> /dev/null | sort -u || true)"
|
||||
|
||||
while read -r disk_id || [[ -n "$disk_id" ]]; do
|
||||
local device_info
|
||||
|
||||
device_info="$(udevadm info --query=property "$(readlink -f "$disk_id")")"
|
||||
block_device_basename="$(basename "$(readlink -f "$disk_id")")"
|
||||
|
||||
if ! grep -q '^ID_TYPE=cd$' <<< "$device_info"; then
|
||||
if ! grep -q "^$block_device_basename\$" <<< "$mounted_devices"; then
|
||||
v_suitable_disks+=("$disk_id")
|
||||
fi
|
||||
fi
|
||||
|
||||
cat >> "$c_disks_log" << LOG
|
||||
|
||||
## DEVICE: $disk_id ################################
|
||||
|
||||
$(udevadm info --query=property "$(readlink -f "$disk_id")")
|
||||
|
||||
LOG
|
||||
|
||||
done < <(echo -n "$candidate_disk_ids")
|
||||
|
||||
if [[ ${#v_suitable_disks[@]} -eq 0 ]]; then
|
||||
local dialog_message='No suitable disks have been found!
|
||||
|
||||
If you think this is a bug, please open an issue on https://github.com/terem42/zfs-hetzner-vm/issues, and attach the file `'"$c_disks_log"'`.
|
||||
'
|
||||
dialog --msgbox "$dialog_message" 30 100
|
||||
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_variables v_suitable_disks
|
||||
}
|
||||
|
||||
function select_disks {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
while true; do
|
||||
local menu_entries_option=()
|
||||
|
||||
if [[ ${#v_suitable_disks[@]} -eq 1 ]]; then
|
||||
local disk_selection_status=ON
|
||||
else
|
||||
local disk_selection_status=OFF
|
||||
fi
|
||||
|
||||
for disk_id in "${v_suitable_disks[@]}"; do
|
||||
menu_entries_option+=("$disk_id" "($block_device_basename)" "$disk_selection_status")
|
||||
done
|
||||
|
||||
local dialog_message="Select the ZFS devices (multiple selections will be in mirror).
|
||||
|
||||
Devices with mounted partitions, cdroms, and removable devices are not displayed!
|
||||
"
|
||||
mapfile -t v_selected_disks < <(dialog --separate-output --checklist "$dialog_message" 30 100 $((${#menu_entries_option[@]} / 3)) "${menu_entries_option[@]}" 3>&1 1>&2 2>&3)
|
||||
|
||||
if [[ ${#v_selected_disks[@]} -gt 0 ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
print_variables v_selected_disks
|
||||
}
|
||||
|
||||
function ask_swap_size {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
local swap_size_invalid_message=
|
||||
|
||||
while [[ ! $v_swap_size =~ ^[0-9]+$ ]]; do
|
||||
v_swap_size=$(dialog --inputbox "${swap_size_invalid_message}Enter the swap size in GiB (0 for no swap):" 30 100 2 3>&1 1>&2 2>&3)
|
||||
|
||||
swap_size_invalid_message="Invalid swap size! "
|
||||
done
|
||||
|
||||
print_variables v_swap_size
|
||||
}
|
||||
|
||||
function ask_free_tail_space {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
local tail_space_invalid_message=
|
||||
|
||||
while [[ ! $v_free_tail_space =~ ^[0-9]+$ ]]; do
|
||||
v_free_tail_space=$(dialog --inputbox "${tail_space_invalid_message}Enter the space to leave at the end of each disk (0 for none):" 30 100 0 3>&1 1>&2 2>&3)
|
||||
|
||||
tail_space_invalid_message="Invalid size! "
|
||||
done
|
||||
|
||||
print_variables v_free_tail_space
|
||||
}
|
||||
|
||||
function ask_zfs_arc_max_size {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
local zfs_arc_max_invalid_message=
|
||||
|
||||
while [[ ! $v_zfs_arc_max_mb =~ ^[0-9]+$ ]]; do
|
||||
v_zfs_arc_max_mb=$(dialog --inputbox "${zfs_arc_max_invalid_message}Enter ZFS ARC cache max size in Mb (minimum 64Mb, enter 0 for ZFS default value, the default will take up to 50% of memory):" 30 100 "$c_default_zfs_arc_max_mb" 3>&1 1>&2 2>&3)
|
||||
|
||||
zfs_arc_max_invalid_message="Invalid size! "
|
||||
done
|
||||
|
||||
print_variables v_zfs_arc_max_mb
|
||||
}
|
||||
|
||||
|
||||
function ask_pool_names {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
local bpool_name_invalid_message=
|
||||
|
||||
while [[ ! $v_bpool_name =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_bpool_name=$(dialog --inputbox "${bpool_name_invalid_message}Insert the name for the boot pool" 30 100 bpool 3>&1 1>&2 2>&3)
|
||||
|
||||
bpool_name_invalid_message="Invalid pool name! "
|
||||
done
|
||||
local rpool_name_invalid_message=
|
||||
|
||||
while [[ ! $v_rpool_name =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_rpool_name=$(dialog --inputbox "${rpool_name_invalid_message}Insert the name for the root pool" 30 100 rpool 3>&1 1>&2 2>&3)
|
||||
|
||||
rpool_name_invalid_message="Invalid pool name! "
|
||||
done
|
||||
|
||||
print_variables v_bpool_name v_rpool_name
|
||||
}
|
||||
|
||||
function ask_pool_tweaks {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
v_bpool_tweaks=$(dialog --inputbox "Insert the tweaks for the boot pool" 30 100 -- "$c_default_bpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
v_rpool_tweaks=$(dialog --inputbox "Insert the tweaks for the root pool" 30 100 -- "$c_default_rpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
|
||||
print_variables v_bpool_tweaks v_rpool_tweaks
|
||||
}
|
||||
|
||||
|
||||
function ask_root_password {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
set +x
|
||||
local password_invalid_message=
|
||||
local password_repeat=-
|
||||
|
||||
while [[ "$v_root_password" != "$password_repeat" || "$v_root_password" == "" ]]; do
|
||||
v_root_password=$(dialog --passwordbox "${password_invalid_message}Please enter the root account password (can't be empty):" 30 100 3>&1 1>&2 2>&3)
|
||||
password_repeat=$(dialog --passwordbox "Please repeat the password:" 30 100 3>&1 1>&2 2>&3)
|
||||
|
||||
password_invalid_message="Passphrase empty, or not matching! "
|
||||
done
|
||||
set -x
|
||||
}
|
||||
|
||||
function ask_encryption {
|
||||
print_step_info_header
|
||||
|
||||
if dialog --defaultno --yesno 'Do you want to encrypt the root pool?' 30 100; then
|
||||
v_encrypt_rpool=1
|
||||
fi
|
||||
set +x
|
||||
if [[ $v_encrypt_rpool == "1" ]]; then
|
||||
local passphrase_invalid_message=
|
||||
local passphrase_repeat=-
|
||||
while [[ "$v_passphrase" != "$passphrase_repeat" || ${#v_passphrase} -lt 8 ]]; do
|
||||
v_passphrase=$(dialog --passwordbox "${passphrase_invalid_message}Please enter the passphrase for the root pool (8 chars min.):" 30 100 3>&1 1>&2 2>&3)
|
||||
passphrase_repeat=$(dialog --passwordbox "Please repeat the passphrase:" 30 100 3>&1 1>&2 2>&3)
|
||||
|
||||
passphrase_invalid_message="Passphrase too short, or not matching! "
|
||||
done
|
||||
fi
|
||||
set -x
|
||||
}
|
||||
|
||||
function ask_zfs_experimental {
|
||||
print_step_info_header
|
||||
|
||||
if dialog --defaultno --yesno 'Do you want to use experimental zfs module build?' 30 100; then
|
||||
v_zfs_experimental=1
|
||||
fi
|
||||
}
|
||||
|
||||
function ask_hostname {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
local hostname_invalid_message=
|
||||
|
||||
while [[ ! $v_hostname =~ ^[a-z][a-zA-Z0-9_:.-]+$ ]]; do
|
||||
v_hostname=$(dialog --inputbox "${hostname_invalid_message}Set the host name" 30 100 "$c_default_hostname" 3>&1 1>&2 2>&3)
|
||||
|
||||
hostname_invalid_message="Invalid host name! "
|
||||
done
|
||||
|
||||
print_variables v_hostname
|
||||
}
|
||||
|
||||
function determine_kernel_variant {
|
||||
if dmidecode | grep -q vServer; then
|
||||
v_kernel_variant="-virtual"
|
||||
else
|
||||
v_kernel_variant="-generic"
|
||||
fi
|
||||
}
|
||||
|
||||
function chroot_execute {
|
||||
chroot $c_zfs_mount_dir bash -c "DEBIAN_FRONTEND=noninteractive $1"
|
||||
}
|
||||
|
||||
function unmount_and_export_fs {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
for virtual_fs_dir in dev sys proc; do
|
||||
umount --recursive --force --lazy "$c_zfs_mount_dir/$virtual_fs_dir"
|
||||
done
|
||||
|
||||
local max_unmount_wait=5
|
||||
echo -n "Waiting for virtual filesystems to unmount "
|
||||
|
||||
SECONDS=0
|
||||
|
||||
for virtual_fs_dir in dev sys proc; do
|
||||
while mountpoint -q "$c_zfs_mount_dir/$virtual_fs_dir" && [[ $SECONDS -lt $max_unmount_wait ]]; do
|
||||
sleep 0.5
|
||||
echo -n .
|
||||
done
|
||||
done
|
||||
|
||||
echo
|
||||
|
||||
for virtual_fs_dir in dev sys proc; do
|
||||
if mountpoint -q "$c_zfs_mount_dir/$virtual_fs_dir"; then
|
||||
echo "Re-issuing umount for $c_zfs_mount_dir/$virtual_fs_dir"
|
||||
umount --recursive --force --lazy "$c_zfs_mount_dir/$virtual_fs_dir"
|
||||
fi
|
||||
done
|
||||
|
||||
SECONDS=0
|
||||
zpools_exported=99
|
||||
echo "===========exporting zfs pools============="
|
||||
set +e
|
||||
while (( zpools_exported == 99 )) && (( SECONDS++ <= 60 )); do
|
||||
|
||||
if zpool export -a 2> /dev/null; then
|
||||
zpools_exported=1
|
||||
echo "all zfs pools were succesfully exported"
|
||||
break;
|
||||
else
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
set -e
|
||||
if (( zpools_exported != 1 )); then
|
||||
echo "failed to export zfs pools"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
#################### MAIN ################################
|
||||
export LC_ALL=en_US.UTF-8
|
||||
export NCURSES_NO_UTF8_ACS=1
|
||||
|
||||
check_prerequisites
|
||||
|
||||
display_intro_banner
|
||||
|
||||
activate_debug
|
||||
|
||||
find_suitable_disks
|
||||
|
||||
select_disks
|
||||
|
||||
ask_swap_size
|
||||
|
||||
ask_free_tail_space
|
||||
|
||||
ask_pool_names
|
||||
|
||||
ask_pool_tweaks
|
||||
|
||||
ask_encryption
|
||||
|
||||
ask_zfs_arc_max_size
|
||||
|
||||
ask_zfs_experimental
|
||||
|
||||
ask_root_password
|
||||
|
||||
ask_hostname
|
||||
|
||||
determine_kernel_variant
|
||||
|
||||
clear
|
||||
|
||||
echo "===========remove unused kernels in rescue system========="
|
||||
for kver in $(find /lib/modules/* -maxdepth 0 -type d | grep -v "$(uname -r)" | cut -s -d "/" -f 4); do
|
||||
apt purge --yes "linux-headers-$kver"
|
||||
apt purge --yes "linux-image-$kver"
|
||||
done
|
||||
|
||||
echo "======= installing zfs on rescue system =========="
|
||||
echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections
|
||||
# echo "y" | zfs
|
||||
# linux-headers-generic linux-image-generic
|
||||
apt install --yes software-properties-common dpkg-dev dkms
|
||||
rm -f "$(which zfs)"
|
||||
rm -f "$(which zpool)"
|
||||
echo -e "deb http://deb.debian.org/debian/ testing main contrib non-free\ndeb http://deb.debian.org/debian/ testing main contrib non-free\n" >/etc/apt/sources.list.d/bookworm-testing.list
|
||||
echo -e "Package: src:zfs-linux\nPin: release n=testing\nPin-Priority: 990\n" > /etc/apt/preferences.d/90_zfs
|
||||
apt update
|
||||
apt install -t testing --yes zfs-dkms zfsutils-linux
|
||||
rm /etc/apt/sources.list.d/bookworm-testing.list
|
||||
rm /etc/apt/preferences.d/90_zfs
|
||||
apt update
|
||||
export PATH=$PATH:/usr/sbin
|
||||
zfs --version
|
||||
|
||||
echo "======= partitioning the disk =========="
|
||||
|
||||
if [[ $v_free_tail_space -eq 0 ]]; then
|
||||
tail_space_parameter=0
|
||||
else
|
||||
tail_space_parameter="-${v_free_tail_space}G"
|
||||
fi
|
||||
|
||||
for selected_disk in "${v_selected_disks[@]}"; do
|
||||
wipefs --all --force "$selected_disk"
|
||||
sgdisk -a1 -n1:24K:+1000K -t1:EF02 "$selected_disk"
|
||||
sgdisk -n2:0:+2G -t2:BF01 "$selected_disk" # Boot pool
|
||||
sgdisk -n3:0:"$tail_space_parameter" -t3:BF01 "$selected_disk" # Root pool
|
||||
done
|
||||
|
||||
udevadm settle
|
||||
|
||||
echo "======= create zfs pools and datasets =========="
|
||||
|
||||
encryption_options=()
|
||||
rpool_disks_partitions=()
|
||||
bpool_disks_partitions=()
|
||||
|
||||
if [[ $v_encrypt_rpool == "1" ]]; then
|
||||
encryption_options=(-O "encryption=aes-256-gcm" -O "keylocation=prompt" -O "keyformat=passphrase")
|
||||
fi
|
||||
|
||||
for selected_disk in "${v_selected_disks[@]}"; do
|
||||
rpool_disks_partitions+=("${selected_disk}-part3")
|
||||
bpool_disks_partitions+=("${selected_disk}-part2")
|
||||
done
|
||||
|
||||
if [[ ${#v_selected_disks[@]} -gt 1 ]]; then
|
||||
pools_mirror_option=mirror
|
||||
else
|
||||
pools_mirror_option=
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
zpool create \
|
||||
$v_bpool_tweaks -O canmount=off -O devices=off \
|
||||
-o cachefile=/etc/zpool.cache \
|
||||
-O mountpoint=/boot -R $c_zfs_mount_dir -f \
|
||||
$v_bpool_name $pools_mirror_option "${bpool_disks_partitions[@]}"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
echo -n "$v_passphrase" | zpool create \
|
||||
$v_rpool_tweaks \
|
||||
-o cachefile=/etc/zpool.cache \
|
||||
"${encryption_options[@]}" \
|
||||
-O mountpoint=/ -R $c_zfs_mount_dir -f \
|
||||
$v_rpool_name $pools_mirror_option "${rpool_disks_partitions[@]}"
|
||||
|
||||
zfs create -o canmount=off -o mountpoint=none "$v_rpool_name/ROOT"
|
||||
zfs create -o canmount=off -o mountpoint=none "$v_bpool_name/BOOT"
|
||||
|
||||
zfs create -o canmount=noauto -o mountpoint=/ "$v_rpool_name/ROOT/ubuntu"
|
||||
zfs mount "$v_rpool_name/ROOT/ubuntu"
|
||||
|
||||
zfs create -o canmount=noauto -o mountpoint=/boot "$v_bpool_name/BOOT/ubuntu"
|
||||
zfs mount "$v_bpool_name/BOOT/ubuntu"
|
||||
|
||||
zfs create "$v_rpool_name/home"
|
||||
#zfs create -o mountpoint=/root "$v_rpool_name/home/root"
|
||||
zfs create -o canmount=off "$v_rpool_name/var"
|
||||
zfs create "$v_rpool_name/var/log"
|
||||
zfs create "$v_rpool_name/var/spool"
|
||||
|
||||
zfs create -o com.sun:auto-snapshot=false "$v_rpool_name/var/cache"
|
||||
zfs create -o com.sun:auto-snapshot=false "$v_rpool_name/var/tmp"
|
||||
chmod 1777 "$c_zfs_mount_dir/var/tmp"
|
||||
|
||||
zfs create "$v_rpool_name/srv"
|
||||
|
||||
zfs create -o canmount=off "$v_rpool_name/usr"
|
||||
zfs create "$v_rpool_name/usr/local"
|
||||
|
||||
zfs create "$v_rpool_name/var/mail"
|
||||
|
||||
zfs create -o com.sun:auto-snapshot=false -o canmount=on -o mountpoint=/tmp "$v_rpool_name/tmp"
|
||||
chmod 1777 "$c_zfs_mount_dir/tmp"
|
||||
|
||||
if [[ $v_swap_size -gt 0 ]]; then
|
||||
zfs create \
|
||||
-V "${v_swap_size}G" -b "$(getconf PAGESIZE)" \
|
||||
-o compression=zle -o logbias=throughput -o sync=always -o primarycache=metadata -o secondarycache=none -o com.sun:auto-snapshot=false \
|
||||
"$v_rpool_name/swap"
|
||||
|
||||
udevadm settle
|
||||
|
||||
mkswap -f "/dev/zvol/$v_rpool_name/swap"
|
||||
fi
|
||||
|
||||
echo "======= setting up initial system packages =========="
|
||||
debootstrap --arch=amd64 jammy "$c_zfs_mount_dir" "$c_deb_packages_repo"
|
||||
|
||||
zfs set devices=off "$v_rpool_name"
|
||||
|
||||
echo "======= setting up the network =========="
|
||||
|
||||
echo "$v_hostname" > $c_zfs_mount_dir/etc/hostname
|
||||
|
||||
cat > "$c_zfs_mount_dir/etc/hosts" <<CONF
|
||||
127.0.1.1 ${v_hostname}
|
||||
127.0.0.1 localhost
|
||||
|
||||
# The following lines are desirable for IPv6 capable hosts
|
||||
::1 ip6-localhost ip6-loopback
|
||||
fe00::0 ip6-localnet
|
||||
ff00::0 ip6-mcastprefix
|
||||
ff02::1 ip6-allnodes
|
||||
ff02::2 ip6-allrouters
|
||||
ff02::3 ip6-allhosts
|
||||
CONF
|
||||
|
||||
ip6addr_prefix=$(ip -6 a s | grep -E "inet6.+global" | sed -nE 's/.+inet6\s(([0-9a-z]{1,4}:){4,4}).+/\1/p' | head -n 1)
|
||||
|
||||
cat <<CONF > /mnt/etc/systemd/network/10-eth0.network
|
||||
[Match]
|
||||
Name=eth0
|
||||
|
||||
[Network]
|
||||
DHCP=ipv4
|
||||
Address=${ip6addr_prefix}:1/64
|
||||
Gateway=fe80::1
|
||||
CONF
|
||||
|
||||
chroot_execute "systemctl enable systemd-networkd.service"
|
||||
chroot_execute "systemctl enable systemd-resolved.service"
|
||||
|
||||
|
||||
mkdir -p "$c_zfs_mount_dir/etc/cloud/cloud.cfg.d/"
|
||||
cat > "$c_zfs_mount_dir/etc/cloud/cloud.cfg.d/99-disable-network-config.cfg" <<CONF
|
||||
network:
|
||||
config: disabled
|
||||
CONF
|
||||
|
||||
rm -rf $c_zfs_mount_dir/etc/network/interfaces.d/50-cloud-init.cfg
|
||||
|
||||
echo "======= preparing the jail for chroot =========="
|
||||
for virtual_fs_dir in proc sys dev; do
|
||||
mount --rbind "/$virtual_fs_dir" "$c_zfs_mount_dir/$virtual_fs_dir"
|
||||
done
|
||||
|
||||
echo "======= setting apt repos =========="
|
||||
cat > "$c_zfs_mount_dir/etc/apt/sources.list" <<CONF
|
||||
deb [arch=i386,amd64] $c_deb_packages_repo jammy main restricted
|
||||
deb [arch=i386,amd64] $c_deb_packages_repo jammy-updates main restricted
|
||||
deb [arch=i386,amd64] $c_deb_packages_repo jammy-backports main restricted
|
||||
deb [arch=i386,amd64] $c_deb_packages_repo jammy universe
|
||||
deb [arch=i386,amd64] $c_deb_security_repo jammy-security main restricted
|
||||
CONF
|
||||
|
||||
chroot_execute "apt update"
|
||||
|
||||
echo "======= setting locale, console and language =========="
|
||||
chroot_execute "apt --yes --fix-broken install"
|
||||
chroot_execute "apt install --yes -qq locales debconf-i18n apt-utils keyboard-configuration console-setup"
|
||||
sed -i 's/# en_US.UTF-8/en_US.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
sed -i 's/# fr_FR.UTF-8/fr_FR.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
sed -i 's/# fr_FR.UTF-8/fr_FR.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
sed -i 's/# de_AT.UTF-8/de_AT.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
sed -i 's/# de_DE.UTF-8/de_DE.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
|
||||
chroot_execute 'cat <<CONF | debconf-set-selections
|
||||
locales locales/default_environment_locale select en_US.UTF-8
|
||||
keyboard-configuration keyboard-configuration/store_defaults_in_debconf_db boolean true
|
||||
keyboard-configuration keyboard-configuration/variant select German
|
||||
keyboard-configuration keyboard-configuration/unsupported_layout boolean true
|
||||
keyboard-configuration keyboard-configuration/modelcode string pc105
|
||||
keyboard-configuration keyboard-configuration/unsupported_config_layout boolean true
|
||||
keyboard-configuration keyboard-configuration/layout select German
|
||||
keyboard-configuration keyboard-configuration/layoutcode string de
|
||||
keyboard-configuration keyboard-configuration/optionscode string
|
||||
keyboard-configuration keyboard-configuration/toggle select No toggling
|
||||
keyboard-configuration keyboard-configuration/xkb-keymap select de
|
||||
keyboard-configuration keyboard-configuration/switch select No temporary switch
|
||||
keyboard-configuration keyboard-configuration/unsupported_config_options boolean true
|
||||
keyboard-configuration keyboard-configuration/ctrl_alt_bksp boolean false
|
||||
keyboard-configuration keyboard-configuration/variantcode string
|
||||
keyboard-configuration keyboard-configuration/model select Generic 105-key PC (intl.)
|
||||
keyboard-configuration keyboard-configuration/altgr select The default for the keyboard layout
|
||||
keyboard-configuration keyboard-configuration/compose select No compose key
|
||||
keyboard-configuration keyboard-configuration/unsupported_options boolean true
|
||||
console-setup console-setup/fontsize-fb47 select 8x16
|
||||
console-setup console-setup/store_defaults_in_debconf_db boolean true
|
||||
console-setup console-setup/codeset47 select # Latin1 and Latin5 - western Europe and Turkic languages
|
||||
console-setup console-setup/fontface47 select Fixed
|
||||
console-setup console-setup/fontsize string 8x16
|
||||
console-setup console-setup/charmap47 select UTF-8
|
||||
console-setup console-setup/fontsize-text47 select 8x16
|
||||
console-setup console-setup/codesetcode string Lat15
|
||||
tzdata tzdata/Areas select Europe
|
||||
tzdata tzdata/Zones/Europe select Vienna
|
||||
grub-pc grub-pc/install_devices_empty boolean true
|
||||
CONF'
|
||||
|
||||
chroot_execute "dpkg-reconfigure locales -f noninteractive"
|
||||
echo -e "LC_ALL=en_US.UTF-8\nLANG=en_US.UTF-8\n" >> "$c_zfs_mount_dir/etc/environment"
|
||||
chroot_execute "dpkg-reconfigure keyboard-configuration -f noninteractive"
|
||||
chroot_execute "dpkg-reconfigure console-setup -f noninteractive"
|
||||
chroot_execute "setupcon"
|
||||
|
||||
chroot_execute "rm -f /etc/localtime /etc/timezone"
|
||||
chroot_execute "dpkg-reconfigure tzdata -f noninteractive "
|
||||
|
||||
echo "======= installing latest kernel============="
|
||||
chroot_execute "apt install --yes linux-headers${v_kernel_variant} linux-image${v_kernel_variant}"
|
||||
if [[ $v_kernel_variant == "-virtual" ]]; then
|
||||
# linux-image-extra is only available for virtual hosts
|
||||
chroot_execute "apt install --yes linux-image-extra-virtual"
|
||||
fi
|
||||
|
||||
|
||||
echo "======= installing aux packages =========="
|
||||
chroot_execute "apt install --yes man-db wget curl software-properties-common nano htop gnupg"
|
||||
chroot_execute "systemctl disable thermald"
|
||||
|
||||
echo "======= installing zfs packages =========="
|
||||
chroot_execute 'echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections'
|
||||
|
||||
if [[ $v_zfs_experimental == "1" ]]; then
|
||||
chroot_execute "wget -O - https://terem42.github.io/zfs-debian/apt_pub.gpg | apt-key add -"
|
||||
chroot_execute "add-apt-repository 'deb https://terem42.github.io/zfs-debian/public zfs-debian-experimental main'"
|
||||
chroot_execute "apt update"
|
||||
chroot_execute "apt install -t zfs-debian-experimental --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
else
|
||||
chroot_execute "add-apt-repository --yes ppa:jonathonf/zfs"
|
||||
chroot_execute "apt install --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
fi
|
||||
chroot_execute 'cat << DKMS > /etc/dkms/zfs.conf
|
||||
# override for /usr/src/zfs-*/dkms.conf:
|
||||
# always rebuild initrd when zfs module has been changed
|
||||
# (either by a ZFS update or a new kernel version)
|
||||
REMAKE_INITRD="yes"
|
||||
DKMS'
|
||||
|
||||
echo "======= installing OpenSSH and network tooling =========="
|
||||
chroot_execute "apt install --yes openssh-server net-tools"
|
||||
|
||||
echo "======= setup OpenSSH =========="
|
||||
mkdir -p "$c_zfs_mount_dir/root/.ssh/"
|
||||
cp /root/.ssh/authorized_keys "$c_zfs_mount_dir/root/.ssh/authorized_keys"
|
||||
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' "$c_zfs_mount_dir/etc/ssh/sshd_config"
|
||||
sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/g' "$c_zfs_mount_dir/etc/ssh/sshd_config"
|
||||
chroot_execute "rm /etc/ssh/ssh_host_*"
|
||||
chroot_execute "dpkg-reconfigure openssh-server -f noninteractive"
|
||||
|
||||
echo "======= set root password =========="
|
||||
chroot_execute "echo root:$(printf "%q" "$v_root_password") | chpasswd"
|
||||
|
||||
echo "======= setting up zfs cache =========="
|
||||
cp /etc/zpool.cache /mnt/etc/zfs/zpool.cache
|
||||
|
||||
echo "========setting up zfs module parameters========"
|
||||
chroot_execute "echo options zfs zfs_arc_max=$((v_zfs_arc_max_mb * 1024 * 1024)) >> /etc/modprobe.d/zfs.conf"
|
||||
|
||||
echo "======= setting up grub =========="
|
||||
chroot_execute "echo 'grub-pc grub-pc/install_devices_empty boolean true' | debconf-set-selections"
|
||||
chroot_execute "apt install --yes grub-pc"
|
||||
for disk in ${v_selected_disks[@]}; do
|
||||
chroot_execute "grub-install $disk"
|
||||
done
|
||||
|
||||
chroot_execute "sed -i 's/#GRUB_TERMINAL=console/GRUB_TERMINAL=console/g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"net.ifnames=0\"|' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX=\"\"|GRUB_CMDLINE_LINUX=\"root=ZFS=$v_rpool_name/ROOT/ubuntu\"|g' /etc/default/grub"
|
||||
|
||||
chroot_execute "sed -i 's/quiet//g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's/splash//g' /etc/default/grub"
|
||||
chroot_execute "echo 'GRUB_DISABLE_OS_PROBER=true' >> /etc/default/grub"
|
||||
|
||||
for ((i = 1; i < ${#v_selected_disks[@]}; i++)); do
|
||||
dd if="${v_selected_disks[0]}-part1" of="${v_selected_disks[i]}-part1"
|
||||
done
|
||||
|
||||
if [[ $v_encrypt_rpool == "1" ]]; then
|
||||
echo "=========set up dropbear=============="
|
||||
chroot_execute "apt install --yes dropbear-initramfs"
|
||||
|
||||
mkdir -p "$c_zfs_mount_dir/etc/dropbear/initramfs"
|
||||
cp /root/.ssh/authorized_keys "$c_zfs_mount_dir/etc/dropbear/initramfs/authorized_keys"
|
||||
|
||||
cp "$c_zfs_mount_dir/etc/ssh/ssh_host_rsa_key" "$c_zfs_mount_dir/etc/ssh/ssh_host_rsa_key_temp"
|
||||
chroot_execute "ssh-keygen -p -i -m pem -N '' -f /etc/ssh/ssh_host_rsa_key_temp"
|
||||
chroot_execute "/usr/lib/dropbear/dropbearconvert openssh dropbear /etc/ssh/ssh_host_rsa_key_temp /etc/dropbear/initramfs/dropbear_rsa_host_key"
|
||||
rm -rf "$c_zfs_mount_dir/etc/ssh/ssh_host_rsa_key_temp"
|
||||
|
||||
cp "$c_zfs_mount_dir/etc/ssh/ssh_host_ecdsa_key" "$c_zfs_mount_dir/etc/ssh/ssh_host_ecdsa_key_temp"
|
||||
chroot_execute "ssh-keygen -p -i -m pem -N '' -f /etc/ssh/ssh_host_ecdsa_key_temp"
|
||||
chroot_execute "/usr/lib/dropbear/dropbearconvert openssh dropbear /etc/ssh/ssh_host_ecdsa_key_temp /etc/dropbear/initramfs/dropbear_ecdsa_host_key"
|
||||
chroot_execute "rm -rf /etc/ssh/ssh_host_ecdsa_key_temp"
|
||||
rm -rf "$c_zfs_mount_dir/etc/ssh/ssh_host_ecdsa_key_temp"
|
||||
|
||||
rm -rf "$c_zfs_mount_dir/etc/dropbear/initramfs/dropbear_dss_host_key"
|
||||
fi
|
||||
|
||||
echo "============setup root prompt============"
|
||||
cat > "$c_zfs_mount_dir/root/.bashrc" <<CONF
|
||||
export PS1='\[\033[01;31m\]\u\[\033[01;33m\]@\[\033[01;32m\]\h \[\033[01;33m\]\w \[\033[01;35m\]\$ \[\033[00m\]'
|
||||
umask 022
|
||||
export LS_OPTIONS='--color=auto -h'
|
||||
eval "\$(dircolors)"
|
||||
CONF
|
||||
|
||||
echo "========running packages upgrade==========="
|
||||
chroot_execute "apt upgrade --yes"
|
||||
chroot_execute "apt purge cryptsetup* --yes"
|
||||
|
||||
echo "===========add static route to initramfs via hook to add default routes due to Ubuntu initramfs DHCP bug ========="
|
||||
mkdir -p "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount"
|
||||
cat > "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount/static-route" <<'CONF'
|
||||
#!/bin/sh
|
||||
PREREQ=""
|
||||
prereqs()
|
||||
{
|
||||
echo "$PREREQ"
|
||||
}
|
||||
|
||||
case $1 in
|
||||
prereqs)
|
||||
prereqs
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
. /scripts/functions
|
||||
# Begin real processing below this line
|
||||
|
||||
configure_networking
|
||||
|
||||
ip route add 172.31.1.1/255.255.255.255 dev ens3
|
||||
ip route add default via 172.31.1.1 dev ens3
|
||||
CONF
|
||||
|
||||
chmod 755 "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount/static-route"
|
||||
|
||||
echo "======= update initramfs =========="
|
||||
chroot_execute "update-initramfs -u -k all"
|
||||
|
||||
echo "======= update grub =========="
|
||||
chroot_execute "update-grub"
|
||||
|
||||
echo "======= setting up zed =========="
|
||||
|
||||
chroot_execute "zfs set canmount=noauto $v_rpool_name"
|
||||
|
||||
echo "======= setting mountpoints =========="
|
||||
chroot_execute "zfs set mountpoint=legacy $v_bpool_name/BOOT/ubuntu"
|
||||
chroot_execute "echo $v_bpool_name/BOOT/ubuntu /boot zfs nodev,relatime,x-systemd.requires=zfs-mount.service,x-systemd.device-timeout=10 0 0 > /etc/fstab"
|
||||
|
||||
chroot_execute "zfs set mountpoint=legacy $v_rpool_name/var/log"
|
||||
chroot_execute "echo $v_rpool_name/var/log /var/log zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
chroot_execute "zfs set mountpoint=legacy $v_rpool_name/var/spool"
|
||||
chroot_execute "echo $v_rpool_name/var/spool /var/spool zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
chroot_execute "zfs set mountpoint=legacy $v_rpool_name/var/tmp"
|
||||
chroot_execute "echo $v_rpool_name/var/tmp /var/tmp zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
chroot_execute "zfs set mountpoint=legacy $v_rpool_name/tmp"
|
||||
chroot_execute "echo $v_rpool_name/tmp /tmp zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
|
||||
echo "========= add swap, if defined"
|
||||
if [[ $v_swap_size -gt 0 ]]; then
|
||||
chroot_execute "echo /dev/zvol/$v_rpool_name/swap none swap discard 0 0 >> /etc/fstab"
|
||||
fi
|
||||
|
||||
chroot_execute "echo RESUME=none > /etc/initramfs-tools/conf.d/resume"
|
||||
|
||||
echo "======= unmounting filesystems and zfs pools =========="
|
||||
unmount_and_export_fs
|
||||
|
||||
echo "======== setup complete, rebooting ==============="
|
||||
reboot
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
: <<'end_header_info'
|
||||
(c) Andrey Prokopenko job@terem.fr
|
||||
fully automatic script to install Ubuntu 20 LTS with ZFS root on Hetzner VPS
|
||||
fully automatic script to install Debian 10 with ZFS root on Hetzner VPS
|
||||
WARNING: all data on the disk will be destroyed
|
||||
How to use: add SSH key to the rescue console, set it OS to linux64, then press "mount rescue and power cycle" button
|
||||
How to use: add SSH key to the rescue console, set it OS to linux64, then press mount rescue and power sysle
|
||||
Next, connect via SSH to console, and run the script
|
||||
Answer script questions about desired hostname and ZFS ARC cache size
|
||||
To cope with network failures its higly recommended to run the script inside screen console
|
||||
@@ -17,8 +17,6 @@ set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
export TMPDIR=/tmp
|
||||
|
||||
# Variables
|
||||
v_bpool_name=
|
||||
v_bpool_tweaks=
|
||||
@@ -37,12 +35,12 @@ v_zfs_experimental=
|
||||
v_suitable_disks=()
|
||||
|
||||
# Constants
|
||||
c_deb_packages_repo=http://mirror.hetzner.de/ubuntu/packages
|
||||
c_deb_security_repo=http://mirror.hetzner.de/ubuntu/security
|
||||
c_deb_packages_repo=http://deb.debian.org/debian
|
||||
c_deb_security_repo=http://deb.debian.org/debian-security/
|
||||
|
||||
c_default_zfs_arc_max_mb=250
|
||||
c_default_bpool_tweaks="-o ashift=12 -O compression=lz4"
|
||||
c_default_rpool_tweaks="-o ashift=12 -O acltype=posixacl -O compression=zstd-9 -O dnodesize=auto -O relatime=on -O xattr=sa -O normalization=formD"
|
||||
c_default_rpool_tweaks="-o ashift=12 -O acltype=posixacl -O compression=lz4 -O dnodesize=auto -O relatime=on -O xattr=sa -O normalization=formD"
|
||||
c_default_hostname=terem
|
||||
c_zfs_mount_dir=/mnt
|
||||
c_log_dir=$(dirname "$(mktemp)")/zfs-hetzner-vm
|
||||
@@ -64,9 +62,7 @@ function print_step_info_header {
|
||||
###############################################################################
|
||||
# ${FUNCNAME[1]}"
|
||||
|
||||
if [[ "${1:-}" != "" ]]; then
|
||||
echo -n " $1"
|
||||
fi
|
||||
[[ "${1:-}" != "" ]] && echo -n " $1" || true
|
||||
|
||||
echo "
|
||||
###############################################################################
|
||||
@@ -106,11 +102,11 @@ function display_intro_banner {
|
||||
print_step_info_header
|
||||
|
||||
local dialog_message='Hello!
|
||||
This script will prepare the ZFS pools, then install and configure minimal Ubuntu 20 LTS with ZFS root on Hetzner hosting VPS instance
|
||||
This script will prepare the ZFS pools, then install and configure minimal Debian 10 with ZFS root on Hetzner hosting VPS instance
|
||||
The script with minimal changes may be used on any other hosting provider supporting KVM virtualization and offering Debian-based rescue system.
|
||||
In order to stop the procedure, hit Esc twice during dialogs (excluding yes/no ones), or Ctrl+C while any operation is running.
|
||||
'
|
||||
dialog --msgbox "$dialog_message" 30 100
|
||||
dialog --ascii-lines --msgbox "$dialog_message" 30 100
|
||||
}
|
||||
|
||||
function store_os_distro_information {
|
||||
@@ -127,15 +123,50 @@ function check_prerequisites {
|
||||
echo 'This script must be run with administrative privileges!'
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -r /root/.ssh/authorized_keys ]]; then
|
||||
echo "SSH pubkey file is absent, please add it to the rescue system setting, then reboot into rescue system and run the script"
|
||||
exit 1
|
||||
fi
|
||||
# if [[ ! -r /root/.ssh/authorized_keys ]]; then
|
||||
# echo "SSH pubkey file is absent, please add it to the rescue system setting, then reboot into rescue system and run the script"
|
||||
# exit 1
|
||||
# fi
|
||||
if ! dpkg-query --showformat="\${Status}" -W dialog 2> /dev/null | grep -q "install ok installed"; then
|
||||
apt install --yes dialog
|
||||
fi
|
||||
}
|
||||
|
||||
function initial_load_debian_zed_cache {
|
||||
chroot_execute "mkdir /etc/zfs/zfs-list.cache"
|
||||
chroot_execute "touch /etc/zfs/zfs-list.cache/rpool"
|
||||
chroot_execute "ln -s /usr/lib/zfs-linux/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d/"
|
||||
|
||||
chroot_execute "zed -F &"
|
||||
|
||||
local success=0
|
||||
|
||||
if [[ ! -e /mnt/etc/zfs/zfs-list.cache/rpool ]] || [[ -e /mnt/etc/zfs/zfs-list.cache/rpool && (( $(ls -l /mnt/etc/zfs/zfs-list.cache/rpool 2> /dev/null | cut -d ' ' -f 5) == 0 )) ]]; then
|
||||
chroot_execute "zfs set canmount=noauto rpool"
|
||||
|
||||
SECONDS=0
|
||||
|
||||
while (( SECONDS++ <= 120 )); do
|
||||
if [[ -e /mnt/etc/zfs/zfs-list.cache/rpool ]] && (( "$(ls -l /mnt/etc/zfs/zfs-list.cache/rpool | cut -d ' ' -f 5)" > 0 )); then
|
||||
success=1
|
||||
break
|
||||
else
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
else
|
||||
success=1
|
||||
fi
|
||||
|
||||
if (( success != 1 )); then
|
||||
echo "Fatal zed daemon error: the ZFS cache hasn't been updated by ZED!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chroot_execute "pkill zed"
|
||||
|
||||
sed -Ei 's|/mnt/?|/|g' /mnt/etc/zfs/zfs-list.cache/rpool
|
||||
}
|
||||
|
||||
function find_suitable_disks {
|
||||
# shellcheck disable=SC2119
|
||||
@@ -179,7 +210,7 @@ LOG
|
||||
|
||||
If you think this is a bug, please open an issue on https://github.com/terem42/zfs-hetzner-vm/issues, and attach the file `'"$c_disks_log"'`.
|
||||
'
|
||||
dialog --msgbox "$dialog_message" 30 100
|
||||
dialog --ascii-lines --msgbox "$dialog_message" 30 100
|
||||
|
||||
exit 1
|
||||
fi
|
||||
@@ -208,7 +239,7 @@ function select_disks {
|
||||
|
||||
Devices with mounted partitions, cdroms, and removable devices are not displayed!
|
||||
"
|
||||
mapfile -t v_selected_disks < <(dialog --separate-output --checklist "$dialog_message" 30 100 $((${#menu_entries_option[@]} / 3)) "${menu_entries_option[@]}" 3>&1 1>&2 2>&3)
|
||||
mapfile -t v_selected_disks < <(dialog --ascii-lines --separate-output --checklist "$dialog_message" 30 100 $((${#menu_entries_option[@]} / 3)) "${menu_entries_option[@]}" 3>&1 1>&2 2>&3)
|
||||
|
||||
if [[ ${#v_selected_disks[@]} -gt 0 ]]; then
|
||||
break
|
||||
@@ -225,7 +256,7 @@ function ask_swap_size {
|
||||
local swap_size_invalid_message=
|
||||
|
||||
while [[ ! $v_swap_size =~ ^[0-9]+$ ]]; do
|
||||
v_swap_size=$(dialog --inputbox "${swap_size_invalid_message}Enter the swap size in GiB (0 for no swap):" 30 100 2 3>&1 1>&2 2>&3)
|
||||
v_swap_size=$(dialog --ascii-lines --inputbox "${swap_size_invalid_message}Enter the swap size in GiB (0 for no swap):" 30 100 2 3>&1 1>&2 2>&3)
|
||||
|
||||
swap_size_invalid_message="Invalid swap size! "
|
||||
done
|
||||
@@ -240,7 +271,7 @@ function ask_free_tail_space {
|
||||
local tail_space_invalid_message=
|
||||
|
||||
while [[ ! $v_free_tail_space =~ ^[0-9]+$ ]]; do
|
||||
v_free_tail_space=$(dialog --inputbox "${tail_space_invalid_message}Enter the space to leave at the end of each disk (0 for none):" 30 100 0 3>&1 1>&2 2>&3)
|
||||
v_free_tail_space=$(dialog --ascii-lines --inputbox "${tail_space_invalid_message}Enter the space to leave at the end of each disk (0 for none):" 30 100 0 3>&1 1>&2 2>&3)
|
||||
|
||||
tail_space_invalid_message="Invalid size! "
|
||||
done
|
||||
@@ -255,7 +286,7 @@ function ask_zfs_arc_max_size {
|
||||
local zfs_arc_max_invalid_message=
|
||||
|
||||
while [[ ! $v_zfs_arc_max_mb =~ ^[0-9]+$ ]]; do
|
||||
v_zfs_arc_max_mb=$(dialog --inputbox "${zfs_arc_max_invalid_message}Enter ZFS ARC cache max size in Mb (minimum 64Mb, enter 0 for ZFS default value, the default will take up to 50% of memory):" 30 100 "$c_default_zfs_arc_max_mb" 3>&1 1>&2 2>&3)
|
||||
v_zfs_arc_max_mb=$(dialog --ascii-lines --inputbox "${zfs_arc_max_invalid_message}Enter ZFS ARC cache max size in Mb (minimum 64Mb, enter 0 for ZFS default value, the default will take up to 50% of memory):" 30 100 "$c_default_zfs_arc_max_mb" 3>&1 1>&2 2>&3)
|
||||
|
||||
zfs_arc_max_invalid_message="Invalid size! "
|
||||
done
|
||||
@@ -271,14 +302,14 @@ function ask_pool_names {
|
||||
local bpool_name_invalid_message=
|
||||
|
||||
while [[ ! $v_bpool_name =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_bpool_name=$(dialog --inputbox "${bpool_name_invalid_message}Insert the name for the boot pool" 30 100 bpool 3>&1 1>&2 2>&3)
|
||||
v_bpool_name=$(dialog --ascii-lines --inputbox "${bpool_name_invalid_message}Insert the name for the boot pool" 30 100 bpool 3>&1 1>&2 2>&3)
|
||||
|
||||
bpool_name_invalid_message="Invalid pool name! "
|
||||
done
|
||||
local rpool_name_invalid_message=
|
||||
|
||||
while [[ ! $v_rpool_name =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_rpool_name=$(dialog --inputbox "${rpool_name_invalid_message}Insert the name for the root pool" 30 100 rpool 3>&1 1>&2 2>&3)
|
||||
v_rpool_name=$(dialog --ascii-lines --inputbox "${rpool_name_invalid_message}Insert the name for the root pool" 30 100 rpool 3>&1 1>&2 2>&3)
|
||||
|
||||
rpool_name_invalid_message="Invalid pool name! "
|
||||
done
|
||||
@@ -290,8 +321,8 @@ function ask_pool_tweaks {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
v_bpool_tweaks=$(dialog --inputbox "Insert the tweaks for the boot pool" 30 100 -- "$c_default_bpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
v_rpool_tweaks=$(dialog --inputbox "Insert the tweaks for the root pool" 30 100 -- "$c_default_rpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
v_bpool_tweaks=$(dialog --ascii-lines --inputbox "Insert the tweaks for the boot pool" 30 100 -- "$c_default_bpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
v_rpool_tweaks=$(dialog --ascii-lines --inputbox "Insert the tweaks for the root pool" 30 100 -- "$c_default_rpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
|
||||
print_variables v_bpool_tweaks v_rpool_tweaks
|
||||
}
|
||||
@@ -306,8 +337,8 @@ function ask_root_password {
|
||||
local password_repeat=-
|
||||
|
||||
while [[ "$v_root_password" != "$password_repeat" || "$v_root_password" == "" ]]; do
|
||||
v_root_password=$(dialog --passwordbox "${password_invalid_message}Please enter the root account password (can't be empty):" 30 100 3>&1 1>&2 2>&3)
|
||||
password_repeat=$(dialog --passwordbox "Please repeat the password:" 30 100 3>&1 1>&2 2>&3)
|
||||
v_root_password=$(dialog --ascii-lines --passwordbox "${password_invalid_message}Please enter the root account password (can't be empty):" 30 100 3>&1 1>&2 2>&3)
|
||||
password_repeat=$(dialog --ascii-lines --passwordbox "Please repeat the password:" 30 100 3>&1 1>&2 2>&3)
|
||||
|
||||
password_invalid_message="Passphrase empty, or not matching! "
|
||||
done
|
||||
@@ -317,7 +348,7 @@ function ask_root_password {
|
||||
function ask_encryption {
|
||||
print_step_info_header
|
||||
|
||||
if dialog --defaultno --yesno 'Do you want to encrypt the root pool?' 30 100; then
|
||||
if dialog --ascii-lines --yesno 'Do you want to encrypt the root pool?' 30 100; then
|
||||
v_encrypt_rpool=1
|
||||
fi
|
||||
set +x
|
||||
@@ -325,8 +356,8 @@ function ask_encryption {
|
||||
local passphrase_invalid_message=
|
||||
local passphrase_repeat=-
|
||||
while [[ "$v_passphrase" != "$passphrase_repeat" || ${#v_passphrase} -lt 8 ]]; do
|
||||
v_passphrase=$(dialog --passwordbox "${passphrase_invalid_message}Please enter the passphrase for the root pool (8 chars min.):" 30 100 3>&1 1>&2 2>&3)
|
||||
passphrase_repeat=$(dialog --passwordbox "Please repeat the passphrase:" 30 100 3>&1 1>&2 2>&3)
|
||||
v_passphrase=$(dialog --ascii-lines --passwordbox "${passphrase_invalid_message}Please enter the passphrase for the root pool (8 chars min.):" 30 100 3>&1 1>&2 2>&3)
|
||||
passphrase_repeat=$(dialog --ascii-lines --passwordbox "Please repeat the passphrase:" 30 100 3>&1 1>&2 2>&3)
|
||||
|
||||
passphrase_invalid_message="Passphrase too short, or not matching! "
|
||||
done
|
||||
@@ -337,7 +368,7 @@ function ask_encryption {
|
||||
function ask_zfs_experimental {
|
||||
print_step_info_header
|
||||
|
||||
if dialog --defaultno --yesno 'Do you want to use experimental zfs module build?' 30 100; then
|
||||
if dialog --ascii-lines --yesno 'Do you want to use experimental zfs module build?' 30 100; then
|
||||
v_zfs_experimental=1
|
||||
fi
|
||||
}
|
||||
@@ -348,8 +379,8 @@ function ask_hostname {
|
||||
|
||||
local hostname_invalid_message=
|
||||
|
||||
while [[ ! $v_hostname =~ ^[a-z][a-zA-Z0-9_:.-]+$ ]]; do
|
||||
v_hostname=$(dialog --inputbox "${hostname_invalid_message}Set the host name" 30 100 "$c_default_hostname" 3>&1 1>&2 2>&3)
|
||||
while [[ ! $v_hostname =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_hostname=$(dialog --ascii-lines --inputbox "${hostname_invalid_message}Set the host name" 30 100 "$c_default_hostname" 3>&1 1>&2 2>&3)
|
||||
|
||||
hostname_invalid_message="Invalid host name! "
|
||||
done
|
||||
@@ -359,14 +390,12 @@ function ask_hostname {
|
||||
|
||||
function determine_kernel_variant {
|
||||
if dmidecode | grep -q vServer; then
|
||||
v_kernel_variant="-virtual"
|
||||
else
|
||||
v_kernel_variant="-generic"
|
||||
v_kernel_variant="-cloud"
|
||||
fi
|
||||
}
|
||||
|
||||
function chroot_execute {
|
||||
chroot $c_zfs_mount_dir bash -c "DEBIAN_FRONTEND=noninteractive $1"
|
||||
chroot $c_zfs_mount_dir bash -c "$1"
|
||||
}
|
||||
|
||||
function unmount_and_export_fs {
|
||||
@@ -403,8 +432,8 @@ function unmount_and_export_fs {
|
||||
echo "===========exporting zfs pools============="
|
||||
set +e
|
||||
while (( zpools_exported == 99 )) && (( SECONDS++ <= 60 )); do
|
||||
|
||||
if zpool export -a 2> /dev/null; then
|
||||
zpool export -a 2> /dev/null
|
||||
if [[ $? == 0 ]]; then
|
||||
zpools_exported=1
|
||||
echo "all zfs pools were succesfully exported"
|
||||
break;
|
||||
@@ -421,14 +450,13 @@ function unmount_and_export_fs {
|
||||
|
||||
#################### MAIN ################################
|
||||
export LC_ALL=en_US.UTF-8
|
||||
export NCURSES_NO_UTF8_ACS=1
|
||||
|
||||
check_prerequisites
|
||||
|
||||
display_intro_banner
|
||||
|
||||
activate_debug
|
||||
|
||||
display_intro_banner
|
||||
|
||||
find_suitable_disks
|
||||
|
||||
select_disks
|
||||
@@ -462,20 +490,20 @@ for kver in $(find /lib/modules/* -maxdepth 0 -type d | grep -v "$(uname -r)" |
|
||||
done
|
||||
|
||||
echo "======= installing zfs on rescue system =========="
|
||||
echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections
|
||||
# echo "y" | zfs
|
||||
# linux-headers-generic linux-image-generic
|
||||
apt install --yes software-properties-common dpkg-dev dkms
|
||||
rm -f "$(which zfs)"
|
||||
rm -f "$(which zpool)"
|
||||
echo -e "deb http://deb.debian.org/debian/ testing main contrib non-free\ndeb http://deb.debian.org/debian/ testing main contrib non-free\n" >/etc/apt/sources.list.d/bookworm-testing.list
|
||||
echo -e "Package: src:zfs-linux\nPin: release n=testing\nPin-Priority: 990\n" > /etc/apt/preferences.d/90_zfs
|
||||
apt update
|
||||
apt install -t testing --yes zfs-dkms zfsutils-linux
|
||||
rm /etc/apt/sources.list.d/bookworm-testing.list
|
||||
rm /etc/apt/preferences.d/90_zfs
|
||||
cat > "/etc/apt/sources.list" <<CONF
|
||||
deb [arch=i386,amd64] $c_deb_packages_repo buster main contrib non-free
|
||||
deb [arch=i386,amd64] $c_deb_packages_repo buster-updates main contrib non-free
|
||||
deb [arch=i386,amd64] $c_deb_packages_repo buster-backports main contrib non-free
|
||||
deb [arch=i386,amd64] $c_deb_security_repo buster/updates main contrib non-free
|
||||
CONF
|
||||
|
||||
apt update
|
||||
|
||||
echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections
|
||||
|
||||
apt update
|
||||
export PATH=$PATH:/usr/sbin
|
||||
apt install --yes -t buster-backports libelf-dev zfs-dkms wget debootstrap
|
||||
modprobe zfs
|
||||
zfs --version
|
||||
|
||||
echo "======= partitioning the disk =========="
|
||||
@@ -487,9 +515,9 @@ echo "======= partitioning the disk =========="
|
||||
fi
|
||||
|
||||
for selected_disk in "${v_selected_disks[@]}"; do
|
||||
wipefs --all --force "$selected_disk"
|
||||
wipefs --all "$selected_disk"
|
||||
sgdisk -a1 -n1:24K:+1000K -t1:EF02 "$selected_disk"
|
||||
sgdisk -n2:0:+2G -t2:BF01 "$selected_disk" # Boot pool
|
||||
sgdisk -n2:0:+512M -t2:BF01 "$selected_disk" # Boot pool
|
||||
sgdisk -n3:0:"$tail_space_parameter" -t3:BF01 "$selected_disk" # Root pool
|
||||
done
|
||||
|
||||
@@ -516,17 +544,13 @@ echo "======= create zfs pools and datasets =========="
|
||||
pools_mirror_option=
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
zpool create \
|
||||
$v_bpool_tweaks -O canmount=off -O devices=off \
|
||||
-o cachefile=/etc/zpool.cache \
|
||||
-O mountpoint=/boot -R $c_zfs_mount_dir -f \
|
||||
$v_bpool_name $pools_mirror_option "${bpool_disks_partitions[@]}"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
echo -n "$v_passphrase" | zpool create \
|
||||
$v_rpool_tweaks \
|
||||
-o cachefile=/etc/zpool.cache \
|
||||
"${encryption_options[@]}" \
|
||||
-O mountpoint=/ -R $c_zfs_mount_dir -f \
|
||||
$v_rpool_name $pools_mirror_option "${rpool_disks_partitions[@]}"
|
||||
@@ -534,14 +558,16 @@ echo -n "$v_passphrase" | zpool create \
|
||||
zfs create -o canmount=off -o mountpoint=none "$v_rpool_name/ROOT"
|
||||
zfs create -o canmount=off -o mountpoint=none "$v_bpool_name/BOOT"
|
||||
|
||||
zfs create -o canmount=noauto -o mountpoint=/ "$v_rpool_name/ROOT/ubuntu"
|
||||
zfs mount "$v_rpool_name/ROOT/ubuntu"
|
||||
zfs create -o canmount=noauto -o mountpoint=/ "$v_rpool_name/ROOT/debian"
|
||||
zfs mount "$v_rpool_name/ROOT/debian"
|
||||
|
||||
zfs create -o canmount=noauto -o mountpoint=/boot "$v_bpool_name/BOOT/ubuntu"
|
||||
zfs mount "$v_bpool_name/BOOT/ubuntu"
|
||||
|
||||
zfs create "$v_rpool_name/home"
|
||||
zfs create -o mountpoint=/root "$v_rpool_name/home/root"
|
||||
zfs create -o canmount=off "$v_rpool_name/var"
|
||||
zfs create -o canmount=off "$v_rpool_name/var/lib"
|
||||
zfs create "$v_rpool_name/var/log"
|
||||
zfs create "$v_rpool_name/var/spool"
|
||||
|
||||
@@ -566,12 +592,12 @@ if [[ $v_swap_size -gt 0 ]]; then
|
||||
"$v_rpool_name/swap"
|
||||
|
||||
udevadm settle
|
||||
|
||||
|
||||
mkswap -f "/dev/zvol/$v_rpool_name/swap"
|
||||
fi
|
||||
|
||||
echo "======= setting up initial system packages =========="
|
||||
debootstrap --arch=amd64 focal "$c_zfs_mount_dir" "$c_deb_packages_repo"
|
||||
debootstrap --arch=amd64 buster "$c_zfs_mount_dir" "$c_deb_packages_repo"
|
||||
|
||||
zfs set devices=off "$v_rpool_name"
|
||||
|
||||
@@ -592,7 +618,7 @@ ff02::2 ip6-allrouters
|
||||
ff02::3 ip6-allhosts
|
||||
CONF
|
||||
|
||||
ip6addr_prefix=$(ip -6 a s | grep -E "inet6.+global" | sed -nE 's/.+inet6\s(([0-9a-z]{1,4}:){4,4}).+/\1/p' | head -n 1)
|
||||
ip6addr=$(ip -6 a s | grep -E "inet6.+scope.+link" | sed -nE 's/.+inet6\s(([0-9a-z]{4,4}:{0,2}){5,5}\/[0-9]{2,2}).+/\1/p')
|
||||
|
||||
cat <<CONF > /mnt/etc/systemd/network/10-eth0.network
|
||||
[Match]
|
||||
@@ -600,23 +626,15 @@ Name=eth0
|
||||
|
||||
[Network]
|
||||
DHCP=ipv4
|
||||
Address=${ip6addr_prefix}:1/64
|
||||
|
||||
Address=${ip6addr}
|
||||
Gateway=fe80::1
|
||||
CONF
|
||||
|
||||
chroot_execute "systemctl enable systemd-networkd.service"
|
||||
chroot_execute "systemctl enable systemd-resolved.service"
|
||||
|
||||
|
||||
mkdir -p "$c_zfs_mount_dir/etc/cloud/cloud.cfg.d/"
|
||||
cat > "$c_zfs_mount_dir/etc/cloud/cloud.cfg.d/99-disable-network-config.cfg" <<CONF
|
||||
network:
|
||||
config: disabled
|
||||
CONF
|
||||
|
||||
rm -rf $c_zfs_mount_dir/etc/network/interfaces.d/50-cloud-init.cfg
|
||||
|
||||
#cp /etc/resolv.conf $c_zfs_mount_dir/etc/resolv.conf
|
||||
cp /etc/resolv.conf $c_zfs_mount_dir/etc/resolv.conf
|
||||
|
||||
echo "======= preparing the jail for chroot =========="
|
||||
for virtual_fs_dir in proc sys dev; do
|
||||
@@ -625,11 +643,10 @@ done
|
||||
|
||||
echo "======= setting apt repos =========="
|
||||
cat > "$c_zfs_mount_dir/etc/apt/sources.list" <<CONF
|
||||
deb [arch=i386,amd64] $c_deb_packages_repo focal main restricted
|
||||
deb [arch=i386,amd64] $c_deb_packages_repo focal-updates main restricted
|
||||
deb [arch=i386,amd64] $c_deb_packages_repo focal-backports main restricted
|
||||
deb [arch=i386,amd64] $c_deb_packages_repo focal universe
|
||||
deb [arch=i386,amd64] $c_deb_security_repo focal-security main restricted
|
||||
deb [arch=i386,amd64] $c_deb_packages_repo buster main contrib non-free
|
||||
deb [arch=i386,amd64] $c_deb_packages_repo buster-updates main contrib non-free
|
||||
deb [arch=i386,amd64] $c_deb_packages_repo buster-backports main contrib non-free
|
||||
deb [arch=i386,amd64] $c_deb_security_repo buster/updates main contrib non-free
|
||||
CONF
|
||||
|
||||
chroot_execute "apt update"
|
||||
@@ -645,15 +662,15 @@ sed -i 's/# de_DE.UTF-8/de_DE.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
chroot_execute 'cat <<CONF | debconf-set-selections
|
||||
locales locales/default_environment_locale select en_US.UTF-8
|
||||
keyboard-configuration keyboard-configuration/store_defaults_in_debconf_db boolean true
|
||||
keyboard-configuration keyboard-configuration/variant select German
|
||||
keyboard-configuration keyboard-configuration/variant select English
|
||||
keyboard-configuration keyboard-configuration/unsupported_layout boolean true
|
||||
keyboard-configuration keyboard-configuration/modelcode string pc105
|
||||
keyboard-configuration keyboard-configuration/unsupported_config_layout boolean true
|
||||
keyboard-configuration keyboard-configuration/layout select German
|
||||
keyboard-configuration keyboard-configuration/layoutcode string de
|
||||
keyboard-configuration keyboard-configuration/layout select English
|
||||
keyboard-configuration keyboard-configuration/layoutcode string en
|
||||
keyboard-configuration keyboard-configuration/optionscode string
|
||||
keyboard-configuration keyboard-configuration/toggle select No toggling
|
||||
keyboard-configuration keyboard-configuration/xkb-keymap select de
|
||||
keyboard-configuration keyboard-configuration/xkb-keymap select en
|
||||
keyboard-configuration keyboard-configuration/switch select No temporary switch
|
||||
keyboard-configuration keyboard-configuration/unsupported_config_options boolean true
|
||||
keyboard-configuration keyboard-configuration/ctrl_alt_bksp boolean false
|
||||
@@ -685,42 +702,36 @@ chroot_execute "rm -f /etc/localtime /etc/timezone"
|
||||
chroot_execute "dpkg-reconfigure tzdata -f noninteractive "
|
||||
|
||||
echo "======= installing latest kernel============="
|
||||
chroot_execute "apt install --yes linux-headers${v_kernel_variant} linux-image${v_kernel_variant}"
|
||||
if [[ $v_kernel_variant == "-virtual" ]]; then
|
||||
# linux-image-extra is only available for virtual hosts
|
||||
chroot_execute "apt install --yes linux-image-extra-virtual"
|
||||
fi
|
||||
|
||||
chroot_execute "apt install --yes -t buster-backports linux-image${v_kernel_variant}-amd64 linux-headers${v_kernel_variant}-amd64"
|
||||
|
||||
echo "======= installing aux packages =========="
|
||||
chroot_execute "apt install --yes man-db wget curl software-properties-common nano htop gnupg"
|
||||
chroot_execute "systemctl disable thermald"
|
||||
chroot_execute "apt install --yes man wget curl software-properties-common nano htop gnupg"
|
||||
|
||||
echo "======= installing zfs packages =========="
|
||||
if [[ $v_zfs_experimental == "1" ]]; then
|
||||
chroot_execute "apt install software-properties-common"
|
||||
chroot_execute "wget -O - https://apt.terem.fr/apt_pub.gpg | apt-key add -"
|
||||
chroot_execute "add-apt-repository 'deb [arch=amd64] http://apt.terem.fr/public zfs-debian main'"
|
||||
chroot_execute "apt update"
|
||||
chroot_execute "bash -c \"echo 'zfs-dkms zfs-dkms/note-incompatible-licenses note true' | debconf-set-selections\""
|
||||
chroot_execute "apt install -t zfs-debian --yes zfs-dkms zfsutils-linux"
|
||||
else
|
||||
chroot_execute "apt install --yes zfs-initramfs zfs-dkms"
|
||||
fi
|
||||
chroot_execute 'echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections'
|
||||
|
||||
if [[ $v_zfs_experimental == "1" ]]; then
|
||||
chroot_execute "wget -O - https://terem42.github.io/zfs-debian/apt_pub.gpg | apt-key add -"
|
||||
chroot_execute "add-apt-repository 'deb https://terem42.github.io/zfs-debian/public zfs-debian-experimental main'"
|
||||
chroot_execute "apt update"
|
||||
chroot_execute "apt install -t zfs-debian-experimental --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
chroot_execute "apt install --yes -t zfs-debian-experimental zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
else
|
||||
chroot_execute "add-apt-repository --yes ppa:jonathonf/zfs"
|
||||
chroot_execute "apt install --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
fi
|
||||
chroot_execute 'cat << DKMS > /etc/dkms/zfs.conf
|
||||
# override for /usr/src/zfs-*/dkms.conf:
|
||||
# always rebuild initrd when zfs module has been changed
|
||||
# (either by a ZFS update or a new kernel version)
|
||||
REMAKE_INITRD="yes"
|
||||
DKMS'
|
||||
|
||||
echo "======= installing OpenSSH and network tooling =========="
|
||||
chroot_execute "apt install --yes openssh-server net-tools"
|
||||
|
||||
echo "======= setup OpenSSH =========="
|
||||
mkdir -p "$c_zfs_mount_dir/root/.ssh/"
|
||||
cp /root/.ssh/authorized_keys "$c_zfs_mount_dir/root/.ssh/authorized_keys"
|
||||
wget https://raw.githubusercontent.com/terem42/zfs-hetzner-vm/vmtest/authorized_keys -O "$c_zfs_mount_dir/root/.ssh/authorized_keys"
|
||||
#cp /root/.ssh/authorized_keys "$c_zfs_mount_dir/root/.ssh/authorized_keys"
|
||||
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' "$c_zfs_mount_dir/etc/ssh/sshd_config"
|
||||
sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/g' "$c_zfs_mount_dir/etc/ssh/sshd_config"
|
||||
chroot_execute "rm /etc/ssh/ssh_host_*"
|
||||
@@ -729,22 +740,17 @@ chroot_execute "dpkg-reconfigure openssh-server -f noninteractive"
|
||||
echo "======= set root password =========="
|
||||
chroot_execute "echo root:$(printf "%q" "$v_root_password") | chpasswd"
|
||||
|
||||
echo "======= setting up zfs cache =========="
|
||||
cp /etc/zpool.cache /mnt/etc/zfs/zpool.cache
|
||||
|
||||
echo "========setting up zfs module parameters========"
|
||||
chroot_execute "echo options zfs zfs_arc_max=$((v_zfs_arc_max_mb * 1024 * 1024)) >> /etc/modprobe.d/zfs.conf"
|
||||
|
||||
echo "======= setting up grub =========="
|
||||
chroot_execute "echo 'grub-pc grub-pc/install_devices_empty boolean true' | debconf-set-selections"
|
||||
chroot_execute "apt install --yes grub-pc"
|
||||
for disk in ${v_selected_disks[@]}; do
|
||||
chroot_execute "grub-install $disk"
|
||||
done
|
||||
chroot_execute "DEBIAN_FRONTEND=noninteractive apt install --yes grub-pc"
|
||||
chroot_execute "grub-install ${v_selected_disks[0]}"
|
||||
|
||||
chroot_execute "sed -i 's/#GRUB_TERMINAL=console/GRUB_TERMINAL=console/g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"net.ifnames=0\"|' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX=\"\"|GRUB_CMDLINE_LINUX=\"root=ZFS=$v_rpool_name/ROOT/ubuntu\"|g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX=\"\"|GRUB_CMDLINE_LINUX=\"root=ZFS=rpool/ROOT/debian\"|g' /etc/default/grub"
|
||||
|
||||
chroot_execute "sed -i 's/quiet//g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's/splash//g' /etc/default/grub"
|
||||
@@ -756,9 +762,11 @@ done
|
||||
|
||||
if [[ $v_encrypt_rpool == "1" ]]; then
|
||||
echo "=========set up dropbear=============="
|
||||
|
||||
chroot_execute "apt install --yes dropbear-initramfs"
|
||||
|
||||
cp /root/.ssh/authorized_keys "$c_zfs_mount_dir/etc/dropbear-initramfs/authorized_keys"
|
||||
|
||||
cp "$c_zfs_mount_dir/root/.ssh/authorized_keys" "$c_zfs_mount_dir/etc/dropbear-initramfs/authorized_keys"
|
||||
#cp /root/.ssh/authorized_keys "$c_zfs_mount_dir/etc/dropbear-initramfs/authorized_keys"
|
||||
|
||||
cp "$c_zfs_mount_dir/etc/ssh/ssh_host_rsa_key" "$c_zfs_mount_dir/etc/ssh/ssh_host_rsa_key_temp"
|
||||
chroot_execute "ssh-keygen -p -i -m pem -N '' -f /etc/ssh/ssh_host_rsa_key_temp"
|
||||
@@ -772,19 +780,19 @@ if [[ $v_encrypt_rpool == "1" ]]; then
|
||||
rm -rf "$c_zfs_mount_dir/etc/ssh/ssh_host_ecdsa_key_temp"
|
||||
|
||||
rm -rf "$c_zfs_mount_dir/etc/dropbear-initramfs/dropbear_dss_host_key"
|
||||
fi
|
||||
|
||||
cd "$c_zfs_mount_dir/root"
|
||||
wget http://ftp.de.debian.org/debian/pool/main/libt/libtommath/libtommath1_1.2.0-6_amd64.deb
|
||||
wget http://ftp.de.debian.org/debian/pool/main/d/dropbear/dropbear-bin_2020.81-3_amd64.deb
|
||||
wget http://ftp.de.debian.org/debian/pool/main/d/dropbear/dropbear-initramfs_2020.81-3_all.deb
|
||||
#cd "$c_zfs_mount_dir/root"
|
||||
#wget http://ftp.de.debian.org/debian/pool/main/libt/libtommath/libtommath1_1.1.0-3_amd64.deb
|
||||
#wget http://ftp.de.debian.org/debian/pool/main/d/dropbear/dropbear-bin_2018.76-5_amd64.deb
|
||||
#wget http://ftp.de.debian.org/debian/pool/main/d/dropbear/dropbear-initramfs_2018.76-5_all.deb
|
||||
|
||||
chroot_execute "dpkg -i /root/libtommath1_1.2.0-6_amd64.deb"
|
||||
chroot_execute "dpkg -i /root/dropbear-bin_2020.81-3_amd64.deb"
|
||||
chroot_execute "dpkg -i /root/dropbear-initramfs_2020.81-3_all.deb"
|
||||
#chroot_execute "dpkg -i /root/libtommath1_1.1.0-3_amd64.deb"
|
||||
#chroot_execute "dpkg -i /root/dropbear-bin_2018.76-5_amd64.deb"
|
||||
#chroot_execute "dpkg -i /root/dropbear-initramfs_2018.76-5_all.deb"
|
||||
|
||||
rm $c_zfs_mount_dir/root/*.deb
|
||||
cd /root
|
||||
fi
|
||||
#rm $c_zfs_mount_dir/root/*.deb
|
||||
#cd /root
|
||||
|
||||
echo "============setup root prompt============"
|
||||
cat > "$c_zfs_mount_dir/root/.bashrc" <<CONF
|
||||
@@ -796,35 +804,9 @@ CONF
|
||||
|
||||
echo "========running packages upgrade==========="
|
||||
chroot_execute "apt upgrade --yes"
|
||||
chroot_execute "apt purge cryptsetup* --yes"
|
||||
|
||||
echo "===========add static route to initramfs via hook to add default routes due to Ubuntu initramfs DHCP bug ========="
|
||||
mkdir -p "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount"
|
||||
cat > "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount/static-route" <<'CONF'
|
||||
#!/bin/sh
|
||||
PREREQ=""
|
||||
prereqs()
|
||||
{
|
||||
echo "$PREREQ"
|
||||
}
|
||||
|
||||
case $1 in
|
||||
prereqs)
|
||||
prereqs
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
. /scripts/functions
|
||||
# Begin real processing below this line
|
||||
|
||||
configure_networking
|
||||
|
||||
ip route add 172.31.1.1/255.255.255.255 dev ens3
|
||||
ip route add default via 172.31.1.1 dev ens3
|
||||
CONF
|
||||
|
||||
chmod 755 "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount/static-route"
|
||||
#echo "===========add static route to initramfs via hook to add default routes due to initramfs DHCP bug ========="
|
||||
# removed
|
||||
|
||||
echo "======= update initramfs =========="
|
||||
chroot_execute "update-initramfs -u -k all"
|
||||
@@ -833,12 +815,15 @@ echo "======= update grub =========="
|
||||
chroot_execute "update-grub"
|
||||
|
||||
echo "======= setting up zed =========="
|
||||
|
||||
chroot_execute "zfs set canmount=noauto $v_rpool_name"
|
||||
if [[ $v_zfs_experimental == "1" ]]; then
|
||||
chroot_execute "zfs set canmount=noauto rpool"
|
||||
else
|
||||
initial_load_debian_zed_cache
|
||||
fi
|
||||
|
||||
echo "======= setting mountpoints =========="
|
||||
chroot_execute "zfs set mountpoint=legacy $v_bpool_name/BOOT/ubuntu"
|
||||
chroot_execute "echo $v_bpool_name/BOOT/ubuntu /boot zfs nodev,relatime,x-systemd.requires=zfs-mount.service,x-systemd.device-timeout=10 0 0 > /etc/fstab"
|
||||
chroot_execute "echo $v_bpool_name/BOOT/ubuntu /boot zfs nodev,relatime,x-systemd.requires=zfs-import-bpool.service 0 0 > /etc/fstab"
|
||||
|
||||
chroot_execute "zfs set mountpoint=legacy $v_rpool_name/var/log"
|
||||
chroot_execute "echo $v_rpool_name/var/log /var/log zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
@@ -850,10 +835,7 @@ chroot_execute "zfs set mountpoint=legacy $v_rpool_name/tmp"
|
||||
chroot_execute "echo $v_rpool_name/tmp /tmp zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
|
||||
echo "========= add swap, if defined"
|
||||
if [[ $v_swap_size -gt 0 ]]; then
|
||||
chroot_execute "echo /dev/zvol/$v_rpool_name/swap none swap discard 0 0 >> /etc/fstab"
|
||||
fi
|
||||
|
||||
[[ $v_swap_size -gt 0 ]] && chroot_execute "echo /dev/zvol/$v_rpool_name/swap none swap discard 0 0 >> /etc/fstab" || true
|
||||
chroot_execute "echo RESUME=none > /etc/initramfs-tools/conf.d/resume"
|
||||
|
||||
echo "======= unmounting filesystems and zfs pools =========="
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
: <<'end_header_info'
|
||||
(c) Andrey Prokopenko job@terem.fr
|
||||
fully automatic script to install Debian 11 with ZFS root on Hetzner VPS
|
||||
fully automatic script to install Debian 10 with ZFS root on Hetzner VPS
|
||||
WARNING: all data on the disk will be destroyed
|
||||
How to use: add SSH key to the rescue console, set it OS to linux64, then press "mount rescue and power cycle" button
|
||||
How to use: add SSH key to the rescue console, set it OS to linux64, then press mount rescue and power sysle
|
||||
Next, connect via SSH to console, and run the script
|
||||
Answer script questions about desired hostname, ZFS ARC cache size et cetera
|
||||
Answer script questions about desired hostname and ZFS ARC cache size
|
||||
To cope with network failures its higly recommended to run the script inside screen console
|
||||
screen -dmS zfs
|
||||
screen -r zfs
|
||||
@@ -17,8 +17,6 @@ set -o errexit
|
||||
set -o pipefail
|
||||
set -o nounset
|
||||
|
||||
export TMPDIR=/tmp
|
||||
|
||||
# Variables
|
||||
v_bpool_name=
|
||||
v_bpool_tweaks=
|
||||
@@ -37,12 +35,12 @@ v_zfs_experimental=
|
||||
v_suitable_disks=()
|
||||
|
||||
# Constants
|
||||
c_deb_packages_repo=https://mirror.hetzner.com/debian/packages
|
||||
c_deb_security_repo=https://mirror.hetzner.com/debian/security
|
||||
c_deb_packages_repo=http://deb.debian.org/debian
|
||||
c_deb_security_repo=http://deb.debian.org/debian-security/
|
||||
|
||||
c_default_zfs_arc_max_mb=250
|
||||
c_default_bpool_tweaks="-o ashift=12 -O compression=lz4"
|
||||
c_default_rpool_tweaks="-o ashift=12 -O acltype=posixacl -O compression=zstd-9 -O dnodesize=auto -O relatime=on -O xattr=sa -O normalization=formD"
|
||||
c_default_rpool_tweaks="-o ashift=12 -O acltype=posixacl -O compression=lz4 -O dnodesize=auto -O relatime=on -O xattr=sa -O normalization=formD"
|
||||
c_default_hostname=terem
|
||||
c_zfs_mount_dir=/mnt
|
||||
c_log_dir=$(dirname "$(mktemp)")/zfs-hetzner-vm
|
||||
@@ -64,10 +62,7 @@ function print_step_info_header {
|
||||
###############################################################################
|
||||
# ${FUNCNAME[1]}"
|
||||
|
||||
if [[ "${1:-}" != "" ]]; then
|
||||
echo -n " $1"
|
||||
fi
|
||||
|
||||
[[ "${1:-}" != "" ]] && echo -n " $1" || true
|
||||
|
||||
echo "
|
||||
###############################################################################
|
||||
@@ -107,11 +102,11 @@ function display_intro_banner {
|
||||
print_step_info_header
|
||||
|
||||
local dialog_message='Hello!
|
||||
This script will prepare the ZFS pools, then install and configure minimal Debian 11 with ZFS root on Hetzner hosting VPS instance
|
||||
This script will prepare the ZFS pools, then install and configure minimal Debian 10 with ZFS root on Hetzner hosting VPS instance
|
||||
The script with minimal changes may be used on any other hosting provider supporting KVM virtualization and offering Debian-based rescue system.
|
||||
In order to stop the procedure, hit Esc twice during dialogs (excluding yes/no ones), or Ctrl+C while any operation is running.
|
||||
'
|
||||
dialog --msgbox "$dialog_message" 30 100
|
||||
dialog --ascii-lines --msgbox "$dialog_message" 30 100
|
||||
}
|
||||
|
||||
function store_os_distro_information {
|
||||
@@ -128,31 +123,32 @@ function check_prerequisites {
|
||||
echo 'This script must be run with administrative privileges!'
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -r /root/.ssh/authorized_keys ]]; then
|
||||
echo "SSH pubkey file is absent, please add it to the rescue system setting, then reboot into rescue system and run the script"
|
||||
exit 1
|
||||
fi
|
||||
if ! dpkg-query --showformat="\${Status}" -W dialog 2> /dev/null | grep -q "install ok installed"; then
|
||||
apt install --yes dialog
|
||||
fi
|
||||
# if [[ ! -r /root/.ssh/authorized_keys ]]; then
|
||||
# echo "SSH pubkey file is absent, please add it to the rescue system setting, then reboot into rescue system and run the script"
|
||||
# exit 1
|
||||
# fi
|
||||
# if ! dpkg-query --showformat="\${Status}" -W dialog 2> /dev/null | grep -q "install ok installed"; then
|
||||
# apt install --yes dialog
|
||||
# fi
|
||||
apt install --yes dialog software-properties-common wget debootstrap
|
||||
}
|
||||
|
||||
function initial_load_debian_zed_cache {
|
||||
chroot_execute "mkdir /etc/zfs/zfs-list.cache"
|
||||
chroot_execute "touch /etc/zfs/zfs-list.cache/$v_rpool_name"
|
||||
chroot_execute "ln -sf /usr/lib/zfs-linux/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d/"
|
||||
chroot_execute "touch /etc/zfs/zfs-list.cache/rpool"
|
||||
chroot_execute "ln -s /usr/lib/zfs-linux/zed.d/history_event-zfs-list-cacher.sh /etc/zfs/zed.d/"
|
||||
|
||||
chroot_execute "zed -F &"
|
||||
|
||||
local success=0
|
||||
|
||||
if [[ ! -e "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name" ]] || [[ -e "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name" && (( $(find "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name" -type f -printf '%s' 2> /dev/null) == 0 )) ]]; then
|
||||
chroot_execute "zfs set canmount=noauto $v_rpool_name"
|
||||
if [[ ! -e /mnt/etc/zfs/zfs-list.cache/rpool ]] || [[ -e /mnt/etc/zfs/zfs-list.cache/rpool && (( $(ls -l /mnt/etc/zfs/zfs-list.cache/rpool 2> /dev/null | cut -d ' ' -f 5) == 0 )) ]]; then
|
||||
chroot_execute "zfs set canmount=noauto rpool"
|
||||
|
||||
SECONDS=0
|
||||
|
||||
while (( SECONDS++ <= 120 )); do
|
||||
if [[ -e "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name" ]] && (( $(find "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name" -type f -printf '%s' 2> /dev/null) > 0 )); then
|
||||
if [[ -e /mnt/etc/zfs/zfs-list.cache/rpool ]] && (( "$(ls -l /mnt/etc/zfs/zfs-list.cache/rpool | cut -d ' ' -f 5)" > 0 )); then
|
||||
success=1
|
||||
break
|
||||
else
|
||||
@@ -170,7 +166,7 @@ function initial_load_debian_zed_cache {
|
||||
|
||||
chroot_execute "pkill zed"
|
||||
|
||||
sed -Ei "s|/$c_zfs_mount_dir/?|/|g" "$c_zfs_mount_dir/etc/zfs/zfs-list.cache/$v_rpool_name"
|
||||
sed -Ei 's|/mnt/?|/|g' /mnt/etc/zfs/zfs-list.cache/rpool
|
||||
}
|
||||
|
||||
function find_suitable_disks {
|
||||
@@ -215,7 +211,7 @@ LOG
|
||||
|
||||
If you think this is a bug, please open an issue on https://github.com/terem42/zfs-hetzner-vm/issues, and attach the file `'"$c_disks_log"'`.
|
||||
'
|
||||
dialog --msgbox "$dialog_message" 30 100
|
||||
dialog --ascii-lines --msgbox "$dialog_message" 30 100
|
||||
|
||||
exit 1
|
||||
fi
|
||||
@@ -244,7 +240,7 @@ function select_disks {
|
||||
|
||||
Devices with mounted partitions, cdroms, and removable devices are not displayed!
|
||||
"
|
||||
mapfile -t v_selected_disks < <(dialog --separate-output --checklist "$dialog_message" 30 100 $((${#menu_entries_option[@]} / 3)) "${menu_entries_option[@]}" 3>&1 1>&2 2>&3)
|
||||
mapfile -t v_selected_disks < <(dialog --ascii-lines --separate-output --checklist "$dialog_message" 30 100 $((${#menu_entries_option[@]} / 3)) "${menu_entries_option[@]}" 3>&1 1>&2 2>&3)
|
||||
|
||||
if [[ ${#v_selected_disks[@]} -gt 0 ]]; then
|
||||
break
|
||||
@@ -261,7 +257,7 @@ function ask_swap_size {
|
||||
local swap_size_invalid_message=
|
||||
|
||||
while [[ ! $v_swap_size =~ ^[0-9]+$ ]]; do
|
||||
v_swap_size=$(dialog --inputbox "${swap_size_invalid_message}Enter the swap size in GiB (0 for no swap):" 30 100 2 3>&1 1>&2 2>&3)
|
||||
v_swap_size=$(dialog --ascii-lines --inputbox "${swap_size_invalid_message}Enter the swap size in GiB (0 for no swap):" 30 100 2 3>&1 1>&2 2>&3)
|
||||
|
||||
swap_size_invalid_message="Invalid swap size! "
|
||||
done
|
||||
@@ -276,7 +272,7 @@ function ask_free_tail_space {
|
||||
local tail_space_invalid_message=
|
||||
|
||||
while [[ ! $v_free_tail_space =~ ^[0-9]+$ ]]; do
|
||||
v_free_tail_space=$(dialog --inputbox "${tail_space_invalid_message}Enter the space to leave at the end of each disk (0 for none):" 30 100 0 3>&1 1>&2 2>&3)
|
||||
v_free_tail_space=$(dialog --ascii-lines --inputbox "${tail_space_invalid_message}Enter the space to leave at the end of each disk (0 for none):" 30 100 0 3>&1 1>&2 2>&3)
|
||||
|
||||
tail_space_invalid_message="Invalid size! "
|
||||
done
|
||||
@@ -291,7 +287,7 @@ function ask_zfs_arc_max_size {
|
||||
local zfs_arc_max_invalid_message=
|
||||
|
||||
while [[ ! $v_zfs_arc_max_mb =~ ^[0-9]+$ ]]; do
|
||||
v_zfs_arc_max_mb=$(dialog --inputbox "${zfs_arc_max_invalid_message}Enter ZFS ARC cache max size in Mb (minimum 64Mb, enter 0 for ZFS default value, the default will take up to 50% of memory):" 30 100 "$c_default_zfs_arc_max_mb" 3>&1 1>&2 2>&3)
|
||||
v_zfs_arc_max_mb=$(dialog --ascii-lines --inputbox "${zfs_arc_max_invalid_message}Enter ZFS ARC cache max size in Mb (minimum 64Mb, enter 0 for ZFS default value, the default will take up to 50% of memory):" 30 100 "$c_default_zfs_arc_max_mb" 3>&1 1>&2 2>&3)
|
||||
|
||||
zfs_arc_max_invalid_message="Invalid size! "
|
||||
done
|
||||
@@ -307,14 +303,14 @@ function ask_pool_names {
|
||||
local bpool_name_invalid_message=
|
||||
|
||||
while [[ ! $v_bpool_name =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_bpool_name=$(dialog --inputbox "${bpool_name_invalid_message}Insert the name for the boot pool" 30 100 bpool 3>&1 1>&2 2>&3)
|
||||
v_bpool_name=$(dialog --ascii-lines --inputbox "${bpool_name_invalid_message}Insert the name for the boot pool" 30 100 bpool 3>&1 1>&2 2>&3)
|
||||
|
||||
bpool_name_invalid_message="Invalid pool name! "
|
||||
done
|
||||
local rpool_name_invalid_message=
|
||||
|
||||
while [[ ! $v_rpool_name =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_rpool_name=$(dialog --inputbox "${rpool_name_invalid_message}Insert the name for the root pool" 30 100 rpool 3>&1 1>&2 2>&3)
|
||||
v_rpool_name=$(dialog --ascii-lines --inputbox "${rpool_name_invalid_message}Insert the name for the root pool" 30 100 rpool 3>&1 1>&2 2>&3)
|
||||
|
||||
rpool_name_invalid_message="Invalid pool name! "
|
||||
done
|
||||
@@ -326,8 +322,8 @@ function ask_pool_tweaks {
|
||||
# shellcheck disable=SC2119
|
||||
print_step_info_header
|
||||
|
||||
v_bpool_tweaks=$(dialog --inputbox "Insert the tweaks for the boot pool" 30 100 -- "$c_default_bpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
v_rpool_tweaks=$(dialog --inputbox "Insert the tweaks for the root pool" 30 100 -- "$c_default_rpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
v_bpool_tweaks=$(dialog --ascii-lines --inputbox "Insert the tweaks for the boot pool" 30 100 -- "$c_default_bpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
v_rpool_tweaks=$(dialog --ascii-lines --inputbox "Insert the tweaks for the root pool" 30 100 -- "$c_default_rpool_tweaks" 3>&1 1>&2 2>&3)
|
||||
|
||||
print_variables v_bpool_tweaks v_rpool_tweaks
|
||||
}
|
||||
@@ -342,8 +338,8 @@ function ask_root_password {
|
||||
local password_repeat=-
|
||||
|
||||
while [[ "$v_root_password" != "$password_repeat" || "$v_root_password" == "" ]]; do
|
||||
v_root_password=$(dialog --passwordbox "${password_invalid_message}Please enter the root account password (can't be empty):" 30 100 3>&1 1>&2 2>&3)
|
||||
password_repeat=$(dialog --passwordbox "Please repeat the password:" 30 100 3>&1 1>&2 2>&3)
|
||||
v_root_password=$(dialog --ascii-lines --passwordbox "${password_invalid_message}Please enter the root account password (can't be empty):" 30 100 3>&1 1>&2 2>&3)
|
||||
password_repeat=$(dialog --ascii-lines --passwordbox "Please repeat the password:" 30 100 3>&1 1>&2 2>&3)
|
||||
|
||||
password_invalid_message="Passphrase empty, or not matching! "
|
||||
done
|
||||
@@ -353,7 +349,7 @@ function ask_root_password {
|
||||
function ask_encryption {
|
||||
print_step_info_header
|
||||
|
||||
if dialog --defaultno --yesno 'Do you want to encrypt the root pool?' 30 100; then
|
||||
if dialog --ascii-lines --yesno 'Do you want to encrypt the root pool?' 30 100; then
|
||||
v_encrypt_rpool=1
|
||||
fi
|
||||
set +x
|
||||
@@ -361,8 +357,8 @@ function ask_encryption {
|
||||
local passphrase_invalid_message=
|
||||
local passphrase_repeat=-
|
||||
while [[ "$v_passphrase" != "$passphrase_repeat" || ${#v_passphrase} -lt 8 ]]; do
|
||||
v_passphrase=$(dialog --passwordbox "${passphrase_invalid_message}Please enter the passphrase for the root pool (8 chars min.):" 30 100 3>&1 1>&2 2>&3)
|
||||
passphrase_repeat=$(dialog --passwordbox "Please repeat the passphrase:" 30 100 3>&1 1>&2 2>&3)
|
||||
v_passphrase=$(dialog --ascii-lines --passwordbox "${passphrase_invalid_message}Please enter the passphrase for the root pool (8 chars min.):" 30 100 3>&1 1>&2 2>&3)
|
||||
passphrase_repeat=$(dialog --ascii-lines --passwordbox "Please repeat the passphrase:" 30 100 3>&1 1>&2 2>&3)
|
||||
|
||||
passphrase_invalid_message="Passphrase too short, or not matching! "
|
||||
done
|
||||
@@ -373,7 +369,7 @@ function ask_encryption {
|
||||
function ask_zfs_experimental {
|
||||
print_step_info_header
|
||||
|
||||
if dialog --defaultno --yesno 'Do you want to use experimental zfs module build?' 30 100; then
|
||||
if dialog --ascii-lines --yesno 'Do you want to use experimental zfs module build?' 30 100; then
|
||||
v_zfs_experimental=1
|
||||
fi
|
||||
}
|
||||
@@ -384,8 +380,8 @@ function ask_hostname {
|
||||
|
||||
local hostname_invalid_message=
|
||||
|
||||
while [[ ! $v_hostname =~ ^[a-z][a-zA-Z0-9_:.-]+$ ]]; do
|
||||
v_hostname=$(dialog --inputbox "${hostname_invalid_message}Set the host name" 30 100 "$c_default_hostname" 3>&1 1>&2 2>&3)
|
||||
while [[ ! $v_hostname =~ ^[a-z][a-zA-Z_:.-]+$ ]]; do
|
||||
v_hostname=$(dialog --ascii-lines --inputbox "${hostname_invalid_message}Set the host name" 30 100 "$c_default_hostname" 3>&1 1>&2 2>&3)
|
||||
|
||||
hostname_invalid_message="Invalid host name! "
|
||||
done
|
||||
@@ -400,7 +396,7 @@ function determine_kernel_variant {
|
||||
}
|
||||
|
||||
function chroot_execute {
|
||||
chroot $c_zfs_mount_dir bash -c "DEBIAN_FRONTEND=noninteractive $1"
|
||||
chroot $c_zfs_mount_dir bash -c "$1"
|
||||
}
|
||||
|
||||
function unmount_and_export_fs {
|
||||
@@ -436,8 +432,9 @@ function unmount_and_export_fs {
|
||||
zpools_exported=99
|
||||
echo "===========exporting zfs pools============="
|
||||
set +e
|
||||
while (( zpools_exported == 99 )) && (( SECONDS++ <= 60 )); do
|
||||
if zpool export -a 2> /dev/null; then
|
||||
while (( zpools_exported == 99 )) && (( SECONDS++ <= 60 )); do
|
||||
zpool export -a 2> /dev/null
|
||||
if [[ $? == 0 ]]; then
|
||||
zpools_exported=1
|
||||
echo "all zfs pools were succesfully exported"
|
||||
break;
|
||||
@@ -454,7 +451,6 @@ function unmount_and_export_fs {
|
||||
|
||||
#################### MAIN ################################
|
||||
export LC_ALL=en_US.UTF-8
|
||||
export NCURSES_NO_UTF8_ACS=1
|
||||
|
||||
check_prerequisites
|
||||
|
||||
@@ -494,22 +490,15 @@ for kver in $(find /lib/modules/* -maxdepth 0 -type d | grep -v "$(uname -r)" |
|
||||
apt purge --yes "linux-image-$kver"
|
||||
done
|
||||
|
||||
echo "======= installing zfs on rescue system =========="
|
||||
echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections
|
||||
# echo "y" | zfs
|
||||
# linux-headers-generic linux-image-generic
|
||||
apt install --yes software-properties-common dpkg-dev dkms
|
||||
rm -f "$(which zfs)"
|
||||
rm -f "$(which zpool)"
|
||||
echo -e "deb http://deb.debian.org/debian/ testing main contrib non-free\ndeb http://deb.debian.org/debian/ testing main contrib non-free\n" >/etc/apt/sources.list.d/bookworm-testing.list
|
||||
echo -e "Package: src:zfs-linux\nPin: release n=testing\nPin-Priority: 990\n" > /etc/apt/preferences.d/90_zfs
|
||||
apt update
|
||||
apt install -t testing --yes zfs-dkms zfsutils-linux
|
||||
rm /etc/apt/sources.list.d/bookworm-testing.list
|
||||
rm /etc/apt/preferences.d/90_zfs
|
||||
apt update
|
||||
export PATH=$PATH:/usr/sbin
|
||||
zfs --version
|
||||
echo "======= installing zfs stable on live system =========="
|
||||
wget -O - https://apt.terem.fr/apt_pub.gpg | apt-key add -
|
||||
add-apt-repository 'deb [arch=amd64] http://apt.terem.fr/public zfs-debian main'
|
||||
apt update
|
||||
echo 'zfs-dkms zfs-dkms/note-incompatible-licenses note true' | debconf-set-selections
|
||||
apt install --yes libelf-dev
|
||||
apt install -t zfs-debian --yes zfs-dkms zfsutils-linux
|
||||
modprobe zfs
|
||||
zfs --version
|
||||
|
||||
echo "======= partitioning the disk =========="
|
||||
|
||||
@@ -520,9 +509,9 @@ echo "======= partitioning the disk =========="
|
||||
fi
|
||||
|
||||
for selected_disk in "${v_selected_disks[@]}"; do
|
||||
wipefs --all --force "$selected_disk"
|
||||
wipefs --all "$selected_disk"
|
||||
sgdisk -a1 -n1:24K:+1000K -t1:EF02 "$selected_disk"
|
||||
sgdisk -n2:0:+2G -t2:BF01 "$selected_disk" # Boot pool
|
||||
sgdisk -n2:0:+512M -t2:BF01 "$selected_disk" # Boot pool
|
||||
sgdisk -n3:0:"$tail_space_parameter" -t3:BF01 "$selected_disk" # Root pool
|
||||
done
|
||||
|
||||
@@ -549,19 +538,17 @@ echo "======= create zfs pools and datasets =========="
|
||||
pools_mirror_option=
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
zpool create \
|
||||
$v_bpool_tweaks -O canmount=off -O devices=off \
|
||||
-o cachefile=/etc/zpool.cache \
|
||||
-o cachefile=/etc/zfs/zpool.cache \
|
||||
-O mountpoint=/boot -R $c_zfs_mount_dir -f \
|
||||
$v_bpool_name $pools_mirror_option "${bpool_disks_partitions[@]}"
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
echo -n "$v_passphrase" | zpool create \
|
||||
$v_rpool_tweaks \
|
||||
-o cachefile=/etc/zpool.cache \
|
||||
"${encryption_options[@]}" \
|
||||
-O mountpoint=/ -R $c_zfs_mount_dir -f \
|
||||
-o cachefile=/etc/zfs/zpool.cache \
|
||||
$v_rpool_name $pools_mirror_option "${rpool_disks_partitions[@]}"
|
||||
|
||||
zfs create -o canmount=off -o mountpoint=none "$v_rpool_name/ROOT"
|
||||
@@ -570,11 +557,13 @@ zfs create -o canmount=off -o mountpoint=none "$v_bpool_name/BOOT"
|
||||
zfs create -o canmount=noauto -o mountpoint=/ "$v_rpool_name/ROOT/debian"
|
||||
zfs mount "$v_rpool_name/ROOT/debian"
|
||||
|
||||
zfs create -o canmount=noauto -o mountpoint=/boot "$v_bpool_name/BOOT/debian"
|
||||
zfs mount "$v_bpool_name/BOOT/debian"
|
||||
zfs create -o canmount=noauto -o mountpoint=/boot "$v_bpool_name/BOOT/ubuntu"
|
||||
zfs mount "$v_bpool_name/BOOT/ubuntu"
|
||||
|
||||
zfs create "$v_rpool_name/home"
|
||||
zfs create -o mountpoint=/root "$v_rpool_name/home/root"
|
||||
zfs create -o canmount=off "$v_rpool_name/var"
|
||||
zfs create -o canmount=off "$v_rpool_name/var/lib"
|
||||
zfs create "$v_rpool_name/var/log"
|
||||
zfs create "$v_rpool_name/var/spool"
|
||||
|
||||
@@ -599,12 +588,12 @@ if [[ $v_swap_size -gt 0 ]]; then
|
||||
"$v_rpool_name/swap"
|
||||
|
||||
udevadm settle
|
||||
|
||||
|
||||
mkswap -f "/dev/zvol/$v_rpool_name/swap"
|
||||
fi
|
||||
|
||||
echo "======= setting up initial system packages =========="
|
||||
debootstrap --arch=amd64 bullseye "$c_zfs_mount_dir" "$c_deb_packages_repo"
|
||||
debootstrap --arch=amd64 bullseye "$c_zfs_mount_dir" "$c_deb_packages_repo"
|
||||
|
||||
zfs set devices=off "$v_rpool_name"
|
||||
|
||||
@@ -625,7 +614,7 @@ ff02::2 ip6-allrouters
|
||||
ff02::3 ip6-allhosts
|
||||
CONF
|
||||
|
||||
ip6addr_prefix=$(ip -6 a s | grep -E "inet6.+global" | sed -nE 's/.+inet6\s(([0-9a-z]{1,4}:){4,4}).+/\1/p' | head -n 1)
|
||||
ip6addr=$(ip -6 a s | grep -E "inet6.+scope.+link" | sed -nE 's/.+inet6\s(([0-9a-z]{4,4}:{0,2}){5,5}\/[0-9]{2,2}).+/\1/p')
|
||||
|
||||
cat <<CONF > /mnt/etc/systemd/network/10-eth0.network
|
||||
[Match]
|
||||
@@ -633,13 +622,15 @@ Name=eth0
|
||||
|
||||
[Network]
|
||||
DHCP=ipv4
|
||||
Address=${ip6addr_prefix}:1/64
|
||||
|
||||
Address=${ip6addr}
|
||||
Gateway=fe80::1
|
||||
CONF
|
||||
chroot_execute "systemctl enable systemd-networkd.service"
|
||||
chroot_execute "systemctl enable systemd-resolved.service"
|
||||
|
||||
#cp /etc/resolv.conf $c_zfs_mount_dir/etc/resolv.conf
|
||||
chroot_execute "systemctl enable systemd-networkd.service"
|
||||
|
||||
|
||||
cp /etc/resolv.conf $c_zfs_mount_dir/etc/resolv.conf
|
||||
|
||||
echo "======= preparing the jail for chroot =========="
|
||||
for virtual_fs_dir in proc sys dev; do
|
||||
@@ -657,7 +648,7 @@ CONF
|
||||
chroot_execute "apt update"
|
||||
|
||||
echo "======= setting locale, console and language =========="
|
||||
chroot_execute "apt install --yes -qq locales debconf-i18n apt-utils"
|
||||
chroot_execute "DEBIAN_FRONTEND=noninteractive apt install --yes -qq locales debconf-i18n apt-utils keyboard-configuration console-setup"
|
||||
sed -i 's/# en_US.UTF-8/en_US.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
sed -i 's/# fr_FR.UTF-8/fr_FR.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
sed -i 's/# fr_FR.UTF-8/fr_FR.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
@@ -667,15 +658,15 @@ sed -i 's/# de_DE.UTF-8/de_DE.UTF-8/' "$c_zfs_mount_dir/etc/locale.gen"
|
||||
chroot_execute 'cat <<CONF | debconf-set-selections
|
||||
locales locales/default_environment_locale select en_US.UTF-8
|
||||
keyboard-configuration keyboard-configuration/store_defaults_in_debconf_db boolean true
|
||||
keyboard-configuration keyboard-configuration/variant select German
|
||||
keyboard-configuration keyboard-configuration/variant select English
|
||||
keyboard-configuration keyboard-configuration/unsupported_layout boolean true
|
||||
keyboard-configuration keyboard-configuration/modelcode string pc105
|
||||
keyboard-configuration keyboard-configuration/unsupported_config_layout boolean true
|
||||
keyboard-configuration keyboard-configuration/layout select German
|
||||
keyboard-configuration keyboard-configuration/layoutcode string de
|
||||
keyboard-configuration keyboard-configuration/layout select English
|
||||
keyboard-configuration keyboard-configuration/layoutcode string en
|
||||
keyboard-configuration keyboard-configuration/optionscode string
|
||||
keyboard-configuration keyboard-configuration/toggle select No toggling
|
||||
keyboard-configuration keyboard-configuration/xkb-keymap select de
|
||||
keyboard-configuration keyboard-configuration/xkb-keymap select en
|
||||
keyboard-configuration keyboard-configuration/switch select No temporary switch
|
||||
keyboard-configuration keyboard-configuration/unsupported_config_options boolean true
|
||||
keyboard-configuration keyboard-configuration/ctrl_alt_bksp boolean false
|
||||
@@ -699,7 +690,6 @@ CONF'
|
||||
|
||||
chroot_execute "dpkg-reconfigure locales -f noninteractive"
|
||||
echo -e "LC_ALL=en_US.UTF-8\nLANG=en_US.UTF-8\n" >> "$c_zfs_mount_dir/etc/environment"
|
||||
chroot_execute "apt install -qq --yes keyboard-configuration console-setup"
|
||||
chroot_execute "dpkg-reconfigure keyboard-configuration -f noninteractive"
|
||||
chroot_execute "dpkg-reconfigure console-setup -f noninteractive"
|
||||
chroot_execute "setupcon"
|
||||
@@ -708,35 +698,30 @@ chroot_execute "rm -f /etc/localtime /etc/timezone"
|
||||
chroot_execute "dpkg-reconfigure tzdata -f noninteractive "
|
||||
|
||||
echo "======= installing latest kernel============="
|
||||
chroot_execute "apt install --yes linux-image${v_kernel_variant}-amd64 linux-headers${v_kernel_variant}-amd64"
|
||||
chroot_execute "apt install --yes -t bullseye-backports linux-image${v_kernel_variant}-amd64 linux-headers${v_kernel_variant}-amd64"
|
||||
|
||||
echo "======= installing aux packages =========="
|
||||
chroot_execute "apt install --yes man wget curl software-properties-common nano htop gnupg"
|
||||
|
||||
echo "======= installing zfs packages =========="
|
||||
chroot_execute 'echo "zfs-dkms zfs-dkms/note-incompatible-licenses note true" | debconf-set-selections'
|
||||
|
||||
chroot_execute "bash -c \"echo 'zfs-dkms zfs-dkms/note-incompatible-licenses note true' | debconf-set-selections\""
|
||||
if [[ $v_zfs_experimental == "1" ]]; then
|
||||
chroot_execute "wget -O - https://terem42.github.io/zfs-debian/apt_pub.gpg | apt-key add -"
|
||||
chroot_execute "add-apt-repository 'deb https://terem42.github.io/zfs-debian/public zfs-debian-experimental main'"
|
||||
chroot_execute "apt install software-properties-common"
|
||||
chroot_execute "wget -O - https://apt.terem.fr/apt_pub.gpg | apt-key add -"
|
||||
chroot_execute "add-apt-repository 'deb [arch=amd64] http://apt.terem.fr/public zfs-debian main'"
|
||||
chroot_execute "apt update"
|
||||
chroot_execute "apt install -t zfs-debian-experimental --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
chroot_execute "apt install -t zfs-debian --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
else
|
||||
chroot_execute "apt install -t bullseye-backports --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
chroot_execute "apt install --yes zfs-initramfs zfs-dkms zfsutils-linux"
|
||||
fi
|
||||
chroot_execute 'cat << DKMS > /etc/dkms/zfs.conf
|
||||
# override for /usr/src/zfs-*/dkms.conf:
|
||||
# always rebuild initrd when zfs module has been changed
|
||||
# (either by a ZFS update or a new kernel version)
|
||||
REMAKE_INITRD="yes"
|
||||
DKMS'
|
||||
|
||||
echo "======= installing OpenSSH and network tooling =========="
|
||||
chroot_execute "apt install --yes openssh-server net-tools"
|
||||
|
||||
echo "======= setup OpenSSH =========="
|
||||
mkdir -p "$c_zfs_mount_dir/root/.ssh/"
|
||||
cp /root/.ssh/authorized_keys "$c_zfs_mount_dir/root/.ssh/authorized_keys"
|
||||
wget https://raw.githubusercontent.com/terem42/zfs-hetzner-vm/vmtest/authorized_keys -O "$c_zfs_mount_dir/root/.ssh/authorized_keys"
|
||||
#cp /root/.ssh/authorized_keys "$c_zfs_mount_dir/root/.ssh/authorized_keys"
|
||||
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' "$c_zfs_mount_dir/etc/ssh/sshd_config"
|
||||
sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/g' "$c_zfs_mount_dir/etc/ssh/sshd_config"
|
||||
chroot_execute "rm /etc/ssh/ssh_host_*"
|
||||
@@ -747,22 +732,19 @@ chroot_execute "echo root:$(printf "%q" "$v_root_password") | chpasswd"
|
||||
|
||||
echo "======= setting up zfs cache =========="
|
||||
|
||||
cp /etc/zpool.cache /mnt/etc/zfs/zpool.cache
|
||||
cp /etc/zfs/zpool.cache "$c_zfs_mount_dir/etc/zfs/zpool.cache"
|
||||
|
||||
echo "========setting up zfs module parameters========"
|
||||
chroot_execute "echo options zfs zfs_arc_max=$((v_zfs_arc_max_mb * 1024 * 1024)) >> /etc/modprobe.d/zfs.conf"
|
||||
|
||||
echo "======= setting up grub =========="
|
||||
chroot_execute "echo 'grub-pc grub-pc/install_devices_empty boolean true' | debconf-set-selections"
|
||||
chroot_execute "apt install --yes grub-legacy"
|
||||
chroot_execute "apt install --yes grub-pc"
|
||||
for disk in ${v_selected_disks[@]}; do
|
||||
chroot_execute "grub-install --recheck $disk"
|
||||
done
|
||||
chroot_execute "DEBIAN_FRONTEND=noninteractive apt install --yes grub-pc"
|
||||
chroot_execute "grub-install ${v_selected_disks[0]}"
|
||||
|
||||
chroot_execute "sed -i 's/#GRUB_TERMINAL=console/GRUB_TERMINAL=console/g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"net.ifnames=0\"|' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX=\"\"|GRUB_CMDLINE_LINUX=\"root=ZFS=$v_rpool_name/ROOT/debian\"|g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's|GRUB_CMDLINE_LINUX=\"\"|GRUB_CMDLINE_LINUX=\"root=ZFS=rpool/ROOT/debian\"|g' /etc/default/grub"
|
||||
|
||||
chroot_execute "sed -i 's/quiet//g' /etc/default/grub"
|
||||
chroot_execute "sed -i 's/splash//g' /etc/default/grub"
|
||||
@@ -776,23 +758,23 @@ if [[ $v_encrypt_rpool == "1" ]]; then
|
||||
echo "=========set up dropbear=============="
|
||||
|
||||
chroot_execute "apt install --yes dropbear-initramfs"
|
||||
|
||||
mkdir -p "$c_zfs_mount_dir/etc/dropbear/initramfs"
|
||||
cp /root/.ssh/authorized_keys "$c_zfs_mount_dir/etc/dropbear/initramfs/authorized_keys"
|
||||
|
||||
cp "$c_zfs_mount_dir/root/.ssh/authorized_keys" "$c_zfs_mount_dir/etc/dropbear-initramfs/authorized_keys"
|
||||
#cp /root/.ssh/authorized_keys "$c_zfs_mount_dir/etc/dropbear-initramfs/authorized_keys"
|
||||
|
||||
cp "$c_zfs_mount_dir/etc/ssh/ssh_host_rsa_key" "$c_zfs_mount_dir/etc/ssh/ssh_host_rsa_key_temp"
|
||||
chroot_execute "ssh-keygen -p -i -m pem -N '' -f /etc/ssh/ssh_host_rsa_key_temp"
|
||||
chroot_execute "/usr/lib/dropbear/dropbearconvert openssh dropbear /etc/ssh/ssh_host_rsa_key_temp /etc/dropbear/initramfs/dropbear_rsa_host_key"
|
||||
chroot_execute "/usr/lib/dropbear/dropbearconvert openssh dropbear /etc/ssh/ssh_host_rsa_key_temp /etc/dropbear-initramfs/dropbear_rsa_host_key"
|
||||
rm -rf "$c_zfs_mount_dir/etc/ssh/ssh_host_rsa_key_temp"
|
||||
|
||||
cp "$c_zfs_mount_dir/etc/ssh/ssh_host_ecdsa_key" "$c_zfs_mount_dir/etc/ssh/ssh_host_ecdsa_key_temp"
|
||||
chroot_execute "ssh-keygen -p -i -m pem -N '' -f /etc/ssh/ssh_host_ecdsa_key_temp"
|
||||
chroot_execute "/usr/lib/dropbear/dropbearconvert openssh dropbear /etc/ssh/ssh_host_ecdsa_key_temp /etc/dropbear/initramfs/dropbear_ecdsa_host_key"
|
||||
chroot_execute "/usr/lib/dropbear/dropbearconvert openssh dropbear /etc/ssh/ssh_host_ecdsa_key_temp /etc/dropbear-initramfs/dropbear_ecdsa_host_key"
|
||||
chroot_execute "rm -rf /etc/ssh/ssh_host_ecdsa_key_temp"
|
||||
rm -rf "$c_zfs_mount_dir/etc/ssh/ssh_host_ecdsa_key_temp"
|
||||
|
||||
rm -rf "$c_zfs_mount_dir/etc/dropbear/initramfs/dropbear_dss_host_key"
|
||||
fi
|
||||
rm -rf "$c_zfs_mount_dir/etc/dropbear-initramfs/dropbear_dss_host_key"
|
||||
fi
|
||||
|
||||
echo "============setup root prompt============"
|
||||
cat > "$c_zfs_mount_dir/root/.bashrc" <<CONF
|
||||
@@ -804,37 +786,9 @@ CONF
|
||||
|
||||
echo "========running packages upgrade==========="
|
||||
chroot_execute "apt upgrade --yes"
|
||||
chroot_execute "apt purge cryptsetup* --yes"
|
||||
|
||||
echo "===========add static route to initramfs via hook to add default routes for Hetzner due to Debian/Ubuntu initramfs DHCP bug ========="
|
||||
mkdir -p "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount"
|
||||
cat > "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount/static-route" <<'CONF'
|
||||
#!/bin/sh
|
||||
PREREQ=""
|
||||
prereqs()
|
||||
{
|
||||
echo "$PREREQ"
|
||||
}
|
||||
|
||||
case $1 in
|
||||
prereqs)
|
||||
prereqs
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
. /scripts/functions
|
||||
# Begin real processing below this line
|
||||
|
||||
configure_networking
|
||||
|
||||
ip route add 172.31.1.1/255.255.255.255 dev eth0
|
||||
ip route add default via 172.31.1.1 dev eth0
|
||||
CONF
|
||||
|
||||
chmod 755 "$c_zfs_mount_dir/usr/share/initramfs-tools/scripts/init-premount/static-route"
|
||||
|
||||
chmod 755 "$c_zfs_mount_dir/etc/network/interfaces"
|
||||
#echo "===========add static route to initramfs via hook to add default routes due to initramfs DHCP bug ========="
|
||||
# removed
|
||||
|
||||
echo "======= update initramfs =========="
|
||||
chroot_execute "update-initramfs -u -k all"
|
||||
@@ -844,14 +798,14 @@ chroot_execute "update-grub"
|
||||
|
||||
echo "======= setting up zed =========="
|
||||
if [[ $v_zfs_experimental == "1" ]]; then
|
||||
chroot_execute "zfs set canmount=noauto $v_rpool_name"
|
||||
chroot_execute "zfs set canmount=noauto rpool"
|
||||
else
|
||||
initial_load_debian_zed_cache
|
||||
fi
|
||||
|
||||
echo "======= setting mountpoints =========="
|
||||
chroot_execute "zfs set mountpoint=legacy $v_bpool_name/BOOT/debian"
|
||||
chroot_execute "echo $v_bpool_name/BOOT/debian /boot zfs nodev,relatime,x-systemd.requires=zfs-mount.service,x-systemd.device-timeout=10 0 0 > /etc/fstab"
|
||||
chroot_execute "zfs set mountpoint=legacy $v_bpool_name/BOOT/ubuntu"
|
||||
chroot_execute "echo $v_bpool_name/BOOT/ubuntu /boot zfs nodev,relatime,x-systemd.requires=zfs-mount.service,x-systemd.device-timeout=10 0 0 > /etc/fstab"
|
||||
|
||||
chroot_execute "zfs set mountpoint=legacy $v_rpool_name/var/log"
|
||||
chroot_execute "echo $v_rpool_name/var/log /var/log zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
@@ -863,10 +817,7 @@ chroot_execute "zfs set mountpoint=legacy $v_rpool_name/tmp"
|
||||
chroot_execute "echo $v_rpool_name/tmp /tmp zfs nodev,relatime 0 0 >> /etc/fstab"
|
||||
|
||||
echo "========= add swap, if defined"
|
||||
if [[ $v_swap_size -gt 0 ]]; then
|
||||
chroot_execute "echo /dev/zvol/$v_rpool_name/swap none swap discard 0 0 >> /etc/fstab"
|
||||
fi
|
||||
|
||||
[[ $v_swap_size -gt 0 ]] && chroot_execute "echo /dev/zvol/$v_rpool_name/swap none swap discard 0 0 >> /etc/fstab" || true
|
||||
chroot_execute "echo RESUME=none > /etc/initramfs-tools/conf.d/resume"
|
||||
|
||||
echo "======= unmounting filesystems and zfs pools =========="
|
||||
Reference in New Issue
Block a user