Export ZFS root pool before rebooting from the auto-installer #40

Merged
beatzaplenty merged 1 commits from worktree-fix-zfs-install-export into main 2026-07-22 03:22:33 +00:00
+31 -9
View File
@@ -1,17 +1,20 @@
#!/usr/bin/env nix-shell #!/usr/bin/env nix-shell
#!nix-shell -i bash -p jq disko nixos-install-tools #!nix-shell -i bash -p jq disko nixos-install-tools zfs
# shellcheck shell=bash # shellcheck shell=bash
# The only genuinely external tools this script calls directly: `jq` # The only genuinely external tools this script calls directly: `jq`
# (parsing the `nix eval` host list) and `disko`/`nixos-install` (the # (parsing the `nix eval` host list), `disko`/`nixos-install` (the
# install itself). Everything disko shells out to internally # install itself), and `zpool` (exporting a ZFS root pool before reboot,
# (parted/sgdisk/mkfs.*/zfs/...) is self-contained -- disko's own # see the comment above that call below). Everything disko shells out to
# generated scripts hardcode absolute Nix store paths for those, they # internally (parted/sgdisk/mkfs.*/zfs/...) is self-contained -- disko's
# own generated scripts hardcode absolute Nix store paths for those, they
# don't rely on this script's PATH at all (confirmed by inspecting a # don't rely on this script's PATH at all (confirmed by inspecting a
# generated system.build.formatScript). The built installer image # generated system.build.formatScript). The built installer image
# (modules/installer/common.nix) already has all three in # (modules/installer/common.nix, plus the upstream
# environment.systemPackages, so this nix-shell wrapper is a fast no-op # installation-cd-minimal.nix it imports via iso.nix) already has all
# there; it's what makes the script also work standalone (e.g. run # four in environment.systemPackages, so this nix-shell wrapper is a
# directly from a checkout on a stock ISO), where they aren't. # fast no-op there; it's what makes the script also work standalone
# (e.g. run directly from a checkout on a stock ISO), where they aren't
# guaranteed.
set -eux set -eux
set -euo pipefail set -euo pipefail
@@ -162,5 +165,24 @@ nixos-install \
# /etc/ssh/ssh_host_ed25519_key. Nothing NixOS-managed ever cleans this # /etc/ssh/ssh_host_ed25519_key. Nothing NixOS-managed ever cleans this
# up on its own since it was written imperatively, not declaratively. # up on its own since it was written imperatively, not declaratively.
rm -rf /root/host-keys rm -rf /root/host-keys
# disko's --mode ...,mount left any ZFS root pool imported (that's what
# let nixos-install write into /mnt). If we reboot with it still
# imported, it isn't just "not exported" -- it's stamped with *this*
# live installer environment's hostid, which almost never matches the
# target's own networking.hostId (see hosts/*/host.nix; the installer
# itself sets none). modules/services/zfs/enable-service.nix and
# modules/common/configuration.nix both set boot.zfs.forceImportRoot =
# false deliberately (the safe option per that setting's own docs), so
# the freshly-installed system's first real boot sees a pool "in use by
# another system" and refuses to import it without -f -- which is what
# makes boot stall waiting on the ZFS import. Exporting here (a no-op
# if the chosen host has no ZFS root, e.g. proxmox-*/linode-*) clears
# that in-use state so the next import, from any hostid, succeeds.
if [[ -n "$(zpool list -H -o name 2>/dev/null)" ]]; then
echo "Exporting ZFS pool(s) before reboot..."
zpool export -a
fi
sleep 10 sleep 10
reboot reboot