diff --git a/contrib/initramfs/README.md b/contrib/initramfs/README.md index 34e9bab3c7..68647fa9fc 100644 --- a/contrib/initramfs/README.md +++ b/contrib/initramfs/README.md @@ -78,7 +78,30 @@ To use this feature: 1. Install the `dropbear-initramfs` package. You may wish to uninstall the `cryptsetup-initramfs` package to avoid warnings. 2. Add your SSH key(s) to `/etc/dropbear-initramfs/authorized_keys`. Note - that Dropbear does not support ed25519 keys before version 2020.79; + that Dropbear does not support ed25519 keys before version 2020.79; in that case, use RSA (2048-bit or more) instead. 3. Rebuild the initramfs with your keys: `update-initramfs -u` 4. During the system boot, login via SSH and run: `zfsunlock` + +### Unlocking a ZFS encrypted root via alternate means + +If present, a shell program at `/etc/zfs/initramfs-tools-load-key` +and files matching `/etc/zfs/initramfs-tools-load-key.d/*` +will be copied to the initramfs during generation +and sourced to load the key, if required. + +The `$ENCRYPTIONROOT` to load the key for and `$KEYLOCATION` variables are set, +and all initramfs-tools functions are available; +use unquoted `$ZPOOL` and `$ZFS` to run `zpool` and `zfs`. + +A successful return (and loaded key) stops the search. +A failure return is non-fatal, +and loading keys proceeds as normal if no hook succeeds. + +A trivial example of a key-loading drop-in that uses the BLAKE2 checksum +of the file at the `keylocation` as the key follows. + +```sh +key="$(b2sum "${KEYLOCATION#file://}")" || return +printf '%s\n' "${key%% *}" | $ZFS load-key -L prompt "$ENCRYPTIONROOT" +``` diff --git a/contrib/initramfs/hooks/zfs.in b/contrib/initramfs/hooks/zfs.in index 28dd252eea..6cd7e6f1ea 100755 --- a/contrib/initramfs/hooks/zfs.in +++ b/contrib/initramfs/hooks/zfs.in @@ -41,6 +41,9 @@ copy_file cache "@sysconfdir@/zfs/zpool.cache" copy_file config "@initconfdir@/zfs" copy_file config "@sysconfdir@/zfs/zfs-functions" copy_file config "@sysconfdir@/zfs/vdev_id.conf" +for f in "@sysconfdir@/zfs/initramfs-tools-load-key" "@sysconfdir@/zfs/initramfs-tools-load-key.d/"*; do + copy_file config "$f" +done copy_file rule "@udevruledir@/60-zvol.rules" copy_file rule "@udevruledir@/69-vdev.rules" diff --git a/contrib/initramfs/scripts/zfs b/contrib/initramfs/scripts/zfs index 23aa95efc8..7f977a30f7 100644 --- a/contrib/initramfs/scripts/zfs +++ b/contrib/initramfs/scripts/zfs @@ -420,6 +420,16 @@ decrypt_fs() # Continue only if the key needs to be loaded [ "$KEYSTATUS" = "unavailable" ] || return 0 + # Try extensions first + for f in "/etc/zfs/initramfs-tools-load-key" "/etc/zfs/initramfs-tools-load-key.d/"*; do + [ -r "$f" ] || continue + (. "$f") && { + # Successful return and actually-loaded key: we're done + KEYSTATUS="$(get_fs_value "${ENCRYPTIONROOT}" keystatus)" + [ "$KEYSTATUS" = "unavailable" ] || return 0 + } + done + # Do not prompt if key is stored noninteractively, if ! [ "${KEYLOCATION}" = "prompt" ]; then $ZFS load-key "${ENCRYPTIONROOT}"