Compare commits

..

261 Commits

Author SHA1 Message Date
15d67f2e3f Merge pull request '26-install-zfs-only-when-needed' (#27) from 26-install-zfs-only-when-needed into main
Reviewed-on: #27
2025-01-17 20:11:11 +00:00
6fb13a097c Merge remote-tracking branch 'origin/26-install-zfs-only-when-needed' into 26-install-zfs-only-when-needed 2025-01-17 21:09:40 +01:00
64c66cbd0f fix(zfs): Install ZFS only when needed (#26)
In situations where this script runs on alternative Arch Linux live
CD ISOs such as github.com/stevleibelt/arch-linux-live-cd-iso-with
-zfs we may not have to insall ZFS kernel modules. Test if the 'zfs'
module is loaded and skip installation if yes.
2025-01-17 21:09:19 +01:00
1036ce9c5b fix(zfs): Install ZFS only when needed (#26)
In situations where this script runs on alternative Arch Linux live
CD ISOs such as github.com/stevleibelt/arch-linux-live-cd-iso-with
-zfs we may not have to insall ZFS kernel modules. Test if the 'zfs'
module is loaded and skip installation if yes.
2025-01-17 21:08:44 +01:00
3ae8b53616 build(meta): Don't commit .idea JetBrains dir (#26) 2025-01-17 21:05:53 +01:00
2adac7b94b Add a 2G loop device for emergency swap 2025-01-02 01:00:06 +01:00
9525976fe2 For now no pacman upgrade in ISO 2024-12-28 18:27:29 +01:00
624d278971 For now no pacman upgrade in ISO 2024-12-28 18:21:04 +01:00
08f33c33c7 refactor(os): Retry pacman download on fail 2024-12-28 16:33:13 +01:00
eadbbea2fd Merge pull request '19-define-os-ip' (#24) from 19-define-os-ip into main
Reviewed-on: #24
2023-11-12 03:26:36 +00:00
d7d41eec5b refactor(os): Homogenous single quotes (#19) 2023-11-12 03:32:27 +01:00
6fe5d59108 refactor(os): remove unneeded line break (#19) 2023-11-12 03:31:31 +01:00
96b860e0db refactor(os): Update interactive questionnaire gif (#19) 2023-11-12 03:31:02 +01:00
d467dd6610 refactor(os): Phrasing (#19) 2023-11-11 04:35:41 +01:00
8ed5849596 refactor(os): Phrasing (#19) 2023-11-11 04:26:11 +01:00
5f6a5bfdac refactor(os): No need to hide kernel version string (#19) 2023-11-11 04:20:29 +01:00
47321313a9 refactor(os): Fix function numbering (#19) 2023-11-11 04:07:44 +01:00
c344aac77a refactor(os): Fix comment spacing (#19) 2023-11-11 04:06:30 +01:00
fd2c08a18a refactor(os): Always enable NTP (#19) 2023-11-11 04:05:21 +01:00
d74fc097eb refactor(os): Be specific with systemd unit names (#19) 2023-11-11 04:04:58 +01:00
acc6b2c721 feat(os): Reuse or set SSH pub keys in OS (#19) 2023-11-11 04:04:14 +01:00
d380fc4b6d fix(os): No need to double-quote in a heredoc (#19) 2023-11-11 04:03:09 +01:00
d95d43a22b feat(os): Downgrade kernel when requested (#19) 2023-11-11 04:02:30 +01:00
557db12e8d fix(zbm): ZBM 2.2.2 no longer needs nor has its own stub loader file (#19) 2023-11-11 04:01:59 +01:00
eaf83163b6 refactor(os): Typo (#19) 2023-11-11 04:01:28 +01:00
257648c99d feat(os): Optionally force kernel downgrade for ZFS compatibility (#19) 2023-11-11 04:01:14 +01:00
3903498d40 feat(iso): Modularize network unit file content (#21) 2023-11-11 01:20:32 +01:00
59beb10404 feat(iso): Write OS IPs, gateway, NTP into env file (#21) 2023-11-11 01:19:56 +01:00
d99bb94c52 feat(iso): In setup questionnaire ask for NTP servers (#21) 2023-11-11 01:19:24 +01:00
c9f979a0ad feat(iso): In setup questionnaire ask for OS IP and gateway (#21) 2023-11-11 01:19:01 +01:00
db3c705376 refactor(iso): echo consistently with single quotes (#21) 2023-11-11 01:18:19 +01:00
d5e219dbf5 feat(iso): Add bash-only CIDR calculator function (#21) 2023-11-11 01:17:14 +01:00
bd586e4c67 fix(zfs): Fix multi-line bash command (#21) 2023-11-11 01:16:37 +01:00
d2108276a0 Merge pull request '21-assist-in-env-setup' (#23) from 21-assist-in-env-setup into main
Reviewed-on: #23
2023-11-06 00:39:32 +00:00
ed441299bc fix(iso): Asking for an SSH pub key is mandatory with SSH daemon (#21) 2023-11-06 00:48:40 +01:00
37cafc1f20 fix(iso): Don't reassign settings_file locally (#21) 2023-11-06 00:25:47 +01:00
1bc09b7f8b refactor(os): Install paru-bin instead of paru (#21)
We straight up install paru-bi via its PKGBUILD from
AUR, we skip the additional step we used to do
where we first installed paru from its GitHub
project. This saves time and most importantly
scarce RAM that Rust otherwise needs during
paru compilation.

On systems with little RAM (as in 4 GiB) paru's
compilation process would sometimes fail when
/etc/makepkg.conf when its MAKEFLAGS was
set to use many cores e.g. via "-j$(nproc --ignore 1)".

Without the manual paru compilation step we now
don't need the ability anymore to
--replace-conflicting packages.
2023-11-05 23:29:54 +01:00
1b94e7e3b8 refactor(zbm): Ask for rerun (#21) 2023-11-05 16:57:50 +01:00
e39d60cb00 refactor(zbm): Exit after setting up vars (#21) 2023-11-05 16:55:06 +01:00
055f970f43 docs(zbm): Render asciinema gif with larger typeface (#21) 2023-11-05 16:41:15 +01:00
16e67c8b28 docs(zbm): Typo (#21) 2023-11-05 16:30:48 +01:00
4fb7a91703 docs(zbm): Link to giv instead of mp4 (#21) 2023-11-05 16:30:16 +01:00
2b5d4b4ec8 docs(zbm): Testing HTML image tag in Markdown (#21) 2023-11-05 16:28:17 +01:00
b885bde3c6 docs(zbm): Explain network device naming (#21) 2023-11-05 16:23:00 +01:00
316aa56a55 docs(zbm): Explain interactive questionnaire (#21) 2023-11-05 16:04:57 +01:00
39039ce3fd docs(zbm): No idea if IPv6 works (#21) 2023-11-05 04:53:52 +01:00
1183f3f025 refactor(iso): Rename .gitignore file (#21) 2023-11-05 04:53:17 +01:00
be76d6b0f8 feat(meta): Ignore loca settings file while testing (#21) 2023-11-05 04:52:21 +01:00
67ea72de51 feat(iso): Add setup function to generate answer file (#21) 2023-11-05 04:51:32 +01:00
9f3ada2a36 feat(iso): Parse arguments (#21) 2023-11-05 04:50:31 +01:00
28414af039 refactor(iso): Globally define name of settings file (#21) 2023-11-05 04:49:32 +01:00
58da096eab docs(meta): Typo 2023-11-05 02:37:50 +01:00
5f57698e7d Merge pull request '6-add-ssh-to-bootloader' (#20) from 6-add-ssh-to-bootloader into main
Reviewed-on: #20
2023-11-05 01:35:45 +00:00
2b982be84e docs(meta): Bits and pieces updated (#6) 2023-11-05 02:35:03 +01:00
782168c1b1 docs(zbm): Nudge user to work with Dropbear keepalives (#6) 2023-11-05 02:10:33 +01:00
5cf4b2c325 docs(zbm): Let's not overpromise, the command stanza at first glance seems trickier than anticipated (#6) 2023-11-04 01:16:39 +01:00
a2cb784cb3 feat(zbm): In Syslinux/extlinux mode add KCL (#6) 2023-11-04 01:08:39 +01:00
119be2b876 docs(zbm): Give an example ip= KCL (#6) 2023-11-04 00:46:44 +01:00
9560677352 fix(zbm): Link to dropbear patch hooks (#6) 2023-11-04 00:41:37 +01:00
52c09fc93f docs(zbm): Explain Syslinux KCL (#6) 2023-11-04 00:37:30 +01:00
1181432add docs(iso): Explain sed in_array_remove_n mechanism (#6) 2023-11-04 00:32:16 +01:00
e3025883fa docs(iso): Explain sed insert_n_at_the_end mechanism (#6) 2023-11-04 00:32:01 +01:00
79feaed5ac docs(iso): Explain sed insert_n_before_m mechanism (#6) 2023-11-04 00:20:39 +01:00
7338924c82 docs(zbm): Explain networking and SSH (#6) 2023-11-04 00:08:48 +01:00
924925e08e docs(iso): Do a pass over how we explain passwords for local accounts (#6) 2023-11-04 00:03:42 +01:00
3030eb0f2d docs(iso): Use either an env options file or shell exports (#6) 2023-11-04 00:01:29 +01:00
305e4191f1 docs(zfs): Correctly umount after maintenance (#6) 2023-11-04 00:00:03 +01:00
7d5075a543 fix(ZBM): No KCL inside Syslinux (#6) 2023-11-03 23:43:06 +01:00
003d3f4f2a fix(ZBM): Remove ZBM hook from correct file (#6) 2023-11-03 03:24:33 +01:00
ab5e79d838 refactor(iso): Parallelize pacman in ISO (#6) 2023-11-03 03:24:03 +01:00
53f92032a4 feat(zbm): Add KCL to legacy BIOS ZBM (#6) 2023-11-03 01:40:24 +01:00
b160b4a1e1 feat(zbm): Prepare SSH in ZBM (#6) 2023-11-03 01:38:56 +01:00
1690518197 feat(zbm): Define Dropbear's SSH pub keys (#6) 2023-11-03 01:38:28 +01:00
732cc47405 feat(zbm): Add networking/IP addressing setup to ZBM (#6) 2023-11-03 01:38:11 +01:00
be668b1bdc feat(zbm): Add user's dropbear customizations (#6) 2023-11-03 01:37:38 +01:00
53ed730957 feat(zbm): Add dropbear hook files (#6) 2023-11-03 01:37:15 +01:00
9a89ce4f75 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.
2023-11-01 03:53:18 +01:00
3cb68406ed feat(os): Add SSH to ZBM if requested by user (#6) 2023-11-01 03:49:46 +01:00
33966071ce refactor(os): Simplify mkinitcpio.conf manipulation (#6) 2023-11-01 03:49:05 +01:00
4e734330da feat(os): Add helper functions to manipulate HOOKS array (#6) 2023-11-01 03:47:34 +01:00
f1bab6bc60 refactor(os): Simplify extended regex (#6) 2023-11-01 03:05:43 +01:00
a41d0599e6 Merge pull request '9-settings-file' (#14) from 9-settings-file into main
Reviewed-on: #14
2023-10-27 03:05:46 +00:00
d1ad95dc76 docs(meta): Explain password requirement (#5) 2023-10-27 05:02:53 +02:00
5d03799dae refactor(meta): Renumber functions (#9) 2023-10-27 04:24:40 +02:00
cf50632b6c feat(iso): Allow supplementary password/settings file (#9) 2023-10-27 04:23:11 +02:00
b83cce2aec docs(meta): Link to hook Git repos (#5) 2023-10-27 03:14:20 +02:00
bb8c052f8b Merge pull request '5-auto-regen-zbm' (#13) from 5-auto-regen-zbm into main
Reviewed-on: #13
2023-10-27 01:09:08 +00:00
edd104ed1c docs(meta): Adjust for UEFI/legacy BIOS difference (#5) 2023-10-27 02:49:03 +02:00
9f0f19355e docs(iso): Master Boot Record capitalized (#5) 2023-10-27 02:15:46 +02:00
0b3f5b75dd docs(iso): EFI System Partition capitalized (#5) 2023-10-27 02:14:36 +02:00
04f206129f docs(iso): Typo (#5) 2023-10-27 02:12:36 +02:00
e42e92874e docs(iso): Explain UEFI/legacy BIOS reqirements (#5) 2023-10-27 02:12:09 +02:00
56dc2f85a6 docs(iso): Homogenize MBR partition type codes (#5) 2023-10-27 02:11:27 +02:00
a00b8e8009 refactor(meta): Update lsblk UEFI/GPT output (#5) 2023-10-27 01:55:35 +02:00
844f574e2d refactor(meta): Renumber functions (#5) 2023-10-27 01:47:53 +02:00
b0842ac9ba refactor(zbm): ZBM image names are now static, no need to regen UEFI boot entries (#5) 2023-10-27 01:46:56 +02:00
03ed6e076d fix(zbm): Use stub file, not its parent directory for image rebuilds (#5) 2023-10-27 01:43:20 +02:00
b5666493f1 feat(zbm): Add pacman hook to auto-regen ZBM image files after package upgrade (#5) 2023-10-27 01:41:19 +02:00
81a7fcd64c fix(zbm): ZBM now comes with an EFI stub loader file, we use that (#5) 2023-10-27 00:23:33 +02:00
a0a05b60d1 fix(os): For BIOS/syslinux hook add rsync dependency (#5) 2023-10-26 03:04:37 +02:00
5f98a971ec fix(os): Specify maintenance instructions for UEFI/BIOS (#5) 2023-10-26 03:02:34 +02:00
61c220afd7 feat(os): Add pacman hook to regen syslinux on upgrade (#5) 2023-10-26 02:32:26 +02:00
544b0074e2 Merge pull request '7-add-legacy-bios-support' (#8) from 7-add-legacy-bios-support into main
Reviewed-on: #8
2023-10-24 00:25:34 +00:00
33e7498529 fix(iso): export vars we'll be needing inside a subshell (#7) 2023-10-23 23:53:11 +02:00
d059cb6ae0 fix(iso): Try and improve mirrorlist handling (#7) 2023-10-23 03:02:23 +02:00
e3d5f2b939 fix(iso): Try and improve mirrorlist handling (#7) 2023-10-23 02:52:10 +02:00
615b8c0e95 fix(iso): Find zfs partition on legacy BIOS machine (#7) 2023-10-23 02:28:01 +02:00
d685431684 feat(iso): Use jq only after it's installed (#7) 2023-10-23 02:16:02 +02:00
2f41de67c6 feat(os): Finalize and umount on legacy BIOS machine (#7) 2023-10-23 02:05:25 +02:00
84266e66cf feat(os): Create syslinux boot loader for legacy BIOS machine (#7) 2023-10-23 02:01:36 +02:00
a654f1ad14 feat(iso): Mount drives on legacy BIOS machine (#7) 2023-10-23 01:18:38 +02:00
78053e813a feat(iso): Select correct partition for zpool on a legacy BIOS machine (#7) 2023-10-23 01:01:18 +02:00
3eee3cbe6b feat(iso): Crudely detect BIOS vs. UEFI intent (#7) 2023-10-23 00:46:15 +02:00
73001c8e95 docs(iso): Differentiate between UEFI and legacy BIOS (#7) 2023-10-23 00:08:27 +02:00
ffa322afdd refactor(iso): Fewer packages needed in ISO (#7) 2023-10-22 16:35:49 +02:00
38396d7ccf Merge pull request '3-xen-orchestra-install' (#4) from 3-xen-orchestra-install into main
Reviewed-on: #4
2023-10-22 14:23:53 +00:00
4e795c9cb7 docs(zfs): Export zpool when done working on it (#3) 2023-10-22 16:04:43 +02:00
2e39075273 docs(zfs): Fewer single quotes (#3) 2023-10-22 15:50:45 +02:00
4dab010efd docs(zfs): Export zpool when done working on it (#3) 2023-10-22 15:48:33 +02:00
1a138068d1 refactor(zbm): No ZBM image versioning beyond a main and a backup file (#3) 2023-10-22 15:47:24 +02:00
7133883a5e docs(zfs): Explain how to mount externally (#3) 2023-10-22 15:29:46 +02:00
ae00207947 refactor(zbm): Point to chroot (#3) 2023-10-22 15:26:50 +02:00
108883fd11 docs(meta): Update lsblk output (#3) 2023-10-22 14:48:46 +02:00
cc6e17f06c fix(zbm): Correctly set EFI loader paths (#3) 2023-10-22 14:42:24 +02:00
214f82becf fix(zbm): Use a known good stub loader file (#3)
This works around https://github.com/zbm-dev/zfsbootmenu/issues/503
2023-10-22 14:41:46 +02:00
0fa1564405 fix(zbm): We may want to actually run our ZBM postconf hook (#3) 2023-10-22 03:22:12 +02:00
a9c9b3d788 refactor(iso): Typo (#3) 2023-10-22 02:00:16 +02:00
d3be536516 refactor(iso): Typo (#3) 2023-10-22 01:59:42 +02:00
5d359a3f39 refactor(iso): No kernel updates in ISO (#3) 2023-10-22 01:52:33 +02:00
290e659d29 refactor(zfs): Single-quote dataset options for consistency (#3) 2023-10-22 01:39:57 +02:00
f2213c2ec2 refactor(meta): Unify ISO name (#3) 2023-10-22 01:38:59 +02:00
4645a44333 docs(meta): UPdate lsblk output (#3) 2023-10-22 01:38:05 +02:00
863cee4322 refactor(meta): Remove trailing whitespace (#3) 2023-10-22 01:35:45 +02:00
9d41aabb3e docs(meta): Start with a one-liner (#3) 2023-10-22 01:34:49 +02:00
d1407f00a9 refactor(meta): Update function numbering (#3) 2023-10-21 05:14:38 +02:00
767e9c3b42 refactor(meta): Reorder functions (#3) 2023-10-21 05:09:25 +02:00
915ded9c1b refactor(zbm): Update UEFI boot entries when images are done (#3) 2023-10-21 05:08:22 +02:00
598b176ec6 refactor(zbm): Add ZBM postconf hook (#3)
We're adding this to our chroot after we've
generated a ZBM UEFI image file /without/
this hook script. It's meant to run only in our real
OS.
2023-10-21 05:07:02 +02:00
dcc3cf7d93 refactor(zbm): Streamline ZBM image creation (#3) 2023-10-21 05:05:17 +02:00
be63ed90ad refactor(zbm): We're not building in Arch Linux live CD ISO image (#3)
We don't need rsync anymore either since we
won't have to shuffle UEFI images around.
2023-10-21 05:03:09 +02:00
abffd08c1e feat(zbm): Add ZBM postconf hook to update UEFI bootnums (#3) 2023-10-21 04:48:11 +02:00
b36d4d33c3 refactor(os): pacman install in one go (#3) 2023-10-21 01:54:28 +02:00
b0c50f3323 refactor(os): Get ZFS modules installed before we need them (#3) 2023-10-21 01:25:22 +02:00
da88ec53a6 refactor(meta): ZFS installs in one go should now work (#3) 2023-10-21 00:58:23 +02:00
e92a22c005 refactor(meta): Quoting because we can (#3) 2023-10-21 00:57:57 +02:00
de4f3f2066 refactor(os): Do normal pacman installs, don't prepend keyring nor ZFS installs (#3) 2023-10-21 00:57:32 +02:00
c7e59ba0cb refactor(meta): Explain fd 3 logging and add more of it (#3) 2023-10-21 00:56:26 +02:00
b5c9ba4127 refactor(meta): Print key log output to stdout without capturing it in subshells (#3) 2023-10-21 00:34:13 +02:00
40948ddbae refactor(meta): Print key log output to stdout without capturing it in subshells (#3) 2023-10-21 00:32:16 +02:00
8566b41452 refactor(iso): Inform user partition's missing (#3) 2023-10-21 00:19:30 +02:00
e08697b7fa feat(os): Add a few /etc/motd pointers (#3) 2023-10-20 23:34:31 +02:00
589d66d22b fix(zfs): Make sure root dataset cannot be mounted on accident (#3) 2023-10-20 22:47:05 +02:00
61be86a820 fix(zbm): Update ESP paths to images, install both recovery and release (#3) 2023-10-20 22:34:19 +02:00
b34842434e refactor(os): Get ZFS modules installed before we need them (#3) 2023-10-20 22:17:13 +02:00
c46c78ba92 refactor(os): Set up locale before we do pacman work (#3) 2023-10-20 21:57:27 +02:00
6c25b92113 fix(iso): Force-refresh pkg list, force-upgrade and downgrade pkgs to exactly match repos (#3) 2023-10-20 21:44:30 +02:00
8ad2694dd4 fix(os): Mount chroot before building zfsbootmenu-efi-bin package (#3) 2023-10-20 19:26:05 +02:00
362abe39fc fix(os): Install ZFS as a dependency before building zfsbootmenu-efi-bin package (#3) 2023-10-20 19:21:41 +02:00
c5e0216041 fix(os): Increase CoW space before we start (#3) 2023-10-20 19:19:35 +02:00
9550eceaab feat(os): Replace manually building ZBM UEFI image with AUR package (#3) 2023-10-20 19:04:55 +02:00
4cebd834de fix(os): Enable reflector.timer unit (#3) 2023-10-20 19:03:40 +02:00
7a07b18156 fix(os): Write root password with specific --crypt-method (#3) 2023-10-20 19:01:59 +02:00
7093621049 refactor(meta): Update function numbering (#3) 2023-10-20 18:58:25 +02:00
503ab0b58b feat(os): Replace manually building ZBM UEFI image with AUR package (#3) 2023-10-20 18:48:50 +02:00
b63164f2ad feat(os): Give ourselves rsync in chroot (#3) 2023-10-20 18:30:58 +02:00
e9602491df feat(os): Install base-devel and git before we chroot (#3) 2023-10-20 17:43:46 +02:00
148f930636 refactor(os): Allow AUR helper to replace itself (#3) 2023-10-20 16:30:29 +02:00
66eb02ff7d refactor(meta): Add function numbering (#3) 2023-10-20 15:41:17 +02:00
5cb1e6b1f2 refactor(os): Remind ourselves /etc/pacman.conf is ephemeral (#3) 2023-10-20 15:37:56 +02:00
1ac2353d64 refactor(os): Default pacman to 20 parallel downloads (#3) 2023-10-20 15:35:17 +02:00
b9d9548929 docs(meta): Typo (#3) 2023-10-20 15:30:01 +02:00
93932a522e docs(meta): Default to 512 MiB EFS instead of 100 MiB (#3)
Testing shows 100 MiB is a bit tight with a backup
UEFI image and future growth.
2023-10-20 15:29:40 +02:00
6b12f31866 refactor(meta): Trim trailing whitespace (#3) 2023-10-20 15:26:22 +02:00
2876f55e82 refactor(meta): Add function numbering (#3) 2023-10-20 15:24:39 +02:00
29a5ede899 refactor(meta): Move we_are_changerooted function to top (#3) 2023-10-20 15:15:39 +02:00
63974a2dff docs(os): Explain NetworkManager interaction (#3) 2023-05-30 22:56:18 +02:00
310b180580 docs(zfs): Display mounted state in ZFS example (#3) 2023-05-16 14:12:56 +02:00
ec7931cb4c docs(zfs): Warn about nested datasets creation and auto-mounting (#3) 2023-05-16 14:11:14 +02:00
1f70342aad fix(os): Only diff between DNS and static IP, keep the rest same (#3) 2023-04-29 17:11:55 +02:00
f0c75b735b docs(os): Typo (#3) 2023-03-27 23:19:58 +02:00
85e2640471 docs(os): We scan for a zpool in /dev/disk/by-partuuid now, (#3) 2023-03-27 23:15:46 +02:00
535073a3c2 docs(os): Typo (#3) 2023-03-27 23:13:00 +02:00
412eb93c60 docs(os): Typo (#3) 2023-03-27 23:10:47 +02:00
0cd149f8cb docs(os): Typo (#3) 2023-03-27 23:00:19 +02:00
8f131e3aaf docs(os): Typo (#3) 2023-03-27 22:57:17 +02:00
ecc33655db docs(ZFS): Explain adding a new BE-independent dataset (#3) 2023-03-27 22:53:38 +02:00
9af9572f36 docs(os): Typo (#3) 2023-03-27 16:11:58 +02:00
adde942cff docs(os): Typo (#3) 2023-03-27 02:47:30 +02:00
4973217ff5 docs(os): Typo (#3) 2023-03-27 02:46:13 +02:00
6cecb438a7 docs(os): Typo (#3) 2023-03-27 02:44:46 +02:00
5f8f407e95 docs(os): Typo (#3) 2023-03-27 02:42:49 +02:00
16c746e9d4 feature(zfs): Optionally don't compress and/or don't encrypt (#3) 2023-03-27 02:40:27 +02:00
2f209db426 refactor(os): Check efibootmgr output quitely (#3) 2023-03-27 02:25:51 +02:00
ef029186fe docs(os): Explain static systemd network config (#3) 2023-03-27 02:25:23 +02:00
ba181c5fce feat(zfs): Allow toggle for compression and encryption (#3) 2023-03-27 00:46:16 +02:00
7f2b16c6a4 fix(os): Stop pacman from doing it's CheckSpace on ZFS (#3) 2023-03-27 00:45:43 +02:00
7384dd769b docs(os): Explain sgdisk disk setup (#3) 2023-03-26 21:14:45 +02:00
af9deec753 docs(os): EFI partition must be mountable (#3) 2023-03-26 19:11:50 +02:00
005fe43352 refactor(os): We look for partition IDs in /dev/disk/by-partuuid (#3) 2023-03-26 19:03:20 +02:00
b9da09402a fix(os): Identify disk by partition UUID (#3) 2023-03-26 17:26:02 +02:00
e951e077a0 fix(os): Identify disk by partition UUID (#3) 2023-03-26 17:24:46 +02:00
12038d3eaf docs(zfs): First clean-up then Unmap/TRIM 2023-03-05 06:04:00 +01:00
fefabf2c6e docs(zfs): Add Unmap/TRIM commands (#1) 2023-03-05 06:02:11 +01:00
176a7e89b8 Merge pull request '1-get-initial-setup-working' (#2) from 1-get-initial-setup-working into main
Reviewed-on: #2
2023-03-05 03:02:47 +00:00
1c17351d86 docs(zfs): Typo (#1) 2023-03-05 04:01:50 +01:00
9943b6c61b docs(zfs): Explain how to confirm new master key (#1) 2023-03-05 04:00:51 +01:00
a19adbfe28 docs(zfs): Clarify reboot first, then update encryptionroot (#1) 2023-03-05 04:00:26 +01:00
10c9ae589f docs(zfs): Clarify reencryption in flight (#1) 2023-03-05 04:00:00 +01:00
930d5f4687 fix(zfs): After password change always zfs change-key (#1) 2023-03-05 03:59:25 +01:00
60136f4807 docs(zfs): Minor style fixes (#1) 2023-03-05 03:59:06 +01:00
9b11a12f4c docs(zfs): Reformat password change headline (#1) 2023-03-05 03:58:15 +01:00
bfc6f814ef docs(zfs): Explain how to rekey all data with new master key after user key change (#1) 2023-03-05 03:34:59 +01:00
a2ca77b70a feat(os): Let's assume we want a DNS server pushed via DHCP (#1) 2023-03-04 23:43:11 +01:00
58919e0d7f fix(os): Find /etc/makepkg.conf both with and without chroot (#1) 2023-03-04 23:21:06 +01:00
dd1fcb0c72 feat(zfs): Explain password change and caveats (#1) 2023-03-04 23:12:49 +01:00
96ab417c72 fix(zfs): chmod 000 ZFS encryption keyfile per ZBM's docs (#1) 2023-03-04 18:09:34 +01:00
a5f32cfe76 fix(iso): Propagate EFI drive to efibootmgr (#1) 2023-02-23 03:42:30 +01:00
05f2aa8035 fix(iso): Fix EFI part UUID (#1) 2023-02-23 03:22:00 +01:00
877e948941 fix(iso): Don't unleash too early when no makepkg exists (#1) 2023-02-23 03:21:09 +01:00
e1a6599a6e fix(iso): Only pick ZFS/BF00 partition for install (#1) 2023-02-23 02:38:22 +01:00
616272a069 fix(iso): Close quote (#1) 2023-02-23 02:22:51 +01:00
5cad96b5e2 refactor(iso): Always pick EFI partition based on ZFS drive selection (#1) 2023-02-23 02:16:12 +01:00
91f4022ad1 refactor(iso): Always pick EFI partition based on ZFS drive selection (#1) 2023-02-23 02:08:08 +01:00
60b8ff36d5 refactor(iso): Do JSON tree output (#1) 2023-02-23 02:03:37 +01:00
c3833c397b refactor(iso): Remove unused var (#1) 2023-02-23 01:56:09 +01:00
3df24d8311 refactor(iso): If we fail to pick a single EFI partition just exit (#1) 2023-02-23 01:54:22 +01:00
e36822678c refactor(iso): Local var is sensible (#1) 2023-02-23 01:53:57 +01:00
05b6a1aeaa refactor(iso): Try to pick EFI partition on same drive as zpool (#1) 2023-02-23 01:53:40 +01:00
d18ad238d5 refactor(iso): Correctly print and exit when in subshell (#1) 2023-02-23 01:52:10 +01:00
38ca0c9cd3 refactor(iso): Indicate that zpool_drive will be used globally (#1) 2023-02-23 01:51:19 +01:00
fdc9046726 fix(zfs): If we're seeing more than one ZFS partition exit (#1) 2023-02-23 01:27:10 +01:00
e443f66832 feat(os): Enable the reflector systemd service unit (#1) 2023-02-23 01:18:18 +01:00
c66e910146 feat(os): Always do 5 parallel pacman downloads (#1) 2023-02-23 01:15:13 +01:00
f9b2f144a6 docs(os): Add a getting started motd (#1) 2023-02-23 01:13:26 +01:00
ac0e7dadf1 docs(zbm): bootfs property indicates preferred/default boot environment (#1) 2023-02-23 01:03:29 +01:00
f9cb8c57a3 refactor(iso): When multiple drive IDs pick lexicographically first (#1) 2023-02-23 01:00:11 +01:00
5ea002201f refactor(iso): drive_id can be a list without us knowing (#1) 2023-02-23 00:58:01 +01:00
73258c22b0 refactor(iso): Keep drive_id local (#1) 2023-02-23 00:57:06 +01:00
d5f6e62b56 fix(iso): Don't store subshell error msgs in vars, exit completely (#1) 2023-02-23 00:56:03 +01:00
61cffda88b fix(iso): Unleash makepkg core count (#1) 2023-02-23 00:48:17 +01:00
1290869dfe feat(os): For default AUR builds increase makepkg core use (#1) 2023-02-21 03:53:58 +01:00
35dacb977c fix(os): Actually scratch daemon-reload, no daemon here to reload in a chroot (#1) 2023-02-21 03:46:27 +01:00
0f6cc4aa13 fix(os): In chroot without active systemd 'enable --now' won't work (#1) 2023-02-21 03:41:36 +01:00
8aa2f6ea44 fix(os): After adding new systemd unit files we need to daemon-reload (#1) 2023-02-21 03:39:18 +01:00
97bebe9a99 refactor(iso): ZFS partition selection happens only inside setup_zpool (#1) 2023-02-21 03:27:56 +01:00
1fb3cc37eb refactor(iso): Trust that ZFS partition selection works, remove if-else clause (#1) 2023-02-21 03:02:57 +01:00
a970a3d179 refactor(iso): Rely on select_part for ZFS partition identification (#1) 2023-02-21 03:02:28 +01:00
c27f0e9c7c refactor(iso): Rely on select_part for EFI partition identification (#1) 2023-02-21 03:01:57 +01:00
10440fc6d7 refactor(iso): Use refactored get_drive_id to get drive ID (#1) 2023-02-21 03:01:21 +01:00
ed737409e6 refactor(iso): Loically sort no_zpool_exists lower (#1) 2023-02-21 03:00:55 +01:00
ef03281a63 refactor(iso): Rewrite get_drive_id to be more broadly applicable (#1) 2023-02-21 03:00:25 +01:00
8d38827cd1 feat(iso): Interactively ask for ZFS/EFI partition choice if needed (#1) 2023-02-21 02:58:55 +01:00
49fe3deced refactor(iso): No need to hard-fail when more than one of a partition type exists, we ask for a choice instead (#1) 2023-02-21 02:58:02 +01:00
b12c35ed07 refactor(iso): Uppercase partition type (#1) 2023-02-21 02:57:13 +01:00
c3708a098e refactor(iso): Keep partition count vars local (#1) 2023-02-21 02:56:44 +01:00
c367be8845 docs(zfs): Expand on ZFS bootfs property (#1) 2023-02-21 01:03:29 +01:00
4bf236df75 docs(zfs): Explain ZFS dataset structure in plain English (#1) 2023-02-21 00:54:58 +01:00
155e36dc60 refactor(os): Earlier systemd path unit setup (#1) 2023-02-21 00:40:16 +01:00
23ca5f0c65 refactor(os): Remove existing initramfs fallback files when we remove them from build instructions (#1) 2023-02-21 00:38:55 +01:00
6cee2ab403 feat(os): chmod 0600 new initramfs files, they contain our pool password (#1) 2023-02-21 00:36:06 +01:00
0f099b1d45 docs(zfs): Key file may have newline at the end, ZFS doesn't care (#1) 2023-02-21 00:10:03 +01:00
3 changed files with 2007 additions and 270 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
archzbm_settings.env
.idea

708
README.md
View File

@@ -2,39 +2,342 @@
Helper script to install Arch Linux with ZFSBootMenu from within a running Arch Linux live CD ISO image
# Prep
## Prep
We expect minimal prep on your end. Please make sure that before execution the following conditions are met.
### UEFI
On a UEFI system ensure these conditions are met. See [How to prep](#how-to-prep) for details on how to meet these conditions.
- One GPT-partitioned disk
- Arch Linux live CD ISO image sees exactly one partition with partition type code `BF00` ("Solaris root")
- Arch Linux live CD ISO image sees exactly one partition with partition type code `EF00` ("EFI system partition")
- Arch Linux live CD ISO image sees exactly one partition with partition type code `EF00` ("EFI System Partition")
- The `EF00` EFI partition is mountable, in practical terms this usually only means it has a file system.
- No ZFS zpool exists
The script will create a single ZFS zpool `zpool` on the `BF00` partition with dataset child `zpool/root` which itself has one child `zpool/root/archlinux`, that's where Arch Linux gets installed. Parallel to `zpool/root` it'll create `zpool/data` with a `zpool/data/home` child dataset that gets mounted at `/home`.
### Legacy BIOS
The script will use the `EF00` partition to install a ZFSBootMenu EFI executable if `efibootmgr` says that no such `ZFSBootMenu` entry exists. If ZFSBootMenu gets added to the EFI partition it'll become primary boot option.
If you are instead running a legacy BIOS machine ensure these conditions are met. See [How to prep](#how-to-prep) for details on how to meet these conditions.
- One MBR-partitioned disk
- Arch Linux live CD ISO image sees exactly one partition with partition type code `bf` ("Solaris root")
- Arch Linux live CD ISO image sees exactly one partition with partition type code `83` ("Linux")
- The `83` Linux partition is mountable, in practical terms this usually only means it has a file system.
- No ZFS zpool exists
Neither with a UEFI nor legacy BIOS system are any of these conditions a requirement from ZFSBootMenu. We're just setting requirements to easily identify if you intend to do a UEFI or a legacy BIOS install. Subsequently the script has no logic to detect UEFI or legacy BIOS mode, that's legwork left to the reader :) The Internet seems to agree that a good quick check is to see if your Arch Linux live CD ISO image has directory `/sys/firmware/efi`.
```
[ -d /sys/firmware/efi ] && echo 'Likely a UEFI system' || echo 'Probably a legacy BIOS system'
```
If you're unsure nothing's stopping you from just giving it a go with a best guess and if that fails you know you guessed wrong.
## How to prep
### UEFI
On a blank example disk `/dev/sda` you can fulfill the UEFI requirements (one `EF00` partition with a file system plus one `BF00` partition) for example like so:
```
sgdisk --new '1::+512M' --new '2' --typecode '1:EF00' --typecode '2:BF00' /dev/sda
mkfs.vfat /dev/sda1
```
> `--new '1::+512M'`: Create partition number `1`. The field separator `:` separates the partition number from start sector. In this case start sector is unspecified so start sector sits at whatever the system's default is for this operation. On a blank disk on an Arch Linux live CD ISO image this will default to sector `2048`. Partition ends at whatever the beginning is `+512M` meaning plus 512 Mebibytes.
>
> `--new '2'`: Create partition number `2`. Both field number 2, the start sector, and field number 3, the end sector, are unspecified, there's no field separator `:`. Field number 2 will be the first free sector - in this case right after partition 1 - and field number 3 will be end of disk. Thus partition `2` will fill the remaining free disk space.
>
> `--typecode '1:EF00'`: Partition 1 gets partition type code `EF00`, an EFI System Partition.
>
> `--typecode '2:BF00'`: Partition 2 gets partition type code `BF00`, a Solaris root partition.
The result will be something like this at which point you can start the `setup.sh` script, see [How to run this?](#how-to-run-this) below for more details.
```
# lsblk --paths --output 'NAME,SIZE,FSTYPE,PARTTYPE,PARTTYPENAME,PTTYPE' /dev/sda
NAME SIZE FSTYPE PARTTYPE PARTTYPENAME PTTYPE
/dev/sda 10G gpt
├─/dev/sda1 512M vfat c12a7328-f81f-11d2-ba4b-00a0c93ec93b EFI System gpt
└─/dev/sda2 9.5G 6a85cf4d-1dd2-11b2-99a6-080020736631 Solaris root gpt
```
### Legacy BIOS
For a legacy BIOS machine you'll be using a Master Boot Record (MBR) on your disk.
```
printf -- '%s\n' 'label: dos' 'start=1MiB, size=512MiB, type=83, bootable' 'start=513MiB, size=+, type=bf' | sfdisk /dev/sda
mkfs.vfat /dev/sda1
```
> `label: dos`: Create the following partition layout in a Master Boot Record.
>
> `start=1MiB, size=512MiB, type=83, bootable`: Partition 1 begins 1 Mebibyte after disk start and is 512 Mebibyte in size. We're setting its bootable flag and setting partition type code `83` ("Linux").
>
> `start=513MiB, size=+, type=bf`: Partition 2 begins right at the start of Mebibyte 513, this is the very next sector after the end of partition 1. It takes up the remaining disk space, we're assigning type code `bf` ("Solaris").
The result will be something like this at which point you can start the `setup.sh` script, see [How to run this?](#how-to-run-this) below for more details.
```
# lsblk --paths --output 'NAME,SIZE,FSTYPE,PARTTYPE,PARTTYPENAME,PTTYPE' /dev/sda
NAME SIZE FSTYPE PARTTYPE PARTTYPENAME PTTYPE
/dev/sda 10G dos
├─/dev/sda1 512M vfat 0x83 Linux dos
└─/dev/sda2 9.5G 0xbf Solaris dos
```
# Partition naming
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
The script will create a single ZFS zpool `zpool` on the zpool partition with dataset child `zpool/root` which itself has one child `zpool/root/archlinux`, that's where Arch Linux gets installed. Parallel to `zpool/root` it'll create `zpool/data` with a `zpool/data/home` child dataset that gets mounted at `/home`.
# How to run this?
- Boot an Arch Linux live CD ISO image
- Run:
```
export SCRIPT_URL='https://quico.space/quico-os-setup/arch-zbm/raw/branch/main/setup.sh'
curl -s "${SCRIPT_URL}" | bash
export SCRIPT_URL='https://quico.space/quico-os-setup/arch-zbm/raw/branch/main/setup.sh' && curl -s "${SCRIPT_URL}" | bash
```
During execution the script will call itself when it changes into its `chroot`, that's why we `export SCRIPT_URL`. Feel free to update `"${SCRIPT_URL}"` with whatever branch or revision you want to use from [quico.space/quico-os-setup/arch-zbm](https://quico.space/quico-os-setup/arch-zbm). Typically `.../branch/main/setup.sh` as shown above is what you want.
## 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. You can walk yourself through an interactive questionnaire that helps create a valid `archzbm_settings.env` file. Check out [Command line setup help](#command-line-setup-help) for details on the questionnaire.
If you instead want to define settings yourself with an `archzbm_settings.env` file its 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.
### 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 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 <pool>` to check this feature's status on your `<pool>`.
To get a zpool with uncompressed datasets export the shell variable `ARCHZBM_ZFSPROPS_NO_COMPRESSION` with any value prior to running this script. Literally any value works as long as you're not setting this to an empty string:
```
export ARCHZBM_ZFSPROPS_NO_COMPRESSION=yesplease
```
### Encryption
By default we encrypt the zpool with ZFS property `encryption=on`. In ZFS 2.1.9 this defaults to `encryption=aes-256-gcm`.
To get a zpool with unencrypted datasets export the shell variable `ARCHZBM_ZFSPROPS_NO_ENCRYPTION` with any value prior to running this script:
```
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 before script execution as follows:
```
ARCHZBM_ZPOOL_PASSWORD='a fancy password'
ARCHZBM_ROOT_PASSWORD='t0psecr3t!'
```
> 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. It's intended as a helper for system setup tasks such as `sudo -u build paru -S <package>` 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 <user>
passwd <user>
```
### 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
> IPv6 addresses are untested. Script has been confirmed working with IPv4 addresses.
```
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 interface 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 |
+-------------+------------------------+
| <client-ip> | ARCHZBM_NET_CLIENT_IP |
| <server-ip> | ARCHZBM_NET_SERVER_IP |
| <gw-ip> | ARCHZBM_NET_GATEWAY_IP |
| <netmask> | ARCHZBM_NET_NETMASK |
| <hostname> | ARCHZBM_NET_HOSTNAME |
| <device> | ARCHZBM_NET_DEVICE |
| <autoconf> | 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.
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'
```
> In ZFSBootMenu the device names that go into `ARCHZBM_NET_DEVICE` are raw unchanged kernel device names such as `eth0`. If you're unsure which device name to use in your Arch Linux live CD ISO image check `dmesg` output. During boot typically a kernel module will first assign the raw kernel device name then later `systemd` will enforce [Predictable Network Interface Names](https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/).
>
> In `dmesg | grep` on a physical PC with an MSI B550-A Pro mainboard from 2020 that comes with one onboard Realtek RTL8111H network adapter governed by the Realtek RTL-8169 Gigabit Ethernet driver from the `r8169` kernel module you will for example see:
> ```
> # dmesg -T | grep eth
> [time] r8169 0000:2a:00.0 eth0: RTL8168h/8111h, 04:7c:16:00:01:02, XID 541, IRQ 95
> [time] r8169 0000:2a:00.0 eth0: jumbo features [frames: 9194 bytes, tx checksumming: ko]
> [time] r8169 0000:2a:00.0 enp42s0: renamed from eth0
> ```
>
> Notice how a Predictable Network Interface Name comes in on line 3. What *__you__* need here is the `eth0` part.
#### 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. 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:
```
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. 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.
## Command line setup help
An interactive questionnaire can guide you through settings and goes like this:
![Command line setup questionnaire](https://i.imgur.com/OXG75GH.gif)
To do the questionnaire yourself start this script with the `setup` argument:
```
export SCRIPT_URL='https://quico.space/quico-os-setup/arch-zbm/raw/branch/main/setup.sh' && curl -s "${SCRIPT_URL}" | bash -s -- setup
```
When done rerun it without that argument:
```
export SCRIPT_URL='https://quico.space/quico-os-setup/arch-zbm/raw/branch/main/setup.sh' && curl -s "${SCRIPT_URL}" | bash
```
# Steps
The scripts takes the following installation steps.
The script takes the following installation steps.
1. Install ZFS tools and kernel module with [github.com/eoli3n/archiso-zfs](https://github.com/eoli3n/archiso-zfs)
1. Create one encrypted ZFS zpool on top of `BF00` partition, password `password`
1. Create one ZFS zpool on top of zpool partition, encrypted and compressed datasets, password `password`
1. _See paragraph [Passwords](#passwords) to predefine your own passwords in a settings file_
1. _See paragraphs [Compression](#compression)/[Encryption](#encryption) to optionally disable properties_
1. Create dataset for Arch Linux and `/home`
1. Install Arch Linux into pool
1. Add ZFSBootMenu to `EF00` partition if it doesn't exist already
1. Add ZFSBootMenu to boot partition
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. 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)
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 root@<addr> -p <port>
```
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.
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.
# 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` 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:
```
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.
@@ -52,14 +355,391 @@ 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 <hostname>`
- Unprivileged user accounts: The OS was installed with `root` and unprivileged `build` users
- Passwords
- 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`.
- Arch User Repository (AUR) helper: We installed [paru](https://github.com/Morganamilo/paru) as our AUR helper, we installed from AUR as [paru-bin](https://aur.archlinux.org/packages/paru-bin).
- 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:
```
...
[Network]
DHCP=ipv4
IPForward=yes
Domains=~.
[DHCP]
UseDNS=yes
RouteMetric=10
```
A static config does away with the `[DHCP]` section:
```
...
[Network]
Address=10.10.10.2/24
Gateway=10.10.10.1
DNS=10.10.10.1
IPForward=yes
Domains=~.
```
- In case you later want a graphical interface and specifically NetworkManager (via package `networkmanager`) consider telling it to keep its hands off of some of your network interfaces. The bullet point above adds a `systemd`-style config file that `systemd-networkd.service` will read and use. Should you ever install NetworkManager it will by default assume that it must manage all interfaces. It'll use its own DHCP client to try and get IP addresses for _managed interfaces_ in which case you'll end up with whatever addressing scheme you configured in a `.network` unit file plus NetworkManager's additional address. Create `/etc/NetworkManager/conf.d/99-unmanaged-devices.conf` for example to declare some interfaces as off-limits or _unmanaged_:
```
[keyfile]
unmanaged-devices=mac:52:54:00:74:79:56;type:ethernet
```
Check out [ArchWiki article "NetworkManager" section "Ignore specific devices"](https://wiki.archlinux.org/title/NetworkManager#Ignore_specific_devices) for more info.
# Password change
After installation you're going to want to change your ZFS encryption password (unless you preconfigured a good zpool password in a settings file per [Passwords](#passwords)). At any rate you still want to be familiar with the process and its caveat in case you ever need a zpool password change or want to do one now.
## Steps
In a running OS:
1. Change password in `keylocation` file, e.g. `/etc/zfs/zpool.key` or whatever other `"${zpool_name}"'.key'` file you used during setup
1. Set this key as the new encryption key:
```
zfs change-key -l zpool
```
Quoting `man 8 zfs-change-key` from `zfs-utils` version 2.1.9 for the `-l` argument: "Ensures the key is loaded before attempting to change the key." When successful the command will not output data, it'll just silently change your encryption key.
1. Rebuild initramfs:
```
mkinitcpio -P
```
Here for example with `-P` (`--allpresets`) which processes all presets contained in `/etc/mkinitcpio.d`. This step puts the changed key file into your initramfs. During setup we've adjusted `/etc/mkinitcpio.conf` so that it contains `FILES=(/etc/zfs/zpool.key)` which causes the file to be added to initramfs as-is.
## Boot flow
With your password changed in two locations (key file and initramfs) The boot process works as follows.
At boot time ZFSBootMenu will scan all pools that it can import for a `bootfs` property. If it only finds one pool with that property the dataset given as `bootfs` will be selected for boot with a 10-second countdown allowing manual interaction. With `bootfs` set ZFSBootMenu will not actively search through datasets for valid kernel and initramfs combinations, it'll instead accept `bootfs` as the default boot entry without us entering the pool decryption passphrase.
Upon loading into a given dataset ZFSBootMenu will attempt to auto-load the matching decryption key. In our setup this will fail because we purposely stored the encryption key inside our `zpool/root/archlinux` dataset. ZFSBootMenu will prompt us to type in the decryption key.
Lastly ZFSBootMenu loads our OS' kernel and initramfs combination via `kexec`. For this step we don't need to enter the decryption key again. Our initramfs file contains the plain-text `/etc/zfs/zpool.key` file which allows it to seamlessly import the right dataset, load its key and mount it.
## Caveats in a password change
ZFS differentiates between user keys - also called wrapping keys - and the master key for any given encryption root. You never interact with the master key, you only pick your personal user key. Subsequently a user key change (in our use case we perceive this simply as a password change) has zero effect on data that's already encrypted. The operation is instant and merely reencrypts the already existing master key, the so-called _wrapped_ master key.
ZFS generates the master key exactly once when you enable encryption on a dataset - technically when it becomes an encryption root. Among other inputs it uses your user key to encrypt (to _wrap_) the master key. When you change your user key it just means that the master key stays exactly the same and only the encrypted (_wrapped_) key changes.
`man 8 zfs-change-key` from `zfs-utils` version 2.1.9 adds:
> If the user's key is compromised, `zfs change-key` does not necessarily protect existing or newly-written data from attack. Newly-written data will continue to be encrypted with the same master key as the existing data. The master key is compromised if an attacker obtains a user key and the corresponding wrapped master key. Currently, `zfs change-key` does not overwrite the previous wrapped master key on disk, so it is accessible via forensic analysis for an indeterminate length of time.
>
> In the event of a master key compromise, ideally the drives should be securely erased to remove all the old data (which is readable using the compromised master key), a new pool created, and the data copied back. This can be approximated in place by creating new datasets, copying the data (e.g. using `zfs send | zfs recv`), and then clearing the free space with `zpool trim --secure` if supported by your hardware, otherwise `zpool initialize`.
On one hand changing the ZFS encryption password is generally a good and useful thing to do. On the other hand changing your password does not currently overwrite previous wrapped master keys on disk. A sufficiently motivated party that gains access to a wrapped master key and the matching user key is able to decrypt the master key and use it to read all data encrypted with it.
By extension this means after a password change your data remains at risk until you've copied it to a new dataset and erased previously used space thereby erasing any previous wrapped master keys.
## Changing master key
In order to generate a new master key after you've changed your user key as mentioned in `man 8 zfs-change-key` from `zfs-utils` version 2.1.9 one example workflow goes like this:
1. Change user key
- Update `/etc/zfs/zpool.key`
- Update zpool with new key via `zfs change-key -l zpool`
- Generate new initramfs with `mkinitcpio -P`
1. Create a snapshot from current system dataset
```
# Assuming current system dataset is zpool/root/archlinux-sxu
# where '-sxu' is a random suffix to differentiate datasets
# and has no real meaning
zfs snapshot zpool/root/archlinux-sxu@rekey
```
1. Within same pool `send`/`receive` snapshot
```
zfs send \
--large-block \
--compressed \
'zpool/root/archlinux-sxu@rekey' | \
\
zfs receive \
-Fvu \
-o 'encryption=on' \
-o 'keyformat=passphrase' \
-o 'keylocation=file:///etc/zfs/zpool.key' \
-o 'mountpoint=/' \
-o 'canmount=noauto' \
-o 'org.zfsbootmenu:commandline=rw nowatchdog rd.vconsole.keymap=de-latin1' \
'zpool/root/archlinux-frn'
```
Explanation:
- We specifically don't `zfs send -R` (`--replicate`). While it would normally be nice to transfer all of a dataset's children at once such as all of its snapshots the `-R` argument conflicts with the `encryption` property. See [comment by Tom Caputi on GitHub openzfs/zfs issue 10507 from June 2020](https://github.com/openzfs/zfs/issues/10507#issuecomment-651162104) for details. Basically if `encryption` is set then `-R` doesn't work. We could transfer existing encryption properties with `-w`/`--raw` but we don't actually want to transfer encryption properties at all. We want them to change during transfer, see the bullet point four points down from here talking about `encryption`.
- We `zfs receive -F` destroying any target snapshots and file systems beyond the snapshot we're transferring. In this example the target `zpool/root/archlinux-frn` doesn't even exist so `-F` isn't necessary to clean anything up. It's just good practice.
- With `-v` we get verbose progress output
- Argument `-u` makes sure the dataset does not get mounted after transfer. ZFS would mount it into `/` which wouldn't be helpful since we're currently using that filesystem ourselves.
- We set encryption properties `keyformat`, `keylocation` and most importantly `encryption`. The latter will turn our transferred dataset into its own `encryptionroot` which in turn generates a new master key. The auto-generated new master key gets wrapped with our updated passphrase in `keylocation`. This basically reencrypts all data in this dataset during transfer.
- We set `mountpoint` and `canmount` as well as an `org.zfsbootmenu:commandline` as we would for any new system dataset.
1. Change zpool's `bootfs` property to new system dataset
```
zpool set bootfs=zpool/root/archlinux-frn zpool
```
1. Boot into new system dataset
1. After reboot and now that you're in the new system dataset change its `encryptionroot` by letting it inherit data from its parent:
```
zfs change-key -i -l zpool/root/archlinux-frn
```
The parent `zpool/root` is inheriting this property from `zpool` which will make sure that `zpool/root/archlinux-frn` essentially gets its key now from `zpool`. Both `zpool/root/archlinux-frn` and `zpool` use the same exact `keylocation` with identical content. This operation is instant.
## Finishing touches
### Confirm master key change
Just to confirm that the master key has changed run this command. It takes a moment to output data:
```
zfs send --raw zpool/root/archlinux-frn@rekey | zstream dump | sed -n -e '/crypt_keydata/,/end crypt/p; /END/q'
```
Repeat for source dataset `zpool/root/archlinux-sxu@rekey`. You're particularly interested in parameters `DSL_CRYPTO_MASTER_KEY_1` and the initialization vector `DSL_CRYPTO_IV`. Notice that they differ between old and new dataset confirming that your new dataset has a new master key.
### Clean-up
Clean up:
1. In newly keyed/reencrypted system dataset destroy its snapshot
```
zfs destroy zpool/root/archlinux-frn@rekey
```
1. Recursively destroy source dataset
```
zfs destroy -r zpool/root/archlinux-sxu
```
### Unmap/TRIM
Next up unmap/TRIM unallocated disk areas. If your zpool runs on an entire disk and not just on a partition, and if your disk supports TRIM you're going to want to do:
```
zpool trim --secure zpool
```
The next best alternative is to instead do:
```
zpool initialize zpool
```
View status with either one of:
```
# With TRIM status
zpool status -t zpool
# Without TRIM status
zpool status zpool
```
# ZFS setup explained
## Overview
The ZFS pool and dataset setup that makes this tick, explained in plain English.
1. Create zpool with options:
1. `-R /mnt` (aka `-o cachefile=none -o altroot=/mnt`). The pool is never cached, i.e. it's considered temporary. All pool and dataset mount paths have `/mnt` prepended. From `man zpoolprops`:
> This can be used when examining an unknown pool where the mount points cannot be trusted, or in an alternate boot environment, where the typical paths are not valid. `altroot` is not a persistent property. It is valid only while the system is up.
1. `-O canmount=off`: Note the capital `-O` which makes this a file system property, not a pool property. File system cannot be mounted, and is ignored by `zfs mount -a`. This property is not inherited.
1. `-O mountpoint=none`: What it says on the tin, the pool has no mountpoint configured.
1. `-O encryption=on`: Makes this our `encryptionroot` and passes the `encryption` setting to all child datasets. Selecting `encryption=on` when creating a dataset indicates that the default encryption suite will be selected, which is currently `aes-256-gcm`.
1. `-O keylocation=file://...`: This property is only set for encrypted datasets which are encryption roots. Controls where the user's encryption key will be loaded from by default for commands such as `zfs load-key`.
1. `-O keyformat=passphrase`: Controls what format the user's encryption key will be provided as. Passphrases must be between 8 and 512 bytes long.
1. At this time the newly created zpool is not mounted anywhere. Next we create the "root" dataset, that's an arbitary term for the parent dataset of all boot environments. Boot environments in your case may be for example different operating systems all of which live on separate datasets underneath the root.
1. `-o canmount=off`: Same as above, the root dataset can - just like the pool - not be mounted.
1. `-o mountpoint=none`: Same as above, the root dataset has - just like the pool - no mountpoint configured.
1. `zfs set org.zfsbootmenu:commandline=...`: Set a common kernel command line for all boot environments such as `"ro quiet"`.
1. Neither the root dataset nor the pool are mounted at this time. We now create one boot environment dataset where we want to install Arch Linux.
1. `-o mountpoint=/`: Our Arch Linux dataset will be mounted at `/`.
1. `-o canmount=noauto`: When set to `noauto`, a dataset can only be mounted and unmounted explicitly. The dataset is not mounted automatically when the dataset is created or imported, nor is it mounted by the `zfs mount -a` command or unmounted by the `zfs unmount -a` command.
1. We then `zpool set bootfs="zpool/root/archlinux" zpool`: ZFSBootMenu uses the `bootfs` property to identify suitable boot environments. If only one pool has it - as is the case here - it identifies the pool's preferred boot dataset that will be booted with a 10-second countdown allowing manual interaction in ZFSBootMenu.
1. We explicitly mount the boot environment. Since the entire pool is still subject to our initial `-R /mnt` during creation a `zfs mount zpool/root/archlinux` will mount the Arch Linux dataset not into `/` but instead into `/mnt`.
1. We also create a `data` dataset that - at least for now - we use to store only our `/home` data.
1. For `zpool/data`:
1. `-o mountpoint=/`: We use the `mountpoint` property here only for inheritance.
1. `-o canmount=off`: The `zpool/data` dataset itself cannot actually be mounted.
1. For a `zpool/data/home` child dataset:
1. We do not specify any properties. Since `canmount` cannot be inherited the parent's `canmount=off` does not apply, it instead defaults to `canmount=on`. The parent's `mountpoint=/` property on the other hand is inherited so for a `home` child dataset it conveniently equals `mountpoint=/home`.
1. In effect this `zpool/data/home` dataset is subject to `zfs mount -a` and will happily automount into `/home`.
1. We export the zpool once, we then reimport it by scanning only inside `/dev/disk/by-partuuid`, again setting `-R /mnt` as we did during pool creation a moment ago and we do not mount any file systems.
1. We `zfs load-key <encryptionroot>` which will load the key from `keylocation` after which the `keystatus` property for `<encryptionroot>` and all child datasets will change from `unavailable` to `available`.
1. We mount our Arch Linux boot environment dataset. It automatically gets prefixed with `-R /mnt` since that's how we imported the pool.
1. We `zfs mount -a` which automounts `zpool/data/home` into `/home`, which again gets auto-prepended by `/mnt`.
1. We lastly mount our EFI partition into `/mnt/efi`.
1. We instruct ZFS to save its pool configuration via `zpool set cachefile=/etc/zfs/zpool.cache zpool`.
The complete ZFS structure now exists and is mounted at `/mnt` ready for any `pacstrap`, [debootstrap](https://wiki.debian.org/Debootstrap), `dnf --installroot` or other bootstrapping action.
## Adding another boot environment-independent dataset
Assume that in addition to your `/home` data which lives on `zpool/data/home` you want another dataset that is exempt from Arch Linux snapshots.
Consider an example `/opt/git` directory where a bunch of Git repos are checked out on which you work. You don't want them to be snapshotted - and rolled back - when something goes sideways: they are decoupled from everything else that goes on on your machine so you can easily and safely have a static `/opt/git` directory available in all boot environments.
Move your current `/opt/git` data out of the way for a moment:
```
mv '/opt/git'{,'.bak'}
```
Create datasets
```
zfs create -o canmount=off zpool/data/opt
zfs create zpool/data/opt/git
```
Remember that the `zpool/data` dataset already exists and that it has both `mountpoint=/` and `canmount=off` set. It is not and cannot be mounted itself, it instead conveniently anchors datasets at `/`. Since the `canmount` dataset property cannot be inherited and defaults to `canmount=on` we have to manually specify `-o canmount=off`. Our new `zpool/data/opt` should not automatically mount into `/opt`.
We then create the child dataset `zpool/data/opt/git`, it defaults to `canmount=on` thus immediately shows up at `/opt/git`.
Move data back into place and clean up temp directory
```
rsync -av --remove-source-files '/opt/git'{'.bak',}'/'
find '/opt/git.bak' -type d -empty -delete
```
An example `zpool/data` dataset may now look like so:
```
# zfs list -r -oname,mountpoint,canmount,mounted zpool/data
NAME MOUNTPOINT CANMOUNT MOUNTED
zpool/data / off no
zpool/data/home /home on yes
zpool/data/opt /opt off no
zpool/data/opt/git /opt/git on yes
```
## Nested environment-independent datasets
### Caution
If you want a dedicated dataset for a directory that lives deeper in your file system tree than just `/opt/git`, for example like `/var/lib/docker` make sure to not recursively create this structure in a single `zfs create` command.
In [Adding another boot environment-independent dataset](#adding-another-boot-environment-independent-dataset) above you can safely do:
```
zfs create -o canmount=off zpool/data/opt
```
Here `zpool/data` already exists, you're only creating one child dataset `opt` and you're setting `-o canmount=off` so that it never mounts into your `/opt` directory.
Now consider the same setup for `/var/lib/docker`. If you follow the exact same approach:
```
zfs create -o canmount=off zpool/data/var/lib
```
Docker will correctly report:
```
cannot create 'zpool/data/var/lib': parent does not exist
```
You might want to just create the parent then with `-p` argument:
```
zfs create -p -o canmount=off zpool/data/var/lib
~~
```
Note, however, that `-o canmount=off` only applies to `lib` dataset and that `zpool/data/var` has just been auto-mounted into `/var`:
```
# zfs list -r -oname,mountpoint,canmount,mounted zpool/data
NAME MOUNTPOINT CANMOUNT MOUNTED
zpool/data / off no
zpool/data/home /home on yes
zpool/data/opt /opt off no
zpool/data/opt/git /opt/git on yes
zpool/data/var /var on yes <---
zpool/data/var/lib /var/lib off no
```
### Advice
Instead create nested parents in multiple steps where you set each one to `-o canmount=off`:
```
zfs create -o canmount=off zpool/data/var
zfs create -o canmount=off zpool/data/var/lib
```
Lastly create the dataset you want mounted:
```
zfs create zpool/data/var/lib/docker
```
## Mounting zpool for maintenance
In case you want to mount your zpool on an external operating system such as an Arch Linux live CD ISO image do it like so:
```
zpool import zpool -d /dev/disk/by-partuuid -R /mnt -f -N
zfs load-key -L prompt zpool
zfs mount zpool/root/archlinux
zfs mount -a
# UEFI system ...
mount /dev/sda1 /mnt/efi
# ... or legacy BIOS system
mount /dev/sda1 /mnt/boot/syslinux
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
```
Explanation:
- We always want to mount pools `by-partuuid` for consistency so we specifically only look for pools at `/dev/disk/by-partuuid`.
- We mount our zpool with `-R /mnt` (aka `-o cachefile=none -o altroot=/mnt`). The pool is never cached, i.e. it's considered temporary. All pool and dataset mount paths have `/mnt` prepended. From `man zpoolprops`:
> This can be used when examining an unknown pool where the mount points cannot be trusted, or in an alternate boot environment, where the typical paths are not valid. `altroot` is not a persistent property. It is valid only while the system is up.
- With `-f` and `-N` we force-mount our pool (`-f`) even if it previously wasn't cleanly exported; and we do not auto-mount any of its datasets (`-N`), not even the ones that have `canmount=on` set.
```
# zfs list -oname,mountpoint,canmount,mounted
NAME MOUNTPOINT CANMOUNT MOUNTED
zpool none off no
zpool/data /mnt off no
zpool/data/home /mnt/home on no <-- Not immediately mounted
zpool/root none off no
zpool/root/archlinux /mnt noauto no <-- Not immediately mounted
```
- We load the decryption key by temporarily overriding the `keylocation` property to `-L prompt`. The default value is `file:///etc/zfs/zpool.key` which in all likelihood doesn't exist in this environment.
- We mount our desired boot environment with `zfs mount zpool/root/archlinux`
```
# zfs list -oname,mountpoint,canmount,mounted
NAME MOUNTPOINT CANMOUNT MOUNTED
zpool none off no
zpool/data /mnt off no
zpool/data/home /mnt/home on no
zpool/root none off no
zpool/root/archlinux /mnt noauto yes <-- Only boot env now mounted
```
- We mount all child datasets with `zfs mount -a` making `/mnt/home` available as well as any others you may have created yourself.
```
# zfs list -oname,mountpoint,canmount,mounted
NAME MOUNTPOINT CANMOUNT MOUNTED
zpool none off no
zpool/data /mnt off no
zpool/data/home /mnt/home on yes <-- Now mounted
zpool/root none off no
zpool/root/archlinux /mnt noauto yes <-- Now mounted
```
- We lastly mount our EFI System Partition (ESP), in this example it's living at `/dev/sda1` so adjust this path accordingly.
```
# df -hTP
Filesystem Type Size Used Avail Use% Mounted on
... ... ... ... ... ... ...
zpool/root/archlinux zfs 8.6G 2.5G 6.2G 29% /mnt
zpool/data/home zfs 6.3G 161M 6.2G 3% /mnt/home
/dev/sda1 vfat 511M 31M 481M 6% /mnt/efi
```
- We're ready to `arch-chroot` into our boot environment.
# Development
@@ -80,10 +760,10 @@ Commit _types_ besides `fix` and `feat` are:
The following _scopes_ are known for this project. A Conventional Commits commit message may optionally use one of the following scopes or none:
- `iso`: Changing Arch Linux ISO CD
- `iso`: Changing Arch Linux live CD ISO image
- `zbm`: Adjusting ZFSBootMenu's behavior
- `zfs`: A change to how ZFS interacts with the system, either a pool or a dataset
- `os`: Getting an perating system set up to correctly work in a ZFS boot environment
- `os`: Getting an operating system set up to correctly work in a ZFS boot environment
- `meta`: Affects the project's repo layout, readme content, file names etc.
# Credits

1521
setup.sh

File diff suppressed because it is too large Load Diff