From f1bab6bc604a05b7a991a573afe7c58ef0173c42 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Wed, 1 Nov 2023 03:05:43 +0100 Subject: [PATCH 01/28] refactor(os): Simplify extended regex (#6) --- setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.sh b/setup.sh index fb31a51..c2e51d5 100644 --- a/setup.sh +++ b/setup.sh @@ -465,7 +465,7 @@ function add_zfs_hook_to_initramfs () { #1.16 # Add zfs hook, remove fsck hook from initramfs. sed -ri \ - -e 's'$'\x1''(HOOKS=)(.*?[\(| ])(filesystems)([\)| ][^\r\n\f]*)'$'\x1''\1\2zfs \3\4'$'\x1''g' \ + -e 's'$'\x1''(HOOKS=)(.*?[( ])(filesystems)([) ][^\r\n\f]*)'$'\x1''\1\2zfs \3\4'$'\x1''g' \ -e 's'$'\x1''((\()(fsck)(\)))'$'\x1''\2\4'$'\x1''g' \ -e 's'$'\x1''(([[:space:]]+)(fsck)|(fsck)([[:space:]]+))'$'\x1'''$'\x1''g' \ '/mnt/etc/mkinitcpio.conf' -- 2.47.2 From 4e734330dababa0aa76d488df81bc0f1d0d84d78 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Wed, 1 Nov 2023 03:47:34 +0100 Subject: [PATCH 02/28] feat(os): Add helper functions to manipulate HOOKS array (#6) --- setup.sh | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/setup.sh b/setup.sh index c2e51d5..1922387 100644 --- a/setup.sh +++ b/setup.sh @@ -461,6 +461,39 @@ function set_locale () { printf -- '%s\n' 'LANG=en_US.UTF-8' > '/mnt/etc/locale.conf' } +function in_file_in_array_insert_n_before_m () { + local arg_file arg_array arg_string arg_precede + arg_file="${1:?}" + arg_array="${2:?}" + arg_string="${3:?}" + arg_precede="${4:?}" + sed -ri \ + -e 's'$'\x1''('"${arg_array}"'=)(.*?[( ])('"${arg_precede}"')([) ][^\r\n\f]*)'$'\x1''\1\2'"${arg_string}"' \3\4'$'\x1''g' \ + "${arg_file}" +} + +function in_file_in_array_insert_n_at_the_end () { + local arg_file arg_array arg_string + arg_file="${1:?}" + arg_array="${2:?}" + arg_string="${3:?}" + sed -ri \ + -e 's'$'\x1''('"${arg_array}"'=)([^)]*)(\)[^\r\n\f]*)'$'\x1''\1\2 '"${arg_string}"'\3'$'\x1''g' \ + "${arg_file}" +} + +function in_file_in_array_remove_n () { + local arg_file arg_array arg_string + arg_file="${1:?}" + arg_array="${2:?}" + arg_string="${3:?}" + sed -ri \ + -e 's'$'\x1''((\()('"${arg_string}"')(\)))'$'\x1''\2\4'$'\x1''g' \ + -e 's'$'\x1''('"${arg_array}"'=.*?)([[:space:]]+'"${arg_string}"')([[:space:]]+|\))'$'\x1''\1\3'$'\x1''g' \ + -e 's'$'\x1''('"${arg_array}"'=.*?)([[:space:]]+|\()('"${arg_string}"'[[:space:]]+)'$'\x1''\1\2'$'\x1''g' \ + "${arg_file}" +} + function add_zfs_hook_to_initramfs () { #1.16 # Add zfs hook, remove fsck hook from initramfs. -- 2.47.2 From 33966071ce57f22b949de69ed1a16fc4497a8ffb Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Wed, 1 Nov 2023 03:49:05 +0100 Subject: [PATCH 03/28] refactor(os): Simplify mkinitcpio.conf manipulation (#6) --- setup.sh | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/setup.sh b/setup.sh index 1922387..acc3362 100644 --- a/setup.sh +++ b/setup.sh @@ -497,11 +497,8 @@ function in_file_in_array_remove_n () { function add_zfs_hook_to_initramfs () { #1.16 # Add zfs hook, remove fsck hook from initramfs. - sed -ri \ - -e 's'$'\x1''(HOOKS=)(.*?[( ])(filesystems)([) ][^\r\n\f]*)'$'\x1''\1\2zfs \3\4'$'\x1''g' \ - -e 's'$'\x1''((\()(fsck)(\)))'$'\x1''\2\4'$'\x1''g' \ - -e 's'$'\x1''(([[:space:]]+)(fsck)|(fsck)([[:space:]]+))'$'\x1'''$'\x1''g' \ - '/mnt/etc/mkinitcpio.conf' + in_file_in_array_insert_n_before_m '/mnt/etc/mkinitcpio.conf' 'HOOKS' 'zfs' 'filesystems' + in_file_in_array_remove_n '/mnt/etc/mkinitcpio.conf' 'HOOKS' 'fsck' # Also unless encryption's unwanted add plain text key file into # initramfs since it's living inside an encrypted pool anyway. [[ ! "${ARCHZBM_ZFSPROPS_NO_ENCRYPTION}" ]] && sed -ri \ -- 2.47.2 From 3cb68406ed7a3d84f7e3e9f7f8dc05dc63c0397f Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Wed, 1 Nov 2023 03:49:46 +0100 Subject: [PATCH 04/28] feat(os): Add SSH to ZBM if requested by user (#6) --- setup.sh | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/setup.sh b/setup.sh index acc3362..c6afad0 100644 --- a/setup.sh +++ b/setup.sh @@ -746,6 +746,32 @@ EOF zfs set org.zfsbootmenu:commandline='rw nowatchdog rd.vconsole.keymap=de-latin1' "${zpool_name}"'/root/'"${zfs_arch_dataset_name}" } +function we_want_ssh () { + #2.10 + if [[ "${ARCHZBM_NET_CLIENT_IP}" ]] || \ + [[ "${ARCHZBM_NET_SERVER_IP}" ]] || \ + [[ "${ARCHZBM_NET_GATEWAY_IP}" ]] || \ + [[ "${ARCHZBM_NET_NETMASK}" ]] || \ + [[ "${ARCHZBM_NET_HOSTNAME}" ]] || \ + [[ "${ARCHZBM_NET_DEVICE}" ]] || \ + [[ "${ARCHZBM_NET_AUTOCONF}" ]] || \ + [[ "${ARCHZBM_SSH_PORT}" ]] || \ + [[ "${ARCHZBM_SSH_KEEPALIVE_INTVL}" ]] || \ + [[ "${ARCHZBM_SSH_AUTH_KEYS}" ]]; then + >&3 printf -- '%s\n' 'Installing SSH in ZFSBootMenu' + return 0 + fi + >&3 printf -- '%s\n' 'Not installing SSH in ZFSBootMenu' + return 1 +} + +function configure_ssh_in_zbm () { + #2.11 + paru_install 'mkinitcpio-nfs-utils' 'dropbear' 'mkinitcpio-dropbear' + in_file_in_array_insert_n_at_the_end '/etc/zfsbootmenu/mkinitcpio.conf' 'HOOKS' 'net' + in_file_in_array_insert_n_at_the_end '/etc/zfsbootmenu/mkinitcpio.conf' 'HOOKS' 'dropbear' +} + function add_syslinux_pacman_hook () { mkdir -p '/opt/git/quico.space/quico-os-setup/zbm-syslinux-pacman-hook/branches/main' git -C '/opt/git/quico.space/quico-os-setup/zbm-syslinux-pacman-hook/branches/main' clone 'https://quico.space/quico-os-setup/zbm-syslinux-pacman-hook.git' . @@ -799,6 +825,9 @@ function install_os_in_chroot () { # Install ZFSBootMenu image configure_zfsbootmenu #2.9 + if we_want_ssh; then #2.10 + configure_ssh_in_zbm #2.11 + fi generate-zbm # Yes, we do this twice so we immediately get a functional backup file -- 2.47.2 From 9a89ce4f75493567ee57f0fbf6423dcfbd59d761 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Wed, 1 Nov 2023 03:53:18 +0100 Subject: [PATCH 05/28] fix(os): Remove zfsbootmenu hook from ZFSBootMenu (#6) While unintuitive this prevents us from having to move this hook to the end of the HOOKS array. If user wants SSH in ZBM we first append 'net' to the HOOKS array then append 'dropbear'. At this point the explicit 'zfsbootmenu' hook is no longer last in line in 'HOOKS' array. This causes ZBM to trip and to not correctly load net and dropbear. Since the 'zfsbootmenu' hook is added implicitly by generate-zbm we don't need the explicit hook at all. Better remove it. This way it doesn't get in the way. --- setup.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.sh b/setup.sh index c6afad0..db6ee60 100644 --- a/setup.sh +++ b/setup.sh @@ -704,6 +704,7 @@ EOF function configure_zfsbootmenu () { #2.9 paru_install 'zfsbootmenu' + in_file_in_array_remove_n '/etc/mkinitcpio.conf' 'HOOKS' 'zfsbootmenu' if [[ "${part_schema}" = 'gpt' ]]; then cat > '/etc/zfsbootmenu/config.yaml' < Date: Fri, 3 Nov 2023 01:37:15 +0100 Subject: [PATCH 06/28] feat(zbm): Add dropbear hook files (#6) --- setup.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/setup.sh b/setup.sh index db6ee60..a513e82 100644 --- a/setup.sh +++ b/setup.sh @@ -747,6 +747,13 @@ EOF zfs set org.zfsbootmenu:commandline='rw nowatchdog rd.vconsole.keymap=de-latin1' "${zpool_name}"'/root/'"${zfs_arch_dataset_name}" } +function get_dropbear_hooks () { + mkdir -p '/opt/git/quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook/branches/main' + git -C '/opt/git/quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook/branches/main' clone 'https://quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook.git' . + ln -s '/opt/git/quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook/branches/main/pacman-mkinitcpio-dropbear-hook.hook' '/usr/share/libalpm/hooks/pacman-mkinitcpio-dropbear-hook.hook' + ln -s '/opt/git/quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook/branches/main/pacman-mkinitcpio-dropbear-install.hook' '/usr/share/libalpm/hooks/pacman-mkinitcpio-dropbear-install.hook' +} + function we_want_ssh () { #2.10 if [[ "${ARCHZBM_NET_CLIENT_IP}" ]] || \ -- 2.47.2 From be668b1bdc92115f7e2bc3904a226bdce8c925a6 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Fri, 3 Nov 2023 01:37:38 +0100 Subject: [PATCH 07/28] feat(zbm): Add user's dropbear customizations (#6) --- setup.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/setup.sh b/setup.sh index a513e82..60855ea 100644 --- a/setup.sh +++ b/setup.sh @@ -754,6 +754,22 @@ function get_dropbear_hooks () { ln -s '/opt/git/quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook/branches/main/pacman-mkinitcpio-dropbear-install.hook' '/usr/share/libalpm/hooks/pacman-mkinitcpio-dropbear-install.hook' } +function customize_dropbear_hooks () { + local env_archzbm_ssh_port env_archzbm_ssh_keepalive_intvl + env_archzbm_ssh_port="${ARCHZBM_SSH_PORT:-22}" + env_archzbm_ssh_keepalive_intvl="${ARCHZBM_SSH_KEEPALIVE_INTVL:-1}" + if [[ "${env_archzbm_ssh_port}" -ne '22' ]] || [[ "${env_archzbm_ssh_keepalive_intvl}" -ne '1' ]]; then + paru_install 'rsync' + rsync -av '/opt/git/quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook/branches/main/dropbear_hook'{,'.override'}'.patch' + fi + if [[ "${env_archzbm_ssh_port}" -ne '22' ]]; then + sed -ri -e 's'$'\x1''-p [[:digit:]]+'$'\x1''-p '"${env_archzbm_ssh_port}"''$'\x1''g' '/opt/git/quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook/branches/main/dropbear_hook.override.patch' + fi + if [[ "${env_archzbm_ssh_keepalive_intvl}" -ne '1' ]]; then + sed -ri -e 's'$'\x1''-K [[:digit:]]+'$'\x1''-K '"${env_archzbm_ssh_keepalive_intvl}"''$'\x1''g' '/opt/git/quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook/branches/main/dropbear_hook.override.patch' + fi +} + function we_want_ssh () { #2.10 if [[ "${ARCHZBM_NET_CLIENT_IP}" ]] || \ -- 2.47.2 From 732cc47405a22eba0af4944ea03d806b9f7786b3 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Fri, 3 Nov 2023 01:38:11 +0100 Subject: [PATCH 08/28] feat(zbm): Add networking/IP addressing setup to ZBM (#6) --- setup.sh | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/setup.sh b/setup.sh index 60855ea..2cabc9d 100644 --- a/setup.sh +++ b/setup.sh @@ -770,6 +770,45 @@ function customize_dropbear_hooks () { fi } +function ensure_ip_in_kcl () { + local zbm_config kcl_length kcl_string default_ip ip_addr_found new_kcl first_kcl_elem + local -a kcl + paru_install 'go-yq' + + zbm_config='/etc/zfsbootmenu/config.yaml' + kcl_length="$(yq '.Kernel.CommandLine | length' "${zbm_config}")" + if [[ "${kcl_length}" -eq '0' ]]; then + >&3 printf -- '%s\n' \ + 'No .Kernel.CommandLine YAML element with content found in '"${zbm_config}"'. Exiting ...' + exit 77 + else + kcl_string="$(yq '.Kernel.CommandLine' "${zbm_config}")" + fi + + default_ip='ip='"${ARCHZBM_NET_CLIENT_IP}"':'"${ARCHZBM_NET_SERVER_IP}"':'"${ARCHZBM_NET_GATEWAY_IP}"':'"${ARCHZBM_NET_NETMASK}"':'"${ARCHZBM_NET_HOSTNAME}"':'"${ARCHZBM_NET_DEVICE}"':'"${ARCHZBM_NET_AUTOCONF}" + mapfile -t kcl < <(<<<"${kcl_string}" tr ' ' '\n' | sed '/^$/d') + for kcl_elem in "${!kcl[@]}"; do + if grep -Piq -- 'ip=' <<<"${kcl[$kcl_elem]}"; then + ip_addr_found='true' + kcl["${kcl_elem}"]="${default_ip}" + fi + done + if [[ ! "${ip_addr_found}" ]]; then + kcl+=("${default_ip}") + fi + new_kcl='' + first_kcl_elem='true' + for kcl_elem in "${kcl[@]}"; do + if [[ ! "${first_kcl_elem}" ]]; then + new_kcl+=' '"${kcl_elem}" + else + new_kcl+="${kcl_elem}" + unset -v first_kcl_elem + fi + done + yq -i '.Kernel.CommandLine = "'"${new_kcl}"'"' "${zbm_config}" +} + function we_want_ssh () { #2.10 if [[ "${ARCHZBM_NET_CLIENT_IP}" ]] || \ -- 2.47.2 From 16905181978567f3bbea0f8d62cb0e7eb706d5b9 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Fri, 3 Nov 2023 01:38:28 +0100 Subject: [PATCH 09/28] feat(zbm): Define Dropbear's SSH pub keys (#6) --- setup.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/setup.sh b/setup.sh index 2cabc9d..f7b74ed 100644 --- a/setup.sh +++ b/setup.sh @@ -809,6 +809,17 @@ function ensure_ip_in_kcl () { yq -i '.Kernel.CommandLine = "'"${new_kcl}"'"' "${zbm_config}" } +function set_pub_keys () { + local authorized_keys_file raw_pub_keys + authorized_keys_file="${1:?}" + raw_pub_keys="${2:?}" + :> "${authorized_keys_file}" + while IFS= read -r pub_key_line; do + printf -- '%s\n' "${pub_key_line}" >> "${authorized_keys_file}" + done < <(<<<"${raw_pub_keys}" sed -r -e 's/,,/\n/g') + sed -i '/^$/d' "${authorized_keys_file}" +} + function we_want_ssh () { #2.10 if [[ "${ARCHZBM_NET_CLIENT_IP}" ]] || \ -- 2.47.2 From b160b4a1e102f92eb992199a207d342ddcb726e5 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Fri, 3 Nov 2023 01:38:56 +0100 Subject: [PATCH 10/28] feat(zbm): Prepare SSH in ZBM (#6) --- setup.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/setup.sh b/setup.sh index f7b74ed..5d6da21 100644 --- a/setup.sh +++ b/setup.sh @@ -841,9 +841,16 @@ function we_want_ssh () { function configure_ssh_in_zbm () { #2.11 + get_dropbear_hooks + customize_dropbear_hooks paru_install 'mkinitcpio-nfs-utils' 'dropbear' 'mkinitcpio-dropbear' in_file_in_array_insert_n_at_the_end '/etc/zfsbootmenu/mkinitcpio.conf' 'HOOKS' 'net' in_file_in_array_insert_n_at_the_end '/etc/zfsbootmenu/mkinitcpio.conf' 'HOOKS' 'dropbear' + for key_type in 'dss' 'ecdsa' 'ed25519' 'rsa'; do + dropbearkey -t "${key_type}" -f '/etc/dropbear/dropbear_'"${key_type}"'_host_key' + done + set_pub_keys '/etc/dropbear/root_key' "${ARCHZBM_SSH_AUTH_KEYS}" + ensure_ip_in_kcl } function add_syslinux_pacman_hook () { -- 2.47.2 From 53f92032a499c6a190bcb6fcad7345071489f4f1 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Fri, 3 Nov 2023 01:40:24 +0100 Subject: [PATCH 11/28] feat(zbm): Add KCL to legacy BIOS ZBM (#6) --- setup.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.sh b/setup.sh index 5d6da21..2e13774 100644 --- a/setup.sh +++ b/setup.sh @@ -735,6 +735,7 @@ Components: Versions: false ImageDir: /boot/syslinux/zfsbootmenu Kernel: + CommandLine: ro loglevel=0 zbm.import_policy=hostid Prefix: vmlinuz EOF fi -- 2.47.2 From ab5e79d838a4f9a3b20c0ea32741030d33325400 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Fri, 3 Nov 2023 03:24:03 +0100 Subject: [PATCH 12/28] refactor(iso): Parallelize pacman in ISO (#6) --- setup.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.sh b/setup.sh index 2e13774..f1cca00 100644 --- a/setup.sh +++ b/setup.sh @@ -60,6 +60,7 @@ function resize_cow_space () { function update_pacman_db () { #1.4 + pacman_dl_parallel printf -- '%s\n' 'Refreshing mirror list ...' printf -- '%s\n' \ '--save /etc/pacman.d/mirrorlist' \ -- 2.47.2 From 003d3f4f2a342dbf4e7066cabbb645e5815a69ab Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Fri, 3 Nov 2023 03:24:33 +0100 Subject: [PATCH 13/28] fix(ZBM): Remove ZBM hook from correct file (#6) --- setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.sh b/setup.sh index f1cca00..f60c7c7 100644 --- a/setup.sh +++ b/setup.sh @@ -705,7 +705,7 @@ EOF function configure_zfsbootmenu () { #2.9 paru_install 'zfsbootmenu' - in_file_in_array_remove_n '/etc/mkinitcpio.conf' 'HOOKS' 'zfsbootmenu' + in_file_in_array_remove_n '/etc/zfsbootmenu/mkinitcpio.conf' 'HOOKS' 'zfsbootmenu' if [[ "${part_schema}" = 'gpt' ]]; then cat > '/etc/zfsbootmenu/config.yaml' < Date: Fri, 3 Nov 2023 23:43:06 +0100 Subject: [PATCH 14/28] fix(ZBM): No KCL inside Syslinux (#6) --- setup.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.sh b/setup.sh index f60c7c7..d5c7d85 100644 --- a/setup.sh +++ b/setup.sh @@ -736,7 +736,6 @@ Components: Versions: false ImageDir: /boot/syslinux/zfsbootmenu Kernel: - CommandLine: ro loglevel=0 zbm.import_policy=hostid Prefix: vmlinuz EOF fi -- 2.47.2 From 305e4191f1ad5aec2060690a7eb3999d689eb390 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 4 Nov 2023 00:00:03 +0100 Subject: [PATCH 15/28] docs(zfs): Correctly umount after maintenance (#6) --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index e5bd158..3d80471 100644 --- a/README.md +++ b/README.md @@ -498,7 +498,12 @@ arch-chroot /mnt /bin/bash When done exit `chroot` and cleanly remove your work: ``` +# UEFI system ... umount /mnt/efi + +# ... or legacy BIOS system +umount /mnt/boot/syslinux + zfs umount -a zpool export zpool ``` -- 2.47.2 From 3030eb0f2da7dacdf450e5d28eb8ddbe16cd8204 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 4 Nov 2023 00:01:29 +0100 Subject: [PATCH 16/28] docs(iso): Use either an env options file or shell exports (#6) --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 3d80471..2bb49c9 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,14 @@ The script will create a single ZFS zpool `zpool` on the zpool partition with da ## Options +The following options can be given either by exporting them as shell variables prior to script execution or in a file named `archzbm_settings.env` that lives in your current working directory where you're about to execute the script. File format is identical to shell variable assignments of the form `VAR=value` or `VAR='value'`. + +If `./archzbm_settings.env` exists the script will `source` its content and `export` all variables for use in future steps. + +In cases where a variable is both exported prior to script execution and specified in `archzbm_settings.env` the latter will override the former. + +Known options are as follows. + ### Compression By default we create a zpool with ZFS property `compression=on`. If the `lz4_compress` pool feature is active this will by default enable `compression=lz4`. See `man 7 zfsprops` for example in ZFS 2.1.9 for details. See `zpool get feature@lz4_compress ` to check this feature's status on your ``. -- 2.47.2 From 924925e08ed1552327da1d874f61402c1ec8a74d Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 4 Nov 2023 00:03:42 +0100 Subject: [PATCH 17/28] docs(iso): Do a pass over how we explain passwords for local accounts (#6) --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2bb49c9..da256ab 100644 --- a/README.md +++ b/README.md @@ -127,18 +127,16 @@ export ARCHZBM_ZFSPROPS_NO_ENCRYPTION=yup ### Passwords -By default both the zpool password and the account password for `root` are literally `password`. While you can certainly change these after initial system setup you can also optionally set these passwords in a settings file named `archzbm_settings.env` that lives in your current working directory where you're about to execute the script. File format is identical to shell variable assignments of the form `VAR=value` or `VAR='value'`. - -If `./archzbm_settings.env` exists the script will `source` its content and `export` all variables for use in future steps. Only known variables are: +By default both the zpool password and the account password for `root` are literally `password`. While you can certainly change these after initial system setup (see [Password change](#password-change)) you can also optionally set passwords as follows: ``` ARCHZBM_ZPOOL_PASSWORD='a fancy password' ARCHZBM_ROOT_PASSWORD='t0psecr3t!' ``` -> While the `root` password may be weak and `chpasswd` won't care do make sure to set a zpool password that meets ZFS' complexity rules. Per `man 7 zfsprops` section `keyformat` the only requirement is a length "between 8 and 512 bytes" (as in minimum 8 characters). If you pick a password that's too weak ZFS will reject zpool creation and very ungracefully derail the rest of this script. The script doesn't check what you're setting. +> While the `root` password is allowed to be weak and `chpasswd` won't care do make sure to set a zpool password that meets ZFS' complexity rules. Per `man 7 zfsprops` section `keyformat` the only requirement is a length "between 8 and 512 bytes" (as in minimum 8 characters). If you pick a password that's too weak ZFS will reject zpool creation and very ungracefully derail the rest of this script. The script doesn't check what you're setting. -The script does create a second user named `build` but doesn't set a password on account creation. As such no password variable can be set for it in `./archzbm_settings.env`. It's intended as a helper for system setup tasks such as `sudo -u build paru -S ` where an account password is irrelevant since `root` can always `sudo` whatever it wants. You will not be able to log in to the `build` account yourself although you certainly could set a password for it. Instead we suggest you create a proper user account for yourself. Your newly installed Arch Linux comes with an `/etc/motd` greeting that summarizes this as: +The script does create a second user named `build` but doesn't set a password on account creation. It's intended as a helper for system setup tasks such as `sudo -u build paru -S ` where an account password is irrelevant since `root` can always `sudo` whatever it wants. You will not be able to log in to the `build` account yourself although you certainly could set a password for it. Instead we suggest you create a proper user account for yourself. Your newly installed Arch Linux comes with an `/etc/motd` greeting that summarizes this as: ``` useradd --create-home --shell /bin/bash --user-group --groups wheel -- 2.47.2 From 7338924c82d43956796bd404bd39cf3aa8cb93d6 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 4 Nov 2023 00:08:48 +0100 Subject: [PATCH 18/28] docs(zbm): Explain networking and SSH (#6) --- README.md | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/README.md b/README.md index da256ab..b56f6b1 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,80 @@ useradd --create-home --shell /bin/bash --user-group --groups wheel passwd ``` +### Networking + +By default the script configures plain ZFSBootMenu without networking nor an SSH server. If you're interested in SSH-ing into your ZFSBootMenu boot loader you're going to want to specify some of the following variables. + +#### IP address + +``` +ARCHZBM_NET_CLIENT_IP='' +ARCHZBM_NET_SERVER_IP='' +ARCHZBM_NET_GATEWAY_IP='' +ARCHZBM_NET_NETMASK='' +ARCHZBM_NET_HOSTNAME='' +ARCHZBM_NET_DEVICE='' +ARCHZBM_NET_AUTOCONF='' +``` + +By default none of the variables are set to any value and no networking will be available in ZFSBootMenu. If you want networking as in an IP address bound to a network interace set at least one of these variables or one of the [SSH](#ssh) variables listed further down. Setting one or more `ARCHZBM_NET_*` variables to an empty string is valid. If at least one variable is given either from this paragraph or from [SSH](#ssh) we're assuming that you want networking. Unspecified values and values set to the empty string `''` use defaults. + +For networking we rely on the [mkinitcpio-nfs-utils](https://archlinux.org/packages/core/x86_64/mkinitcpio-nfs-utils/) package with its `net` hook. Please refer to its [initcpio-install-net](https://gitlab.archlinux.org/archlinux/packaging/packages/mkinitcpio-nfs-utils/-/blob/main/initcpio-install-net) script file for usage hints on above variables. The hook implements a subset of the [ip Kernel Command Line argument](https://docs.kernel.org/admin-guide/nfs/nfsroot.html). + +Mapping between `net` hook field names and our shell variables is straightforward. Fields 8, 9 and 10 (DNS and NTP server addresses) from the official `ip` docs are unsupported in `net` hook. As such our hook has a total of 7 fields available for you to configure. + +``` ++-------------+------------------------+ +| net hook | This script | ++-------------+------------------------+ +| | ARCHZBM_NET_CLIENT_IP | +| | ARCHZBM_NET_SERVER_IP | +| | ARCHZBM_NET_GATEWAY_IP | +| | ARCHZBM_NET_NETMASK | +| | ARCHZBM_NET_HOSTNAME | +| | ARCHZBM_NET_DEVICE | +| | ARCHZBM_NET_AUTOCONF | ++-------------+------------------------+ +``` + +A valid example with a few fields populated may look like so: + +``` +ARCHZBM_NET_CLIENT_IP='10.10.10.2' +ARCHZBM_NET_GATEWAY_IP='10.10.10.1' +ARCHZBM_NET_NETMASK='255.255.255.0' +ARCHZBM_NET_DEVICE='eth0' +ARCHZBM_NET_AUTOCONF='none' +``` + +Note that in this example `ARCHZBM_NET_SERVER_IP` and `ARCHZBM_NET_HOSTNAME` are left unassigned. + +#### SSH + +If you want networking indicated by the fact that at least one of the `ARCHZBM_NET_*` variables is set or one of the `ARCHZBM_SSH_*` vars we assume that you want an SSH daemon as well. This comes in the form of a `dropbear` daemon with minimal configurability. Use the following variables to define Dropbear's behavior. + +``` +ARCHZBM_SSH_PORT='22' +ARCHZBM_SSH_KEEPALIVE_INTVL='1' +ARCHZBM_SSH_AUTH_KEYS='' +``` + +In `ARCHZBM_SSH_PORT` you specify Dropbear's listening port, this defaults to `22` if unconfigured or set to an empty string. With `ARCHZBM_SSH_KEEPALIVE_INTVL` you define at which interval Dropbear will send keepalive messages to an SSH client through the SSH connection. This defaults to `1` as in every `1` second a keepalive message is sent. + +Dropbear in this setup only supports key-based authentication, no password-based authentication. The value from `ARCHZBM_SSH_AUTH_KEYS` will be converted to a list of public SSH keys allowed to SSH into Dropbear as its default `root` user while ZFSBootMenu is running. The format of `ARCHZBM_SSH_AUTH_KEYS` is a single line where `authorized_keys` entries are split with double-commas: + +``` +ssh-rsa Eahajei8,,ssh-ed25519 kaeD0mas ... +``` + +This syntax crutch allows you to use the full range of Dropbear-supported `authorized_keys` stanzas, see [man 8 dropbear](https://man.archlinux.org/man/extra/dropbear/dropbear.8.en) for what's available. You may want to for example do: + +``` +command='zfsbootmenu',no-agent-forwarding ssh-rsa Eahajei8,,ssh-ed25519 kaeD0mas ... +``` + +Whether or not this is useful to you is another topic :) At least the functionality for stanzas is there by separating values in `ARCHZBM_SSH_AUTH_KEYS` with double-commas. + # Steps The script takes the following installation steps. -- 2.47.2 From 79feaed5acdcb41959ce3f997a23dce838aa0efe Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 4 Nov 2023 00:20:39 +0100 Subject: [PATCH 19/28] docs(iso): Explain sed insert_n_before_m mechanism (#6) --- setup.sh | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/setup.sh b/setup.sh index d5c7d85..ab95d0d 100644 --- a/setup.sh +++ b/setup.sh @@ -468,6 +468,29 @@ function in_file_in_array_insert_n_before_m () { arg_array="${2:?}" arg_string="${3:?}" arg_precede="${4:?}" + + # Look for a line that contains in this order + # - String "${arg_array}" and a equals sign (=), assign capture group \1 + # - Followed by as few characters as possible followed by either an + # opening parenthesis or a space character, assign capture group \2 + # - String "${arg_precede}", capture as capture group \3 + # - Followed by either a closing parenthesis or a space which are then + # followed by as many non-line break characters as possible, capture + # as capture group \2 + # + # For following example text we're assuming that: + # - "${arg_array}" equals 'HOOKS' + # - "${arg_precede}" equals 'filesystems' + # - "${arg_string}" equals 'zfs' + # + # This finds a 'HOOKS=' array definition that contains the string + # 'filesystems' either at the beginning of the 'HOOKS=(...)' opening + # parenthesis, at the very end or somewhere in the middle where it may + # be preceded or followed by one or more space characters. It saves + # 'HOOKS=', it saves whatever precedes 'filesystems' and 'filesystems' + # itself plus whatever comes after 'filesystems' until end of line. It + # lastly inserts 'zfs' and a space character right in front of + # 'filesystems'. sed -ri \ -e 's'$'\x1''('"${arg_array}"'=)(.*?[( ])('"${arg_precede}"')([) ][^\r\n\f]*)'$'\x1''\1\2'"${arg_string}"' \3\4'$'\x1''g' \ "${arg_file}" -- 2.47.2 From e3025883fa4a0513e64268ca6d40ce99b26ccb66 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 4 Nov 2023 00:32:01 +0100 Subject: [PATCH 20/28] docs(iso): Explain sed insert_n_at_the_end mechanism (#6) --- setup.sh | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/setup.sh b/setup.sh index ab95d0d..8fb61fe 100644 --- a/setup.sh +++ b/setup.sh @@ -501,6 +501,21 @@ function in_file_in_array_insert_n_at_the_end () { arg_file="${1:?}" arg_array="${2:?}" arg_string="${3:?}" + + # Look for end of array, insert "${arg_string}" right before + # + # For following example text we're assuming that: + # - "${arg_array}" equals 'HOOKS' + # - "${arg_string}" equals 'net' + # + # This: + # - Finds a 'HOOKS=' array definition, saves it as \1 + # - Finds as many non-closing parenthesis characters as possible, so all + # characters until just before the final ')' character of the line and + # saves this as \2 + # - Finds the closing parenthesis character plus all non-line break + # characters until end of line that come after it and saves this as \3 + # - Adds a space character and 'net' after \2 sed -ri \ -e 's'$'\x1''('"${arg_array}"'=)([^)]*)(\)[^\r\n\f]*)'$'\x1''\1\2 '"${arg_string}"'\3'$'\x1''g' \ "${arg_file}" -- 2.47.2 From 1181432addb62da2e04929583c88c92cacb3efc0 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 4 Nov 2023 00:32:16 +0100 Subject: [PATCH 21/28] docs(iso): Explain sed in_array_remove_n mechanism (#6) --- setup.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/setup.sh b/setup.sh index 8fb61fe..1d9fc4e 100644 --- a/setup.sh +++ b/setup.sh @@ -526,6 +526,23 @@ function in_file_in_array_remove_n () { arg_file="${1:?}" arg_array="${2:?}" arg_string="${3:?}" + + # Look for any line that contains "${arg_string}", delete that string + # + # For following example text we're assuming that: + # - "${arg_array}" equals 'HOOKS' + # - "${arg_string}" equals 'fsck' + # + # First -e expression removes 'fsck' wherever it is defined as the one + # and only element of any HOOKS=(fsck) should such a line exist. + # + # Second -e expression finds string 'fsck' where it's preceded by space + # character(s) and followed by either space character(s) or a closing + # parenthesis. + # + # Third -e expression finds string 'fsck' where it's preceded by space + # character(s) or an opening parenthesis and followed space + # character(s). sed -ri \ -e 's'$'\x1''((\()('"${arg_string}"')(\)))'$'\x1''\2\4'$'\x1''g' \ -e 's'$'\x1''('"${arg_array}"'=.*?)([[:space:]]+'"${arg_string}"')([[:space:]]+|\))'$'\x1''\1\3'$'\x1''g' \ -- 2.47.2 From 52c09fc93fc62fb985e00888cacc5bc27f25abd6 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 4 Nov 2023 00:37:30 +0100 Subject: [PATCH 22/28] docs(zbm): Explain Syslinux KCL (#6) --- setup.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/setup.sh b/setup.sh index 1d9fc4e..57cd7ae 100644 --- a/setup.sh +++ b/setup.sh @@ -796,7 +796,11 @@ EOF fi # Up here maybe 'ro quiet' instead of 'ro'. This is ZFSBootMenu's kernel -# command line. +# command line. In MBR/Syslinux/extlinux mode /it/ must pass arguments to +# ZFSBootMenu's kernel so check /boot/syslinux/syslinux.cfg for how we start +# ZFSBootMenu in this mode. The .Kernel.CommandLine in +# /etc/zfsbootmenu/config.yaml is irrelevant for us in MBR/Syslinux/extlinux +# mode. # Assign cmdline for final kernel start. This is our Arch Linx kernel # command line. -- 2.47.2 From 956067735263960df983630c4838a36452cf6dbe Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 4 Nov 2023 00:41:37 +0100 Subject: [PATCH 23/28] fix(zbm): Link to dropbear patch hooks (#6) --- setup.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup.sh b/setup.sh index 57cd7ae..cb8b0b9 100644 --- a/setup.sh +++ b/setup.sh @@ -810,6 +810,8 @@ EOF function get_dropbear_hooks () { mkdir -p '/opt/git/quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook/branches/main' git -C '/opt/git/quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook/branches/main' clone 'https://quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook.git' . + ln -s '/opt/git/quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook/branches/main/pacman-mkinitcpio-dropbear-hook.sh' '/usr/local/bin/pacman-mkinitcpio-dropbear-hook' + ln -s '/opt/git/quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook/branches/main/pacman-mkinitcpio-dropbear-install.sh' '/usr/local/bin/pacman-mkinitcpio-dropbear-install' ln -s '/opt/git/quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook/branches/main/pacman-mkinitcpio-dropbear-hook.hook' '/usr/share/libalpm/hooks/pacman-mkinitcpio-dropbear-hook.hook' ln -s '/opt/git/quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook/branches/main/pacman-mkinitcpio-dropbear-install.hook' '/usr/share/libalpm/hooks/pacman-mkinitcpio-dropbear-install.hook' } -- 2.47.2 From 119be2b8765189f34beee77e650fe3884bf407b8 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 4 Nov 2023 00:46:44 +0100 Subject: [PATCH 24/28] docs(zbm): Give an example ip= KCL (#6) --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index b56f6b1..9cae388 100644 --- a/README.md +++ b/README.md @@ -191,6 +191,11 @@ ARCHZBM_NET_AUTOCONF='none' Note that in this example `ARCHZBM_NET_SERVER_IP` and `ARCHZBM_NET_HOSTNAME` are left unassigned. +This add the following `ip=` instruction to your Kernel Command Line: +``` +ip=10.10.10.2::10.10.10.1:255.255.255.0::eth0:none +``` + #### SSH If you want networking indicated by the fact that at least one of the `ARCHZBM_NET_*` variables is set or one of the `ARCHZBM_SSH_*` vars we assume that you want an SSH daemon as well. This comes in the form of a `dropbear` daemon with minimal configurability. Use the following variables to define Dropbear's behavior. -- 2.47.2 From a2cb784cb3b816ed3359d3d6da6457b40217bf58 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 4 Nov 2023 01:08:39 +0100 Subject: [PATCH 25/28] feat(zbm): In Syslinux/extlinux mode add KCL (#6) --- setup.sh | 93 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 33 deletions(-) diff --git a/setup.sh b/setup.sh index cb8b0b9..5cccee2 100644 --- a/setup.sh +++ b/setup.sh @@ -832,43 +832,70 @@ function customize_dropbear_hooks () { fi } +function set_unique_ip_in_syslinux_kcl () { + local zbm_config default_ip + zbm_config="${1:?}" + default_ip="${2:?}" + + # First -e expression removes first looks for lines that contain + # 'APPEND' plus a space character and only in those lines removes all + # occurrences of ' ip=' followed by as many non-space characters as + # possible. This removes whatever 'ip=' definition already was present. + # + # Second -e expression similarly looks for lines that contain 'APPEND' + # plus a space character then at their end inserts a space plus our + # desired new 'ip=' definition. This puts in place the 'ip=' we want. + sed -ri \ + -e \\$'\x1''APPEND '$'\x1 s'$'\x1'' ip=([^[:space:]]*)'$'\x1'''$'\x1''gi' \ + -e \\$'\x1''APPEND '$'\x1 s'$'\x1''$'$'\x1'' '"${default_ip}"''$'\x1''gi' \ + "${zbm_config}" +} + function ensure_ip_in_kcl () { - local zbm_config kcl_length kcl_string default_ip ip_addr_found new_kcl first_kcl_elem - local -a kcl - paru_install 'go-yq' - - zbm_config='/etc/zfsbootmenu/config.yaml' - kcl_length="$(yq '.Kernel.CommandLine | length' "${zbm_config}")" - if [[ "${kcl_length}" -eq '0' ]]; then - >&3 printf -- '%s\n' \ - 'No .Kernel.CommandLine YAML element with content found in '"${zbm_config}"'. Exiting ...' - exit 77 - else - kcl_string="$(yq '.Kernel.CommandLine' "${zbm_config}")" - fi - + local default_ip default_ip='ip='"${ARCHZBM_NET_CLIENT_IP}"':'"${ARCHZBM_NET_SERVER_IP}"':'"${ARCHZBM_NET_GATEWAY_IP}"':'"${ARCHZBM_NET_NETMASK}"':'"${ARCHZBM_NET_HOSTNAME}"':'"${ARCHZBM_NET_DEVICE}"':'"${ARCHZBM_NET_AUTOCONF}" - mapfile -t kcl < <(<<<"${kcl_string}" tr ' ' '\n' | sed '/^$/d') - for kcl_elem in "${!kcl[@]}"; do - if grep -Piq -- 'ip=' <<<"${kcl[$kcl_elem]}"; then - ip_addr_found='true' - kcl["${kcl_elem}"]="${default_ip}" - fi - done - if [[ ! "${ip_addr_found}" ]]; then - kcl+=("${default_ip}") - fi - new_kcl='' - first_kcl_elem='true' - for kcl_elem in "${kcl[@]}"; do - if [[ ! "${first_kcl_elem}" ]]; then - new_kcl+=' '"${kcl_elem}" + + if [[ "${part_schema}" = 'gpt' ]]; then + local zbm_config kcl_length kcl_string ip_addr_found new_kcl first_kcl_elem + local -a kcl + paru_install 'go-yq' + + zbm_config='/etc/zfsbootmenu/config.yaml' + kcl_length="$(yq '.Kernel.CommandLine | length' "${zbm_config}")" + if [[ "${kcl_length}" -eq '0' ]]; then + >&3 printf -- '%s\n' \ + 'No .Kernel.CommandLine YAML element with content found in '"${zbm_config}"'. Exiting ...' + exit 77 else - new_kcl+="${kcl_elem}" - unset -v first_kcl_elem + kcl_string="$(yq '.Kernel.CommandLine' "${zbm_config}")" fi - done - yq -i '.Kernel.CommandLine = "'"${new_kcl}"'"' "${zbm_config}" + + mapfile -t kcl < <(<<<"${kcl_string}" tr ' ' '\n' | sed '/^$/d') + for kcl_elem in "${!kcl[@]}"; do + if grep -Piq -- 'ip=' <<<"${kcl[$kcl_elem]}"; then + ip_addr_found='true' + kcl["${kcl_elem}"]="${default_ip}" + fi + done + if [[ ! "${ip_addr_found}" ]]; then + kcl+=("${default_ip}") + fi + new_kcl='' + first_kcl_elem='true' + for kcl_elem in "${kcl[@]}"; do + if [[ ! "${first_kcl_elem}" ]]; then + new_kcl+=' '"${kcl_elem}" + else + new_kcl+="${kcl_elem}" + unset -v first_kcl_elem + fi + done + yq -i '.Kernel.CommandLine = "'"${new_kcl}"'"' "${zbm_config}" + else + local zbm_config + zbm_config='/boot/syslinux/syslinux.cfg' + set_unique_ip_in_syslinux_kcl "${zbm_config}" "${default_ip}" + fi } function set_pub_keys () { -- 2.47.2 From 5cf4b2c325dbdb9c053b77d17e27b821d9f0bcd7 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 4 Nov 2023 01:16:39 +0100 Subject: [PATCH 26/28] docs(zbm): Let's not overpromise, the command stanza at first glance seems trickier than anticipated (#6) --- README.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index 9cae388..c219a19 100644 --- a/README.md +++ b/README.md @@ -214,13 +214,7 @@ Dropbear in this setup only supports key-based authentication, no password-based ssh-rsa Eahajei8,,ssh-ed25519 kaeD0mas ... ``` -This syntax crutch allows you to use the full range of Dropbear-supported `authorized_keys` stanzas, see [man 8 dropbear](https://man.archlinux.org/man/extra/dropbear/dropbear.8.en) for what's available. You may want to for example do: - -``` -command='zfsbootmenu',no-agent-forwarding ssh-rsa Eahajei8,,ssh-ed25519 kaeD0mas ... -``` - -Whether or not this is useful to you is another topic :) At least the functionality for stanzas is there by separating values in `ARCHZBM_SSH_AUTH_KEYS` with double-commas. +This syntax crutch allows you to use the full range of Dropbear-supported `authorized_keys` stanzas, see [man 8 dropbear](https://man.archlinux.org/man/extra/dropbear/dropbear.8.en) for what's available. Whether or not this is useful to you is another topic :) At least the functionality for stanzas is there by separating values in `ARCHZBM_SSH_AUTH_KEYS` with double-commas. # Steps -- 2.47.2 From 782168c1b15cb20f2fd5f33a4c6e55fbba6b439c Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sun, 5 Nov 2023 02:10:33 +0100 Subject: [PATCH 27/28] docs(zbm): Nudge user to work with Dropbear keepalives (#6) --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index c219a19..9b3e437 100644 --- a/README.md +++ b/README.md @@ -230,11 +230,30 @@ The script takes the following installation steps. 1. Configure boot method - Either an EFI image with EFI boot order entries on a UEFI machine - Or Syslinux with `extlinux` for a legacy BIOS computer +1. If requested by user enable SSH in ZFSBootMenu 1. Add `pacman` hooks to keep ZFSBootMenu images (and `extlinux`) updated - [quico.space/quico-os-setup/zbm-regen-pacman-hook](https://quico.space/quico-os-setup/zbm-regen-pacman-hook) - [quico.space/quico-os-setup/zbm-syslinux-pacman-hook](https://quico.space/quico-os-setup/zbm-syslinux-pacman-hook) 1. Exit into Arch Linux live CD ISO image shell for you to `reboot` and frolick +# SSH in ZFSBootMenu + +Per [SSH](#ssh) and [Networking](#networking) this script will optionally add a Dropbear SSH daemon to ZFSBootMenu. While the mechanism of SSH-ing into a server isn't particularly noteworthy we humbly suggest that in this particular use case you let your SSH client listen for keepalive messages from the server. + +``` +ssh -o ServerAliveInterval=3 -o ServerAliveCountMax=0 -p +``` + +A typical workflow with Dropbear is for your to SSH into it, issue `zfs` or `zfsbootmenu` commands and allow the Arch Linux boot process to commence. As soon as you're done the Dropbear SSH server will terminate as ZFSBootMenu hands its control off to your operating system's real kernel. Without your client listening to keepalive messages it may not realize that the connection's gone for quite some time until you harshly interrupt it. + +The server defaults to sending keepalive messages to your client every second. + +With `-o ServerAliveInterval=3` you instruct your client to send an are-your-still-there message to the server if your client ever stops getting keepalive messages from the server for 3 seconds. The server defaults to sending 1 keepalive ping per second so even on a somewhat lossy connection we can reasonably expect to get one message through to us within 3 seconds. + +When it comes to the point that your SSH client sends an are-your-still-there message it expects a near-realtime response. It will accept `-o ServerAliveCountMax=0` failures from the server to comply. + +This effectively configures your SSH client to remain connected even through somewhat lossy hops to the Dropbear daemon; and to cleanly disconnect 3 seconds and some change after you've executed whatever you needed to do in ZFSBootMenu. + # Flavor choices We make the following opinionated flavor choices. Feel free to change them to your liking. -- 2.47.2 From 2b982be84e1854861adb19182a397451afd68c95 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sun, 5 Nov 2023 02:35:03 +0100 Subject: [PATCH 28/28] docs(meta): Bits and pieces updated (#6) --- README.md | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 9b3e437..2f81553 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ NAME SIZE FSTYPE PARTTYPE PARTTYPENAME PTTYPE # Partition naming -Since this script works with UEFI and legacy BIOS mode we'll be addressing both disk layout schemes with umbrella terms for better readability: "The zpool partition" will be GPT `BF00` partition and MBR `bf` partition. You'll parse the text accordingly. "The boot partition" will be GPT `EF00` partition as well as the MBR `83` partition. +Since this script works with UEFI and legacy BIOS mode we'll be addressing both disk layout schemes with umbrella terms for the rest of this document for better readability: "The zpool partition" will be GPT `BF00` partition and MBR `bf` partition. You'll parse the text accordingly. "The boot partition" will be GPT `EF00` partition as well as the MBR `83` partition. # ZFS dataset layout @@ -127,7 +127,7 @@ export ARCHZBM_ZFSPROPS_NO_ENCRYPTION=yup ### Passwords -By default both the zpool password and the account password for `root` are literally `password`. While you can certainly change these after initial system setup (see [Password change](#password-change)) you can also optionally set passwords as follows: +By default both the zpool password and the account password for `root` are literally `password`. While you can certainly change these after initial system setup (see [Password change](#password-change)) you can also optionally set passwords before script execution as follows: ``` ARCHZBM_ZPOOL_PASSWORD='a fancy password' @@ -191,11 +191,18 @@ ARCHZBM_NET_AUTOCONF='none' Note that in this example `ARCHZBM_NET_SERVER_IP` and `ARCHZBM_NET_HOSTNAME` are left unassigned. -This add the following `ip=` instruction to your Kernel Command Line: +It'll add the following `ip=` instruction to your Kernel Command Line: ``` ip=10.10.10.2::10.10.10.1:255.255.255.0::eth0:none ``` +This is also valid and will configure `eth0` via DHCP: + +``` +ARCHZBM_NET_DEVICE='eth0' +ARCHZBM_NET_AUTOCONF='dhcp' +``` + #### SSH If you want networking indicated by the fact that at least one of the `ARCHZBM_NET_*` variables is set or one of the `ARCHZBM_SSH_*` vars we assume that you want an SSH daemon as well. This comes in the form of a `dropbear` daemon with minimal configurability. Use the following variables to define Dropbear's behavior. @@ -206,7 +213,7 @@ ARCHZBM_SSH_KEEPALIVE_INTVL='1' ARCHZBM_SSH_AUTH_KEYS='' ``` -In `ARCHZBM_SSH_PORT` you specify Dropbear's listening port, this defaults to `22` if unconfigured or set to an empty string. With `ARCHZBM_SSH_KEEPALIVE_INTVL` you define at which interval Dropbear will send keepalive messages to an SSH client through the SSH connection. This defaults to `1` as in every `1` second a keepalive message is sent. +In `ARCHZBM_SSH_PORT` you specify Dropbear's listening port, this defaults to `22` if unconfigured or set to an empty string. With `ARCHZBM_SSH_KEEPALIVE_INTVL` you define at which interval Dropbear will send keepalive messages to an SSH client through the SSH connection. This defaults to `1` as in every `1` second a keepalive message is sent. Per [man 8 dropbear](https://man.archlinux.org/man/extra/dropbear/dropbear.8.en) a value of `0` disables Dropbear sending keepalive messages. We suggest to leave this on and to keep the interval short, see [SSH in ZFSBootMenu](#ssh-in-zfsbootmenu) for how to work with this. Dropbear in this setup only supports key-based authentication, no password-based authentication. The value from `ARCHZBM_SSH_AUTH_KEYS` will be converted to a list of public SSH keys allowed to SSH into Dropbear as its default `root` user while ZFSBootMenu is running. The format of `ARCHZBM_SSH_AUTH_KEYS` is a single line where `authorized_keys` entries are split with double-commas: @@ -230,7 +237,8 @@ The script takes the following installation steps. 1. Configure boot method - Either an EFI image with EFI boot order entries on a UEFI machine - Or Syslinux with `extlinux` for a legacy BIOS computer -1. If requested by user enable SSH in ZFSBootMenu +1. If requested by user enable SSH in ZFSBootMenu. We then also add: + - [quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook](https://quico.space/quico-os-setup/mkinitcpio-dropbear-pacman-hook) 1. Add `pacman` hooks to keep ZFSBootMenu images (and `extlinux`) updated - [quico.space/quico-os-setup/zbm-regen-pacman-hook](https://quico.space/quico-os-setup/zbm-regen-pacman-hook) - [quico.space/quico-os-setup/zbm-syslinux-pacman-hook](https://quico.space/quico-os-setup/zbm-syslinux-pacman-hook) @@ -241,12 +249,12 @@ The script takes the following installation steps. Per [SSH](#ssh) and [Networking](#networking) this script will optionally add a Dropbear SSH daemon to ZFSBootMenu. While the mechanism of SSH-ing into a server isn't particularly noteworthy we humbly suggest that in this particular use case you let your SSH client listen for keepalive messages from the server. ``` -ssh -o ServerAliveInterval=3 -o ServerAliveCountMax=0 -p +ssh -o ServerAliveInterval=3 -o ServerAliveCountMax=0 root@ -p ``` -A typical workflow with Dropbear is for your to SSH into it, issue `zfs` or `zfsbootmenu` commands and allow the Arch Linux boot process to commence. As soon as you're done the Dropbear SSH server will terminate as ZFSBootMenu hands its control off to your operating system's real kernel. Without your client listening to keepalive messages it may not realize that the connection's gone for quite some time until you harshly interrupt it. +A typical workflow with Dropbear is for you to SSH into it, issue `zfs` or `zfsbootmenu` commands and allow the Arch Linux boot process to commence. As soon as you're done Dropbear will terminate as ZFSBootMenu hands control off to your operating system's kernel. Without your client listening to keepalive messages it may not realize that the connection's gone for quite some time until you harshly interrupt it. -The server defaults to sending keepalive messages to your client every second. +The server defaults to sending keepalive messages to your client every second. With `-o ServerAliveInterval=3` you instruct your client to send an are-your-still-there message to the server if your client ever stops getting keepalive messages from the server for 3 seconds. The server defaults to sending 1 keepalive ping per second so even on a somewhat lossy connection we can reasonably expect to get one message through to us within 3 seconds. @@ -271,14 +279,14 @@ We make the following opinionated flavor choices. Feel free to change them to yo After installation you're going to want to at least touch these points in your new Arch Linux install: - Package manager hook: `pacman` does not have a hook to do ZFS snapshots - - See [this GitHub gist](https://gist.github.com/Soulsuke/6a7d1f09f7fef968a2f32e0ff32a5c4c#file-arch_on_zfs-txt-L238) and [zfs-snapshotter.bash](https://github.com/Soulsuke/arch-zfs-tools/blob/master/zfs-snapshotter.bash) for inspiration + - See [quico.space/quico-os-setup/zfs-pacman-hook](https://quico.space/quico-os-setup/zfs-pacman-hook/src/branch/1-get-base-version-going) for an example you may want to install - Hostname: Installation chose a pseudo-randomly generated 8-character string with `pwgen` - Check `hostnamectl set-hostname ` - Unprivileged user accounts: The OS was installed with `root` and unprivileged `build` users -- Unless you had a settings file per [Passwords](#passwords) you're going to want to change passwords now: +- Unless you had a settings file or exported shell env vars per [Passwords](#passwords) you're going to want to change passwords now: - ZFS: The password for all datasets underneath `zpool` is `password`. - Local `root` account: The local `root` account's password is `password`. -- Arch User Repository (AUR) helper: We installed [paru](https://github.com/Morganamilo/paru) as our AUR helper, we installed from GitHub via `makepkg -si` then replaced itself with its [paru-bin](https://aur.archlinux.org/packages/paru-bin) version from AUR. +- Arch User Repository (AUR) helper: We installed [paru](https://github.com/Morganamilo/paru) as our AUR helper, we installed from GitHub via `makepkg -si` then replaced it with its [paru-bin](https://aur.archlinux.org/packages/paru-bin) version from AUR. - In `/etc/systemd/network/50-wired.network` instead of a DHCP-based network config you can get a static one. The DHCP-based one for reference looks like: ``` ... -- 2.47.2