aboutsummaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'contrib')
-rw-r--r--contrib/initramfs/Makefile.am3
-rw-r--r--contrib/initramfs/README.initramfs.markdown12
-rw-r--r--contrib/initramfs/hooks/.gitignore1
-rw-r--r--contrib/initramfs/hooks/Makefile.am6
-rwxr-xr-xcontrib/initramfs/hooks/zfs.in1
-rw-r--r--contrib/initramfs/hooks/zfsunlock.in18
-rw-r--r--contrib/initramfs/scripts/zfs12
-rwxr-xr-xcontrib/initramfs/zfsunlock42
8 files changed, 92 insertions, 3 deletions
diff --git a/contrib/initramfs/Makefile.am b/contrib/initramfs/Makefile.am
index 7d8597312..ee17de096 100644
--- a/contrib/initramfs/Makefile.am
+++ b/contrib/initramfs/Makefile.am
@@ -1,5 +1,8 @@
initrddir = /usr/share/initramfs-tools
+dist_initrd_SCRIPTS = \
+ zfsunlock
+
SUBDIRS = conf.d conf-hooks.d hooks scripts
EXTRA_DIST = \
diff --git a/contrib/initramfs/README.initramfs.markdown b/contrib/initramfs/README.initramfs.markdown
index c8bc9f4bd..ddae71a2e 100644
--- a/contrib/initramfs/README.initramfs.markdown
+++ b/contrib/initramfs/README.initramfs.markdown
@@ -72,3 +72,15 @@ The following kernel command line arguments are supported:
* `zfsdebug=(on,yes,1)`: Show extra debugging information
* `zfsforce=(on,yes,1)`: Force import the pool
* `rollback=(on,yes,1)`: Rollback to (instead of clone) the snapshot
+
+### Unlocking a ZFS encrypted root over SSH
+
+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; 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`
diff --git a/contrib/initramfs/hooks/.gitignore b/contrib/initramfs/hooks/.gitignore
index 73304bc2c..4e1604e18 100644
--- a/contrib/initramfs/hooks/.gitignore
+++ b/contrib/initramfs/hooks/.gitignore
@@ -1 +1,2 @@
zfs
+zfsunlock
diff --git a/contrib/initramfs/hooks/Makefile.am b/contrib/initramfs/hooks/Makefile.am
index d76845494..9b20c080a 100644
--- a/contrib/initramfs/hooks/Makefile.am
+++ b/contrib/initramfs/hooks/Makefile.am
@@ -1,10 +1,12 @@
hooksdir = /usr/share/initramfs-tools/hooks
hooks_SCRIPTS = \
- zfs
+ zfs \
+ zfsunlock
EXTRA_DIST = \
- $(top_srcdir)/contrib/initramfs/hooks/zfs.in
+ $(top_srcdir)/contrib/initramfs/hooks/zfs.in \
+ $(top_srcdir)/contrib/initramfs/hooks/zfsunlock.in
$(hooks_SCRIPTS):%:%.in Makefile
-$(SED) -e 's,@sbindir\@,$(sbindir),g' \
diff --git a/contrib/initramfs/hooks/zfs.in b/contrib/initramfs/hooks/zfs.in
index 15f23c908..ff7e49f12 100755
--- a/contrib/initramfs/hooks/zfs.in
+++ b/contrib/initramfs/hooks/zfs.in
@@ -21,6 +21,7 @@ COPY_FILE_LIST="$COPY_FILE_LIST @udevruledir@/69-vdev.rules"
# These prerequisites are provided by the base system.
COPY_EXEC_LIST="$COPY_EXEC_LIST /usr/bin/dirname /bin/hostname /sbin/blkid"
COPY_EXEC_LIST="$COPY_EXEC_LIST /usr/bin/env"
+COPY_EXEC_LIST="$COPY_EXEC_LIST $(which systemd-ask-password)"
# Explicitly specify all kernel modules because automatic dependency resolution
# is unreliable on many systems.
diff --git a/contrib/initramfs/hooks/zfsunlock.in b/contrib/initramfs/hooks/zfsunlock.in
new file mode 100644
index 000000000..c8ae86363
--- /dev/null
+++ b/contrib/initramfs/hooks/zfsunlock.in
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+PREREQ="dropbear"
+
+prereqs() {
+ echo "$PREREQ"
+}
+
+case "$1" in
+ prereqs)
+ prereqs
+ exit 0
+ ;;
+esac
+
+. /usr/share/initramfs-tools/hook-functions
+
+copy_exec /usr/share/initramfs-tools/zfsunlock /usr/bin
diff --git a/contrib/initramfs/scripts/zfs b/contrib/initramfs/scripts/zfs
index dbc4e253f..a795fd39f 100644
--- a/contrib/initramfs/scripts/zfs
+++ b/contrib/initramfs/scripts/zfs
@@ -405,6 +405,8 @@ decrypt_fs()
ENCRYPTIONROOT="$(get_fs_value "${fs}" encryptionroot)"
KEYLOCATION="$(get_fs_value "${ENCRYPTIONROOT}" keylocation)"
+ echo "${ENCRYPTIONROOT}" > /run/zfs_fs_name
+
# If root dataset is encrypted...
if ! [ "${ENCRYPTIONROOT}" = "-" ]; then
KEYSTATUS="$(get_fs_value "${ENCRYPTIONROOT}" keystatus)"
@@ -418,6 +420,7 @@ decrypt_fs()
# Prompt with plymouth, if active
elif [ -e /bin/plymouth ] && /bin/plymouth --ping 2>/dev/null; then
+ echo "plymouth" > /run/zfs_console_askpwd_cmd
while [ $TRY_COUNT -gt 0 ]; do
plymouth ask-for-password --prompt "Encrypted ZFS password for ${ENCRYPTIONROOT}" | \
$ZFS load-key "${ENCRYPTIONROOT}" && break
@@ -426,6 +429,7 @@ decrypt_fs()
# Prompt with systemd, if active
elif [ -e /run/systemd/system ]; then
+ echo "systemd-ask-password" > /run/zfs_console_askpwd_cmd
while [ $TRY_COUNT -gt 0 ]; do
systemd-ask-password "Encrypted ZFS password for ${ENCRYPTIONROOT}" --no-tty | \
$ZFS load-key "${ENCRYPTIONROOT}" && break
@@ -434,7 +438,8 @@ decrypt_fs()
# Prompt with ZFS tty, otherwise
else
- # Setting "printk" temporarily to "7" will allow prompt even if kernel option "quiet"
+ # Temporarily setting "printk" to "7" allows the prompt to appear even when the "quiet" kernel option has been used
+ echo "load-key" > /run/zfs_console_askpwd_cmd
storeprintk="$(awk '{print $1}' /proc/sys/kernel/printk)"
echo 7 > /proc/sys/kernel/printk
$ZFS load-key "${ENCRYPTIONROOT}"
@@ -964,6 +969,11 @@ mountroot()
mount_fs "$fs"
done
+ touch /run/zfs_unlock_complete
+ if [ -e /run/zfs_unlock_complete_notify ]; then
+ read zfs_unlock_complete_notify < /run/zfs_unlock_complete_notify
+ fi
+
# ------------
# Debugging information
if [ -n "${ZFS_DEBUG}" ]
diff --git a/contrib/initramfs/zfsunlock b/contrib/initramfs/zfsunlock
new file mode 100755
index 000000000..1202a144d
--- /dev/null
+++ b/contrib/initramfs/zfsunlock
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+set -eu
+if [ ! -e /run/zfs_fs_name ]; then
+ echo "Wait for the root pool to be imported or press Ctrl-C to exit."
+fi
+while [ ! -e /run/zfs_fs_name ]; do
+ if [ -e /run/zfs_unlock_complete ]; then
+ exit 0
+ fi
+ sleep 0.5
+done
+echo
+echo "Unlocking encrypted ZFS filesystems..."
+echo "Enter the password or press Ctrl-C to exit."
+echo
+zfs_fs_name=""
+if [ ! -e /run/zfs_unlock_complete_notify ]; then
+ mkfifo /run/zfs_unlock_complete_notify
+fi
+while [ ! -e /run/zfs_unlock_complete ]; do
+ zfs_fs_name=$(cat /run/zfs_fs_name)
+ zfs_console_askpwd_cmd=$(cat /run/zfs_console_askpwd_cmd)
+ systemd-ask-password "Encrypted ZFS password for ${zfs_fs_name}:" | \
+ /sbin/zfs load-key "$zfs_fs_name" || true
+ if [ "$(/sbin/zfs get -H -ovalue keystatus "$zfs_fs_name" 2> /dev/null)" = "available" ]; then
+ echo "Password for $zfs_fs_name accepted."
+ zfs_console_askpwd_pid=$(ps a -o pid= -o args | grep -v grep | grep "$zfs_console_askpwd_cmd" | cut -d ' ' -f3 | sort -n | head -n1)
+ if [ -n "$zfs_console_askpwd_pid" ]; then
+ kill "$zfs_console_askpwd_pid"
+ fi
+ # Wait for another filesystem to unlock.
+ while [ "$(cat /run/zfs_fs_name)" = "$zfs_fs_name" ] && [ ! -e /run/zfs_unlock_complete ]; do
+ sleep 0.5
+ done
+ else
+ echo "Wrong password. Try again."
+ fi
+done
+echo "Unlocking complete. Resuming boot sequence..."
+echo "Please reconnect in a while."
+echo "ok" > /run/zfs_unlock_complete_notify