try better unlock strategy that doesnt leave me in locked emergency shell

This commit is contained in:
RingOfStorms (Joshua Bell) 2026-01-01 14:07:10 -06:00
parent d923e49c19
commit c0f7f7428c

View file

@ -16,6 +16,8 @@ let
USB_KEY = null; USB_KEY = null;
USB_KEY_PATH = if USB_KEY == null then "" else USB_KEY;
primaryDeviceUnit = "${utils.escapeSystemdPath PRIMARY}.device"; primaryDeviceUnit = "${utils.escapeSystemdPath PRIMARY}.device";
in in
lib.mkMerge [ lib.mkMerge [
@ -99,14 +101,10 @@ lib.mkMerge [
boot.initrd.systemd.services.create-needed-for-boot-dirs = lib.mkIf ENCRYPTED { boot.initrd.systemd.services.create-needed-for-boot-dirs = lib.mkIf ENCRYPTED {
after = [ after = [
"bcachefs-reset-root.service" "bcachefs-reset-root.service"
]
++ lib.optionals (USB_KEY != null) [
"unlock-bcachefs-custom.service" "unlock-bcachefs-custom.service"
]; ];
requires = [ requires = [
"bcachefs-reset-root.service" "bcachefs-reset-root.service"
]
++ lib.optionals (USB_KEY != null) [
"unlock-bcachefs-custom.service" "unlock-bcachefs-custom.service"
]; ];
serviceConfig.KeyringMode = "shared"; serviceConfig.KeyringMode = "shared";
@ -118,15 +116,11 @@ lib.mkMerge [
after = [ after = [
"initrd-root-device.target" "initrd-root-device.target"
"cryptsetup.target" "cryptsetup.target"
]
++ lib.optionals (USB_KEY != null) [
"unlock-bcachefs-custom.service" "unlock-bcachefs-custom.service"
]; ];
requires = [ requires = [
primaryDeviceUnit primaryDeviceUnit
]
++ lib.optionals (USB_KEY != null) [
"unlock-bcachefs-custom.service" "unlock-bcachefs-custom.service"
]; ];
@ -186,14 +180,14 @@ lib.mkMerge [
"rd.emergency=reboot" "rd.emergency=reboot"
]; ];
}) })
# Bcachefs auto decryption # Bcachefs auto decryption / unlock
(lib.mkIf (ENCRYPTED && USB_KEY != null) { (lib.mkIf ENCRYPTED {
boot.supportedFilesystems = [ boot.supportedFilesystems = [
"bcachefs" "bcachefs"
]; ];
boot.initrd.systemd.services.unlock-bcachefs-custom = { boot.initrd.systemd.services.unlock-bcachefs-custom = {
description = "Custom single bcachefs unlock for all subvolumes"; description = "Custom bcachefs unlock (USB key optional, passphrase retry)";
wantedBy = [ wantedBy = [
"persist.mount" "persist.mount"
@ -218,49 +212,76 @@ lib.mkMerge [
Type = "oneshot"; Type = "oneshot";
RemainAfterExit = true; RemainAfterExit = true;
KeyringMode = lib.mkIf IMPERMANENCE "shared"; KeyringMode = lib.mkIf IMPERMANENCE "shared";
StandardInput = "tty";
StandardOutput = "tty";
StandardError = "tty";
TTYPath = "/dev/console";
TTYReset = true;
TTYVHangup = true;
TTYVTDisallocate = true;
}; };
script = '' script = ''
echo "Searching for USB Unlock Key..." unlock_with_usb_key() {
if [[ -z "${USB_KEY_PATH}" ]]; then
return 2
fi
echo "Searching for USB unlock key..."
KEY_FOUND=0 KEY_FOUND=0
# 4 second search # 4 second search
for i in {1..40}; do for i in {1..40}; do
if [ -e "${USB_KEY}" ]; then if [ -e "${USB_KEY_PATH}" ]; then
KEY_FOUND=1 KEY_FOUND=1
break break
fi fi
sleep 0.1 sleep 0.1
done done
if [ "$KEY_FOUND" -eq 1 ]; then if [ "$KEY_FOUND" -ne 1 ]; then
echo "USB Key found at ${USB_KEY}. Attempting unlock..." echo "USB key not found within timeout."
return 2
fi
echo "USB key found at ${USB_KEY_PATH}. Attempting unlock..."
mkdir -p /tmp/usb_key_mount mkdir -p /tmp/usb_key_mount
# Mount read-only # Mount read-only
if mount -t bcachefs -o ro "${USB_KEY}" /tmp/usb_key_mount; then if ! mount -t bcachefs -o ro "${USB_KEY_PATH}" /tmp/usb_key_mount; then
# Attempt unlock
${pkgs.bcachefs-tools}/bin/bcachefs unlock -f /tmp/usb_key_mount/key "${PRIMARY}"
UNLOCK_STATUS=$?
# Cleanup
umount /tmp/usb_key_mount
if [ $UNLOCK_STATUS -eq 0 ]; then
echo "Bcachefs unlock successful!"
exit 0
else
echo "Failed to unlock with USB key."
fi
else
echo "Failed to mount USB key device." echo "Failed to mount USB key device."
fi return 1
else
echo "USB Key not found within timeout."
fi fi
# 3. Fallback if ${pkgs.bcachefs-tools}/bin/bcachefs unlock -f /tmp/usb_key_mount/key "${PRIMARY}"; then
echo "Proceeding to standard mount (password prompt will appear if still locked)..." umount /tmp/usb_key_mount || true
echo "Bcachefs unlock successful (USB key)!"
return 0
fi
umount /tmp/usb_key_mount || true
echo "Failed to unlock with USB key."
return 1
}
unlock_with_passphrase_until_success() {
echo "Unlocking ${PRIMARY} (will retry on failure)..."
while true; do
if ${pkgs.bcachefs-tools}/bin/bcachefs unlock "${PRIMARY}"; then
echo "Bcachefs unlock successful (passphrase)!"
return 0
fi
echo "Unlock failed. Try again."
sleep 0.2
done
}
# 1) Optional USB key unlock attempt (if configured)
if unlock_with_usb_key; then
exit 0 exit 0
fi
# 2) If USB key not configured or failed, prompt for passphrase and retry
unlock_with_passphrase_until_success
''; '';
}; };
}) })