On my encrypted machines I have a keyfile sitting at /luks.key with chmod 0000. Before kexec.target I append a cpio image with they keyfile to the original initrd in memory and load that instead of the default. If I remember correctly this only works with systemd-boot, I honestly forgot why, it’s been a while. Next you need to add the keyfile (/boot/luks.key in my case) path to your boot.initrd.luks.devices.<name>.keyFile config. Remember to enable fallbackToPassword for normal boots.
{
pkgs,
...
}:
{
systemd.services."kexec-load" = {
before = [ "prepare-kexec.service" ];
wantedBy = [ "kexec.target" ];
path = with pkgs; [
cpio
zstd
kexec-tools
];
script = builtins.readFile ./load.bash;
unitConfig = {
ConditionPathExists = "/luks.key";
DefaultDependencies = false;
};
serviceConfig.Type = "oneshot";
};
}
#!/usr/bin/env bash
set -euxo pipefail
umask 0077
TMPDIR=$(mktemp --directory --tmpdir=/dev/shm initrd.XXXXXXXXX)
function cleanup() {
shred -fu "${TMPDIR}/initrd" || true
shred -fu "${TMPDIR}/boot/luks.key" || true
rm -rf "$TMPDIR"
}
trap cleanup INT TERM EXIT
cd "$TMPDIR"
# put target files in place
mkdir -v ./boot
cp -v /luks.key ./boot/
# pack and append the initrd
PROFILE="$(readlink -f /nix/var/nix/profiles/system)"
cp -v "${PROFILE}/initrd" initrd
find . -print0 | cpio --null --create --format=newc --owner=+0:+0 | zstd >> initrd
# append initrd secrets
"$PROFILE/append-initrd-secrets" initrd
exec kexec --load "${PROFILE}/kernel" --initrd="${TMPDIR}/initrd" --append="$(cat "${PROFILE}/kernel-params") init=${PROFILE}/init"
Anyway, this fits my threat model for these machines given a certain update interval and the resulting maintenance headache. I tend to gitops my private infra these days. Push to git, CI builds, machines pull and switch/kexec/reboot as needed/possible.