From bd586e4c67e3c9e06a063ea21a4ae29802bc4c5d Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 01:16:37 +0100 Subject: [PATCH 01/23] fix(zfs): Fix multi-line bash command (#21) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c992f5c..887cff8 100644 --- a/README.md +++ b/README.md @@ -418,7 +418,7 @@ In order to generate a new master key after you've changed your user key as ment --large-block \ --compressed \ 'zpool/root/archlinux-sxu@rekey' | \ - + \ zfs receive \ -Fvu \ -o 'encryption=on' \ From d5e219dbf5ce69d6eac1f26eb7d1c590120952e3 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 01:17:14 +0100 Subject: [PATCH 02/23] feat(iso): Add bash-only CIDR calculator function (#21) --- setup.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/setup.sh b/setup.sh index c6404b7..c606a9e 100644 --- a/setup.sh +++ b/setup.sh @@ -36,6 +36,17 @@ trap '[ "$?" -ne 77 ] || exit 77' ERR declare zpool_drive efi_drive boot_drive part_schema +function calculate_prefix_from_netmask () { + # https://stackoverflow.com/a/50419919 + c='0' + x='0'"$(printf -- '%o' ${1//./ })" + while [ "${x}" -gt '0' ]; do + # Modulo then bitwise-shift x and store as new x + let c+="$(( x % 2 ))" 'x>>=1' + done + printf -- '%s' '/'"${c}"; +} + function setup_env_vars () { printf -- '%s\n' \ 'We will go over a series of questions to create an answer file with' \ From db3c705376fece26bc163701adfaef42facf8738 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 01:18:19 +0100 Subject: [PATCH 03/23] refactor(iso): echo consistently with single quotes (#21) --- setup.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/setup.sh b/setup.sh index c606a9e..cd2ed2d 100644 --- a/setup.sh +++ b/setup.sh @@ -68,7 +68,7 @@ function setup_env_vars () { echo '----------------------------------------' echo - echo "Do you want compressed datasets?" + echo 'Do you want compressed datasets?' select arg_compressed in "Compressed" "Uncompressed"; do case "${arg_compressed}" in Compressed) @@ -81,7 +81,7 @@ function setup_env_vars () { esac done <&3 && echo - echo "Do you want encrypted datasets?" + echo 'Do you want encrypted datasets?' select arg_encrypted in "Encrypted" "Unencrypted"; do case "${arg_encrypted}" in Encrypted) @@ -95,7 +95,7 @@ function setup_env_vars () { done <&3 && echo if [[ "${arg_encrypted}" = 'Encrypted' ]]; then - echo "Do you want a custom dataset decryption password?" + echo 'Do you want a custom dataset decryption password?' select arg_custom_dataset_pw in "Yes" "No"; do case "${arg_custom_dataset_pw}" in Yes) @@ -115,7 +115,7 @@ function setup_env_vars () { fi fi - echo "Do you want a custom 'root' user password?" + echo 'Do you want a custom '"'"'root'"'"' user password?' select arg_custom_root_pw in "Yes" "No"; do case "${arg_custom_root_pw}" in Yes) @@ -134,7 +134,7 @@ function setup_env_vars () { echo fi - echo "Do you want an SSH daemon in ZFSBootMenu?" + echo 'Do you want an SSH daemon in ZFSBootMenu?' select arg_ssh_in_zbm in "Yes" "No"; do case "${arg_ssh_in_zbm}" in Yes) @@ -148,7 +148,7 @@ function setup_env_vars () { done <&3 && echo if [[ "${want_ssh_in_zbm}" ]]; then - echo "How do you want to assign an IP address in ZFSBootMenu?" + echo 'How do you want to assign an IP address in ZFSBootMenu?' select arg_ip_autoconf_method in "Statically" "Dynamically, DHCP" "Dynamically, BOOTP" "Dynamically, RARP"; do case "${arg_ip_autoconf_method}" in 'Statically') @@ -184,7 +184,7 @@ function setup_env_vars () { echo fi - echo "Do you want a custom SSH listening port?" + echo 'Do you want a custom SSH listening port?' select arg_custom_ssh_port in "Yes (let me specify)" "No (keep port 22)"; do case "${arg_custom_ssh_port}" in 'Yes (let me specify)') @@ -202,7 +202,7 @@ function setup_env_vars () { echo fi - echo "Do you want the SSH daemon to use a custom keepalive send interval?" + echo 'Do you want the SSH daemon to use a custom keepalive send interval?' select arg_custom_ssh_keepalive_intvl in "Yes (let me specify)" "No (keep 1)"; do case "${arg_custom_ssh_keepalive_intvl}" in 'Yes (let me specify)') From c9f979a0ad5e6c3644f0fdc017fbf42c5a27ce34 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 01:19:01 +0100 Subject: [PATCH 04/23] feat(iso): In setup questionnaire ask for OS IP and gateway (#21) --- setup.sh | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/setup.sh b/setup.sh index cd2ed2d..5c61455 100644 --- a/setup.sh +++ b/setup.sh @@ -224,7 +224,59 @@ function setup_env_vars () { echo fi - for env_var in 'ARCHZBM_ZFSPROPS_NO_COMPRESSION' 'ARCHZBM_ZFSPROPS_NO_ENCRYPTION' 'ARCHZBM_ZPOOL_PASSWORD' 'ARCHZBM_ROOT_PASSWORD' 'ARCHZBM_NET_AUTOCONF' 'ARCHZBM_NET_DEVICE' 'ARCHZBM_NET_CLIENT_IP' 'ARCHZBM_NET_NETMASK' 'ARCHZBM_NET_GATEWAY_IP' 'ARCHZBM_SSH_PORT' 'ARCHZBM_SSH_KEEPALIVE_INTVL' 'ARCHZBM_SSH_AUTH_KEYS'; do + if [[ "${want_ssh_in_zbm}" ]]; then + echo 'Do you want to define operating system'"'"'s IP address?' + select arg_os_ip in 'Yes (let me specify)' 'Yes (use ZBM addresses)' 'No (DHCP is fine)'; do + case "${arg_os_ip}" in + 'Yes (let me specify)') + want_custom_ip_in_os='true' + want_dns_and_ntp='true' + break + ;; + 'Yes (use ZBM addresses)') + ARCHZBM_OS_CLIENT_IP="${ARCHZBM_NET_CLIENT_IP}" + ARCHZBM_NET_CLIENT_IP_PREFIX="$(calculate_prefix_from_netmask "${ARCHZBM_NET_NETMASK}")" + ARCHZBM_OS_CLIENT_IP+="${ARCHZBM_NET_CLIENT_IP_PREFIX}" + ARCHZBM_OS_GATEWAY_IP="${ARCHZBM_NET_GATEWAY_IP}" + want_dns_and_ntp='true' + break + ;; + 'No (DHCP is fine)') + break + ;; + esac + done <&3 && echo + + if [[ "${want_custom_ip_in_os}" ]]; then + read -u3 -p 'Interface IP address with CIDR prefix (a.b.c.d/nn): ' ARCHZBM_OS_CLIENT_IP + echo + + read -u3 -p 'Gateway IP address: ' ARCHZBM_OS_GATEWAY_IP + echo + fi + else + echo 'Do you want to define operating system'"'"'s IP address?' + select arg_os_ip in 'Yes (let me specify)' 'No (DHCP is fine)'; do + case "${arg_os_ip}" in + 'Yes (let me specify)') + want_own_ip_in_os='true' + want_dns_and_ntp='true' + break + ;; + 'No (DHCP is fine)') + break + ;; + esac + done <&3 && echo + + if [[ "${want_own_ip_in_os}" ]]; then + read -u3 -p 'Interface IP address with CIDR prefix (a.b.c.d/nn): ' ARCHZBM_OS_CLIENT_IP + echo + + read -u3 -p 'Gateway IP address: ' ARCHZBM_OS_GATEWAY_IP + echo + fi + fi if [[ "${!env_var}" ]]; then printf -- '%s='"'"'%s'"'"'\n' \ "${env_var}" "${!env_var}" \ From d99bb94c522aae1d36ef119097986bd7bd94ed46 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 01:19:24 +0100 Subject: [PATCH 05/23] feat(iso): In setup questionnaire ask for NTP servers (#21) --- setup.sh | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/setup.sh b/setup.sh index 5c61455..f07d487 100644 --- a/setup.sh +++ b/setup.sh @@ -277,6 +277,29 @@ function setup_env_vars () { echo fi fi + + if [[ "${want_dns_and_ntp}" ]]; then + read -u3 -p 'Specify one or more comma-separated DNS IPs: ' ARCHZBM_OS_DNS_IP + echo + + echo 'Do you want to override Arch Linux'"'"' NTP servers?' + select arg_custom_ntp in 'Yes' 'No'; do + case "${arg_custom_ntp}" in + 'Yes') + want_own_ntp='true' + break + ;; + 'No') + break + ;; + esac + done <&3 && echo + + if [[ "${want_own_ntp}" ]]; then + read -u3 -p 'Specify one or more comma-separated NTP hostnames or IPs: ' ARCHZBM_OS_NTP_IP + echo + fi + fi if [[ "${!env_var}" ]]; then printf -- '%s='"'"'%s'"'"'\n' \ "${env_var}" "${!env_var}" \ From 59beb1040423a95ef341f5032ada7541563e61af Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 01:19:56 +0100 Subject: [PATCH 06/23] feat(iso): Write OS IPs, gateway, NTP into env file (#21) --- setup.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup.sh b/setup.sh index f07d487..61f8b09 100644 --- a/setup.sh +++ b/setup.sh @@ -300,6 +300,8 @@ function setup_env_vars () { echo fi fi + + for env_var in 'ARCHZBM_ZFSPROPS_NO_COMPRESSION' 'ARCHZBM_ZFSPROPS_NO_ENCRYPTION' 'ARCHZBM_ZPOOL_PASSWORD' 'ARCHZBM_ROOT_PASSWORD' 'ARCHZBM_NET_AUTOCONF' 'ARCHZBM_NET_DEVICE' 'ARCHZBM_NET_CLIENT_IP' 'ARCHZBM_NET_NETMASK' 'ARCHZBM_NET_GATEWAY_IP' 'ARCHZBM_SSH_PORT' 'ARCHZBM_SSH_KEEPALIVE_INTVL' 'ARCHZBM_SSH_AUTH_KEYS' 'ARCHZBM_OS_CLIENT_IP' 'ARCHZBM_OS_GATEWAY_IP' 'ARCHZBM_OS_DNS_IP' 'ARCHZBM_OS_NTP_IP'; do if [[ "${!env_var}" ]]; then printf -- '%s='"'"'%s'"'"'\n' \ "${env_var}" "${!env_var}" \ From 3903498d409e6a18fe5f879eaca1f5988478644e Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 01:20:32 +0100 Subject: [PATCH 07/23] feat(iso): Modularize network unit file content (#21) --- setup.sh | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/setup.sh b/setup.sh index 61f8b09..bcf383b 100644 --- a/setup.sh +++ b/setup.sh @@ -1295,11 +1295,54 @@ function set_root_pw () { function configure_networking () { #3.3 + local -a dns_addresses ntp_addresses + + # Begin network unit file with a default top section cat > '/mnt/etc/systemd/network/50-wired.network' <<"EOF" [Match] Name=en* [Network] +EOF + + # Decide on what comes next in network unit file + if [[ "${ARCHZBM_OS_CLIENT_IP}" ]] || \ + [[ "${ARCHZBM_OS_GATEWAY_IP}" ]] || \ + [[ "${ARCHZBM_OS_DNS_IP}" ]] || \ + [[ "${ARCHZBM_OS_NTP_IP}" ]]; then + + cat >> '/mnt/etc/systemd/network/50-wired.network' <> '/mnt/etc/systemd/network/50-wired.network' <> '/mnt/etc/systemd/network/50-wired.network' <> '/mnt/etc/systemd/network/50-wired.network' <<"EOF" +IPForward=yes +Domains=~. +EOF + else + cat >> '/mnt/etc/systemd/network/50-wired.network' <<"EOF" DHCP=ipv4 IPForward=yes @@ -1307,6 +1350,8 @@ IPForward=yes UseDNS=yes RouteMetric=10 EOF + fi + systemctl enable 'systemd-networkd' --root='/mnt' systemctl disable 'systemd-networkd-wait-online' --root='/mnt' } From 257648c99da39f3ec5d336c59eaa6f72a6b2cb3b Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 04:01:14 +0100 Subject: [PATCH 08/23] feat(os): Optionally force kernel downgrade for ZFS compatibility (#19) --- README.md | 42 ++++++++++++++++++++++++++++++++++++++++++ setup.sh | 6 +++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 887cff8..321ada2 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,30 @@ In cases where a variable is both exported prior to script execution and specifi Known options are as follows. +### Kernel downgrade + +By default we install newest `linux` and `linux-headers` packages into a `chroot`. Once we're in that `chroot` we then install newest [AUR zfs-dkms package](https://aur.archlinux.org/packages/zfs-dkms). You may want to override `linux` and `linux-headers` versions we're installing to ensure you end up with a compatible mix between them and `zfs-dkms`. + +For example: +``` +export ARCHZBM_KERNEL_VER=6.5.9.arch2 +``` + +In our `chroot` this will trigger execution of: +``` +downgrade --ala-only 'linux=6.5.9.arch2' 'linux-headers=6.5.9.arch2' --ignore always +``` + +Where `downgrade` is the [AUR downgrade package](https://aur.archlinux.org/packages/downgrade). This will downgrade `linux` and `linux-headers` and will add a setting to your `/etc/pacman.conf`: +``` +[options] +IgnorePkg = linux linux-headers +``` + +Setting `ARCHZBM_KERNEL_VER` to an empty string `''` or keeping it undefined are both valid and will retain newest versions instead of downgrading. + +Also read [Kernel selection](#kernel-selection) for details. + ### 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 ``. @@ -296,6 +320,24 @@ When it comes to the point that your SSH client sends an are-your-still-there me 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. +# Kernel selection + +This script compiles ZFS via Arch Linux' [Dynamic Kernel Module Support](https://wiki.archlinux.org/title/Dynamic_Kernel_Module_Support) (DKMS). Not all kernels allow for successful compilation, in some instances a particularly recent kernel version may change APIs to such a degree that ZFS compilation simply fails. + +We strongly suggest to that you: + +- Firstly, refer to a resource such as the [Arch Linux Archive package version list](https://archive.archlinux.org/packages/l/linux/) to find out what newest kernel version this script will install. +- Secondly, research if newest [AUR zfs-dkms package](https://aur.archlinux.org/packages/zfs-dkms) is compatible with that kernel. Two reasonable points of contact are AUR and its comments section for `zfs-dkms` where users quickly report issues; and the [github.com/openzfs/zfs issues list](https://github.com/openzfs/zfs/issues). + +An example for this is that `linux-6.6.1.arch1-1-x86_64` released on Wednesday, November 8, 2023 at a time when newest `zfs-dkms` package version [was 2.2.0](https://aur.archlinux.org/cgit/aur.git/commit/?h=zfs-dkms&id=da1b6372c57b16f2781a7fda2b95971bb392c5ee) which did not compile against `linux` 6.6.x. + +You'd then set for example: +``` +export ARCHZBM_KERNEL_VER=6.5.9.arch2 +``` + +Where any 6.5.x version is known to work well with `zfs-dkms`. See also [Kernel downgrade](#kernel-downgrade) for details on how to configure this. + # Flavor choices We make the following opinionated flavor choices. Feel free to change them to your liking. diff --git a/setup.sh b/setup.sh index bcf383b..37ee339 100644 --- a/setup.sh +++ b/setup.sh @@ -68,6 +68,10 @@ function setup_env_vars () { echo '----------------------------------------' echo + read -u3 -p 'Please type kernel version to use, leave empty for latest, confirm with : ' -s ARCHZBM_KERNEL_VER + echo + echo + echo 'Do you want compressed datasets?' select arg_compressed in "Compressed" "Uncompressed"; do case "${arg_compressed}" in @@ -301,7 +305,7 @@ function setup_env_vars () { fi fi - for env_var in 'ARCHZBM_ZFSPROPS_NO_COMPRESSION' 'ARCHZBM_ZFSPROPS_NO_ENCRYPTION' 'ARCHZBM_ZPOOL_PASSWORD' 'ARCHZBM_ROOT_PASSWORD' 'ARCHZBM_NET_AUTOCONF' 'ARCHZBM_NET_DEVICE' 'ARCHZBM_NET_CLIENT_IP' 'ARCHZBM_NET_NETMASK' 'ARCHZBM_NET_GATEWAY_IP' 'ARCHZBM_SSH_PORT' 'ARCHZBM_SSH_KEEPALIVE_INTVL' 'ARCHZBM_SSH_AUTH_KEYS' 'ARCHZBM_OS_CLIENT_IP' 'ARCHZBM_OS_GATEWAY_IP' 'ARCHZBM_OS_DNS_IP' 'ARCHZBM_OS_NTP_IP'; do + for env_var in 'ARCHZBM_KERNEL_VER' 'ARCHZBM_ZFSPROPS_NO_COMPRESSION' 'ARCHZBM_ZFSPROPS_NO_ENCRYPTION' 'ARCHZBM_ZPOOL_PASSWORD' 'ARCHZBM_ROOT_PASSWORD' 'ARCHZBM_NET_AUTOCONF' 'ARCHZBM_NET_DEVICE' 'ARCHZBM_NET_CLIENT_IP' 'ARCHZBM_NET_NETMASK' 'ARCHZBM_NET_GATEWAY_IP' 'ARCHZBM_SSH_PORT' 'ARCHZBM_SSH_KEEPALIVE_INTVL' 'ARCHZBM_SSH_AUTH_KEYS' 'ARCHZBM_OS_CLIENT_IP' 'ARCHZBM_OS_GATEWAY_IP' 'ARCHZBM_OS_SSH_AUTH_KEYS' 'ARCHZBM_OS_DNS_IP' 'ARCHZBM_OS_NTP_IP'; do if [[ "${!env_var}" ]]; then printf -- '%s='"'"'%s'"'"'\n' \ "${env_var}" "${!env_var}" \ From eaf83163b641f4921d136937de089796e970fd95 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 04:01:28 +0100 Subject: [PATCH 09/23] refactor(os): Typo (#19) --- setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.sh b/setup.sh index 37ee339..402661d 100644 --- a/setup.sh +++ b/setup.sh @@ -316,7 +316,7 @@ function setup_env_vars () { printf -- '%s\n' \ 'Done, please rerun script now with just' \ '... | bash' \ - 'so without the '"'"'setup'"'"' argument's + 'so without the '"'"'setup'"'"' argument' exit 77 } From 557db12e8db27948cad3a2001694c361341641d3 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 04:01:59 +0100 Subject: [PATCH 10/23] fix(zbm): ZBM 2.2.2 no longer needs nor has its own stub loader file (#19) --- setup.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.sh b/setup.sh index 402661d..8021b0d 100644 --- a/setup.sh +++ b/setup.sh @@ -1051,7 +1051,6 @@ EFI: ImageDir: /efi/EFI/ZBM Versions: false Enabled: true - Stub: /usr/share/zfsbootmenu/stubs/linuxx64.efi.stub/linuxx64.efi.stub # workaround: https://github.com/zbm-dev/zfsbootmenu/discussions/501 Kernel: CommandLine: ro loglevel=0 zbm.import_policy=hostid Prefix: vmlinuz From d95d43a22bc7bb9a75094ca6b3c5fd5f8d304304 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 04:02:30 +0100 Subject: [PATCH 11/23] feat(os): Downgrade kernel when requested (#19) --- setup.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/setup.sh b/setup.sh index 8021b0d..a9d013e 100644 --- a/setup.sh +++ b/setup.sh @@ -1264,6 +1264,13 @@ function install_os_in_chroot () { unleash_makepkg #2.5 add_motd_getting_started_msg #2.6 get_aur_helper #2.7 + if [[ "${ARCHZBM_KERNEL_VER}" ]]; then + paru_install 'downgrade' + yes | downgrade --ala-only \ + 'linux='"${ARCHZBM_KERNEL_VER}" \ + 'linux-headers='"${ARCHZBM_KERNEL_VER}" \ + --ignore always + fi paru_install 'zfs-dkms' 'zfs-utils' 'jq' hwclock --systohc mkinitcpio -P From d380fc4b6dfd3e3ce70ab047509d26bf504a8360 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 04:03:09 +0100 Subject: [PATCH 12/23] fix(os): No need to double-quote in a heredoc (#19) --- setup.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup.sh b/setup.sh index a9d013e..1ea9230 100644 --- a/setup.sh +++ b/setup.sh @@ -1322,8 +1322,8 @@ EOF [[ "${ARCHZBM_OS_NTP_IP}" ]]; then cat >> '/mnt/etc/systemd/network/50-wired.network' <> '/mnt/etc/systemd/network/50-wired.network' <> '/mnt/etc/systemd/network/50-wired.network' < Date: Sat, 11 Nov 2023 04:04:14 +0100 Subject: [PATCH 13/23] feat(os): Reuse or set SSH pub keys in OS (#19) --- setup.sh | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/setup.sh b/setup.sh index 1ea9230..601358e 100644 --- a/setup.sh +++ b/setup.sh @@ -282,6 +282,48 @@ function setup_env_vars () { fi fi + if [[ "${want_ssh_in_zbm}" ]]; then + echo 'Do you want to define OS root user'"'"'s SSH pub key?' + select arg_root_pub_keys in 'Yes (let me specify)' 'Yes (use ZBM pub keys)' 'No (don'"'"'t enable sshd.service)'; do + case "${arg_root_pub_keys}" in + 'Yes (let me specify)') + want_custom_pub_keys_in_os='true' + break + ;; + 'Yes (use ZBM pub keys)') + ARCHZBM_OS_SSH_AUTH_KEYS="${ARCHZBM_SSH_AUTH_KEYS}" + break + ;; + 'No (don'"'"'t enable sshd.service)') + break + ;; + esac + done <&3 && echo + + if [[ "${want_custom_pub_keys_in_os}" ]]; then + read -u3 -p 'Please type SSH pub keys on one line separated by double-commas (,,) and confirm with : ' ARCHZBM_OS_SSH_AUTH_KEYS + echo + fi + else + echo 'Do you want to define OS root user'"'"'s SSH pub key?' + select arg_root_pub_keys in 'Yes (let me specify)' 'No (don'"'"'t enable sshd.service)'; do + case "${arg_root_pub_keys}" in + 'Yes (let me specify)') + want_own_pub_key_in_os='true' + break + ;; + 'No (don'"'"'t enable sshd.service)') + break + ;; + esac + done <&3 && echo + + if [[ "${want_own_pub_key_in_os}" ]]; then + read -u3 -p 'Please type SSH pub keys on one line separated by double-commas (,,) and confirm with : ' ARCHZBM_OS_SSH_AUTH_KEYS + echo + fi + fi + if [[ "${want_dns_and_ntp}" ]]; then read -u3 -p 'Specify one or more comma-separated DNS IPs: ' ARCHZBM_OS_DNS_IP echo @@ -1366,6 +1408,21 @@ EOF systemctl disable 'systemd-networkd-wait-online' --root='/mnt' } +function configure_sshd () { + local pub_key_line + + cat >> '/mnt/etc/ssh/sshd_config.d/40-defaults.conf' <<"EOF" +PasswordAuthentication no +PermitRootLogin yes +EOF + + while IFS= read -r pub_key_line; do + printf -- '%s\n' "${pub_key_line}" >> '/mnt/root/.ssh/authorized_keys' + done < <(<<<"${ARCHZBM_OS_SSH_AUTH_KEYS}" sed -r -e 's/,,/\n/g') + + systemctl enable 'sshd.service' --root='/mnt' +} + function configure_dns () { #3.4 rm '/mnt/etc/resolv.conf' @@ -1453,6 +1510,9 @@ function finalize_os_setup () { #3.1 set_root_pw #3.2 configure_networking #3.3 + if [[ "${ARCHZBM_OS_SSH_AUTH_KEYS}" ]]; then + configure_sshd + fi configure_dns #3.4 configure_reflector #3.5 configure_zfs #3.6 From d74fc097eb7efe95f564f76fdc11a65eb72374a3 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 04:04:58 +0100 Subject: [PATCH 14/23] refactor(os): Be specific with systemd unit names (#19) --- setup.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.sh b/setup.sh index 601358e..0424583 100644 --- a/setup.sh +++ b/setup.sh @@ -1431,7 +1431,7 @@ function configure_dns () { # Optionally you may want /etc/systemd/network/50-wired.network to use # UseDNS=no and hardcode DNS server(s) here: # sed -i 's/^#DNS=.*/DNS=1.1.1.1/' /mnt/etc/systemd/resolved.conf - systemctl enable 'systemd-resolved' --root='/mnt' + systemctl enable 'systemd-resolved.service' --root='/mnt' } function configure_reflector () { @@ -1441,7 +1441,7 @@ function configure_reflector () { function configure_zfs () { #3.6 - systemctl enable 'zfs-import-cache' 'zfs-mount' 'zfs-import.target' 'zfs.target' --root='/mnt' + systemctl enable 'zfs-import-cache.service' 'zfs-mount.service' 'zfs-import.target' 'zfs.target' --root='/mnt' } function configure_zfs_mount_gen () { From fd2c08a18a3b3ebd5b9eae8f689a02988e21a8a4 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 04:05:21 +0100 Subject: [PATCH 15/23] refactor(os): Always enable NTP (#19) --- setup.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/setup.sh b/setup.sh index 0424583..60ac380 100644 --- a/setup.sh +++ b/setup.sh @@ -1434,6 +1434,10 @@ function configure_dns () { systemctl enable 'systemd-resolved.service' --root='/mnt' } +function configure_ntp () { + systemctl enable 'systemd-timesyncd.service' --root='/mnt' +} + function configure_reflector () { #3.5 systemctl enable 'reflector.service' 'reflector.timer' --root='/mnt' @@ -1514,6 +1518,7 @@ function finalize_os_setup () { configure_sshd fi configure_dns #3.4 + configure_ntp configure_reflector #3.5 configure_zfs #3.6 configure_zfs_mount_gen #3.7 From c344aac77a7b6b2c2febb8ac185b7fd9e56c0bcb Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 04:06:30 +0100 Subject: [PATCH 16/23] refactor(os): Fix comment spacing (#19) --- setup.sh | 58 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/setup.sh b/setup.sh index 60ac380..da20b21 100644 --- a/setup.sh +++ b/setup.sh @@ -1512,20 +1512,20 @@ function umount_all () { function finalize_os_setup () { #3.1 - set_root_pw #3.2 - configure_networking #3.3 + set_root_pw #3.2 + configure_networking #3.3 if [[ "${ARCHZBM_OS_SSH_AUTH_KEYS}" ]]; then configure_sshd fi - configure_dns #3.4 + configure_dns #3.4 configure_ntp - configure_reflector #3.5 - configure_zfs #3.6 - configure_zfs_mount_gen #3.7 + configure_reflector #3.5 + configure_zfs #3.6 + configure_zfs_mount_gen #3.7 if [[ "${part_schema}" = 'gpt' ]]; then - set_new_uefi_boot_entries #3.8 + set_new_uefi_boot_entries #3.8 fi - umount_all #3.9 + umount_all #3.9 } function main () { @@ -1533,29 +1533,29 @@ function main () { arg_parse "${@}" fi if we_are_changerooted; then - install_os_in_chroot #2.2 + install_os_in_chroot #2.2 else - no_kernel_update_in_iso #1.1 - set_ntp #1.2 - resize_cow_space #1.3 - update_pacman_db #1.4 - install_pkgs 'jq' #1.5 - install_zfs #1.6 - uefi_or_bios #1.7 - load_settings_file #1.8 - setup_zpool #1.9 - mount_system #1.10 - copy_zpool_cache #1.11 - install_archlinux #1.12 - gen_fstab #1.13 - set_hostname #1.14 - set_locale #1.15 - add_zfs_hook_to_initramfs #1.16 - set_initramfs_build_list #1.17 - add_zfs_files_to_new_os #1.18 - enter_chroot #2.1 + no_kernel_update_in_iso #1.1 + set_ntp #1.2 + resize_cow_space #1.3 + update_pacman_db #1.4 + install_pkgs 'jq' #1.5 + install_zfs #1.6 + uefi_or_bios #1.7 + load_settings_file #1.8 + setup_zpool #1.9 + mount_system #1.10 + copy_zpool_cache #1.11 + install_archlinux #1.12 + gen_fstab #1.13 + set_hostname #1.14 + set_locale #1.15 + add_zfs_hook_to_initramfs #1.16 + set_initramfs_build_list #1.17 + add_zfs_files_to_new_os #1.18 + enter_chroot #2.1 # We're done in chroot - finalize_os_setup #3.1 + finalize_os_setup #3.1 fi } From 47321313a99327e0a2584fbd7d6b7435dae9853b Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 04:07:44 +0100 Subject: [PATCH 17/23] refactor(os): Fix function numbering (#19) --- setup.sh | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/setup.sh b/setup.sh index da20b21..e6e2fe7 100644 --- a/setup.sh +++ b/setup.sh @@ -1409,6 +1409,7 @@ EOF } function configure_sshd () { + #3.4 local pub_key_line cat >> '/mnt/etc/ssh/sshd_config.d/40-defaults.conf' <<"EOF" @@ -1424,7 +1425,7 @@ EOF } function configure_dns () { - #3.4 + #3.5 rm '/mnt/etc/resolv.conf' ln -s '/run/systemd/resolve/stub-resolv.conf' '/mnt/etc/resolv.conf' @@ -1435,21 +1436,22 @@ function configure_dns () { } function configure_ntp () { + #3.6 systemctl enable 'systemd-timesyncd.service' --root='/mnt' } function configure_reflector () { - #3.5 + #3.7 systemctl enable 'reflector.service' 'reflector.timer' --root='/mnt' } function configure_zfs () { - #3.6 + #3.8 systemctl enable 'zfs-import-cache.service' 'zfs-mount.service' 'zfs-import.target' 'zfs.target' --root='/mnt' } function configure_zfs_mount_gen () { - #3.7 + #3.9 mkdir -p '/mnt/etc/zfs/zfs-list.cache' touch '/mnt/etc/zfs/zfs-list.cache/'"${zpool_name}" zfs list -H -o name,mountpoint,canmount,atime,relatime,devices,exec,readonly,setuid,nbmand | sed 's/\/mnt//' > '/mnt/etc/zfs/zfs-list.cache/'"${zpool_name}" @@ -1457,7 +1459,7 @@ function configure_zfs_mount_gen () { } function set_new_uefi_boot_entries () { - #3.8 + #3.10 declare -a uefi_images mapfile -t uefi_images < \ <(find '/mnt/efi/EFI/ZBM' -type f -iname '*.efi' -print0 | \ @@ -1500,7 +1502,7 @@ function set_new_uefi_boot_entries () { } function umount_all () { - #3.9 + #3.11 if [[ "${part_schema}" = 'mbr' ]]; then umount '/mnt/boot/syslinux' else @@ -1515,17 +1517,17 @@ function finalize_os_setup () { set_root_pw #3.2 configure_networking #3.3 if [[ "${ARCHZBM_OS_SSH_AUTH_KEYS}" ]]; then - configure_sshd + configure_sshd #3.4 fi - configure_dns #3.4 - configure_ntp - configure_reflector #3.5 - configure_zfs #3.6 - configure_zfs_mount_gen #3.7 + configure_dns #3.5 + configure_ntp #3.6 + configure_reflector #3.7 + configure_zfs #3.8 + configure_zfs_mount_gen #3.9 if [[ "${part_schema}" = 'gpt' ]]; then - set_new_uefi_boot_entries #3.8 + set_new_uefi_boot_entries #3.10 fi - umount_all #3.9 + umount_all #3.11 } function main () { From 5f6a5bfdacc06f2db90bf68e75486e54e7ca787c Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 04:20:29 +0100 Subject: [PATCH 18/23] refactor(os): No need to hide kernel version string (#19) --- setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.sh b/setup.sh index e6e2fe7..c2e0cdc 100644 --- a/setup.sh +++ b/setup.sh @@ -68,7 +68,7 @@ function setup_env_vars () { echo '----------------------------------------' echo - read -u3 -p 'Please type kernel version to use, leave empty for latest, confirm with : ' -s ARCHZBM_KERNEL_VER + read -u3 -p 'Please type kernel version to use, leave empty for latest, confirm with : ' ARCHZBM_KERNEL_VER echo echo From 8ed5849596108ee38071faceec11ec749db8a626 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 04:26:11 +0100 Subject: [PATCH 19/23] refactor(os): Phrasing (#19) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 321ada2..b86558c 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ Known options are as follows. ### Kernel downgrade -By default we install newest `linux` and `linux-headers` packages into a `chroot`. Once we're in that `chroot` we then install newest [AUR zfs-dkms package](https://aur.archlinux.org/packages/zfs-dkms). You may want to override `linux` and `linux-headers` versions we're installing to ensure you end up with a compatible mix between them and `zfs-dkms`. +By default we install newest `linux` and `linux-headers` packages into a `chroot`. Once we're in that `chroot` we then install newest [AUR zfs-dkms package](https://aur.archlinux.org/packages/zfs-dkms). You may want to override `linux` and `linux-headers` versions to ensure you end up with a compatible mix between them and `zfs-dkms`. For example: ``` From d467dd66100f7cb294032770aee2e162d0cc9d9c Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sat, 11 Nov 2023 04:35:41 +0100 Subject: [PATCH 20/23] refactor(os): Phrasing (#19) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b86558c..15d2b67 100644 --- a/README.md +++ b/README.md @@ -329,7 +329,7 @@ We strongly suggest to that you: - Firstly, refer to a resource such as the [Arch Linux Archive package version list](https://archive.archlinux.org/packages/l/linux/) to find out what newest kernel version this script will install. - Secondly, research if newest [AUR zfs-dkms package](https://aur.archlinux.org/packages/zfs-dkms) is compatible with that kernel. Two reasonable points of contact are AUR and its comments section for `zfs-dkms` where users quickly report issues; and the [github.com/openzfs/zfs issues list](https://github.com/openzfs/zfs/issues). -An example for this is that `linux-6.6.1.arch1-1-x86_64` released on Wednesday, November 8, 2023 at a time when newest `zfs-dkms` package version [was 2.2.0](https://aur.archlinux.org/cgit/aur.git/commit/?h=zfs-dkms&id=da1b6372c57b16f2781a7fda2b95971bb392c5ee) which did not compile against `linux` 6.6.x. +An example for this is that `linux-6.6.1.arch1-1-x86_64` came out on Wednesday, November 8, 2023 at a time when newest `zfs-dkms` package version [was 2.2.0](https://aur.archlinux.org/cgit/aur.git/commit/?h=zfs-dkms&id=da1b6372c57b16f2781a7fda2b95971bb392c5ee) which did not compile against `linux` 6.6.x. You'd then set for example: ``` From 96b860e0db0d23d39209bcfeb4bcf4c3738d2b34 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sun, 12 Nov 2023 03:31:02 +0100 Subject: [PATCH 21/23] refactor(os): Update interactive questionnaire gif (#19) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 15d2b67..4d29890 100644 --- a/README.md +++ b/README.md @@ -267,7 +267,7 @@ This syntax crutch allows you to use the full range of Dropbear-supported `autho An interactive questionnaire can guide you through settings and goes like this: -![Command line setup questionnaire](https://i.imgur.com/RhCStdu.gif) +![Command line setup questionnaire](https://i.imgur.com/OXG75GH.gif) To do the questionnaire yourself start this script with the `setup` argument: From 6fe5d59108a702f1ab538c81125a2395d4dc0716 Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sun, 12 Nov 2023 03:31:31 +0100 Subject: [PATCH 22/23] refactor(os): remove unneeded line break (#19) --- setup.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.sh b/setup.sh index c2e0cdc..593d2a6 100644 --- a/setup.sh +++ b/setup.sh @@ -70,7 +70,6 @@ function setup_env_vars () { read -u3 -p 'Please type kernel version to use, leave empty for latest, confirm with : ' ARCHZBM_KERNEL_VER echo - echo echo 'Do you want compressed datasets?' select arg_compressed in "Compressed" "Uncompressed"; do From d7d41eec5b9c6477c1cdd1ef307ae691264041ef Mon Sep 17 00:00:00 2001 From: hygienic-books Date: Sun, 12 Nov 2023 03:32:27 +0100 Subject: [PATCH 23/23] refactor(os): Homogenous single quotes (#19) --- setup.sh | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/setup.sh b/setup.sh index 593d2a6..8630a5d 100644 --- a/setup.sh +++ b/setup.sh @@ -72,12 +72,12 @@ function setup_env_vars () { echo echo 'Do you want compressed datasets?' - select arg_compressed in "Compressed" "Uncompressed"; do + select arg_compressed in 'Compressed' 'Uncompressed'; do case "${arg_compressed}" in - Compressed) + 'Compressed') break ;; - Uncompressed) + 'Uncompressed') ARCHZBM_ZFSPROPS_NO_COMPRESSION='true' break ;; @@ -85,12 +85,12 @@ function setup_env_vars () { done <&3 && echo echo 'Do you want encrypted datasets?' - select arg_encrypted in "Encrypted" "Unencrypted"; do + select arg_encrypted in 'Encrypted' 'Unencrypted'; do case "${arg_encrypted}" in - Encrypted) + 'Encrypted') break ;; - Unencrypted) + 'Unencrypted') ARCHZBM_ZFSPROPS_NO_ENCRYPTION='true' break ;; @@ -99,13 +99,13 @@ function setup_env_vars () { if [[ "${arg_encrypted}" = 'Encrypted' ]]; then echo 'Do you want a custom dataset decryption password?' - select arg_custom_dataset_pw in "Yes" "No"; do + select arg_custom_dataset_pw in 'Yes' 'No (use '"'"'password'"'"')'; do case "${arg_custom_dataset_pw}" in - Yes) + 'Yes') want_custom_dataset_pw='true' break ;; - No) + 'No (use '"'"'password'"'"')') break ;; esac @@ -119,13 +119,13 @@ function setup_env_vars () { fi echo 'Do you want a custom '"'"'root'"'"' user password?' - select arg_custom_root_pw in "Yes" "No"; do + select arg_custom_root_pw in 'Yes' 'No (use '"'"'password'"'"')'; do case "${arg_custom_root_pw}" in - Yes) + 'Yes') want_custom_root_pw='true' break ;; - No) + 'No (use '"'"'password'"'"')') break ;; esac @@ -152,7 +152,7 @@ function setup_env_vars () { if [[ "${want_ssh_in_zbm}" ]]; then echo 'How do you want to assign an IP address in ZFSBootMenu?' - select arg_ip_autoconf_method in "Statically" "Dynamically, DHCP" "Dynamically, BOOTP" "Dynamically, RARP"; do + select arg_ip_autoconf_method in 'Statically' 'Dynamically, DHCP' 'Dynamically, BOOTP' 'Dynamically, RARP'; do case "${arg_ip_autoconf_method}" in 'Statically') ARCHZBM_NET_AUTOCONF='none' @@ -188,7 +188,7 @@ function setup_env_vars () { fi echo 'Do you want a custom SSH listening port?' - select arg_custom_ssh_port in "Yes (let me specify)" "No (keep port 22)"; do + select arg_custom_ssh_port in 'Yes (let me specify)' 'No (keep port 22)'; do case "${arg_custom_ssh_port}" in 'Yes (let me specify)') want_custom_ssh_port='true' @@ -206,7 +206,7 @@ function setup_env_vars () { fi echo 'Do you want the SSH daemon to use a custom keepalive send interval?' - select arg_custom_ssh_keepalive_intvl in "Yes (let me specify)" "No (keep 1)"; do + select arg_custom_ssh_keepalive_intvl in 'Yes (let me specify)' 'No (keep 1)'; do case "${arg_custom_ssh_keepalive_intvl}" in 'Yes (let me specify)') want_custom_keepalive_intvl='true' @@ -282,7 +282,7 @@ function setup_env_vars () { fi if [[ "${want_ssh_in_zbm}" ]]; then - echo 'Do you want to define OS root user'"'"'s SSH pub key?' + echo 'Do you want to define OS '"'"'root'"'"' user'"'"'s SSH pub key?' select arg_root_pub_keys in 'Yes (let me specify)' 'Yes (use ZBM pub keys)' 'No (don'"'"'t enable sshd.service)'; do case "${arg_root_pub_keys}" in 'Yes (let me specify)')