From cryptsetup-askpass (25.11) to systemd based system (26.05)

Hi all,

I use the setup below (with 25.11) to remotely unlock a NixOS server:

  # Bootloader.
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;
  boot.loader.grub.configurationLimit = 5;

  boot.kernelParams = [ "ip=dhcp" ];
  boot.initrd = {
    availableKernelModules = [ "igc" ];
    network = {
      enable = true;
      ssh = {
        enable = true;
        port = 22;
        authorizedKeys = [ "ssh-ed25519 xxx freek@nixos" ];
        hostKeys = [ "/etc/secrets/initrd/ssh_host_rsa_key" ];
        shell = "/bin/cryptsetup-askpass";
      };
    };
  };

I got a warning that this is all changing when trying to upgrade:

error:
       Failed assertions:
       - cryptsetup-askpass is not available in systemd stage 1. Please remove it from: boot.initrd.systemd.users.root.shell

       Use `systemctl default` instead; see the NixOS 26.05 release notes for details. If you want to continue restricting the command for SSH login, you can use `command="systemctl default"` in SSH authorized keys instead; see `sshd(8)`.
Command 'nix-build '<nixpkgs/nixos>' --attr config.system.build.toplevel --no-out-link' returned non-zero exit status 1.

Now I read the wiki at https://nixos.wiki/wiki/Remote_disk_unlocking but am unsure about what to change exactly, I’m thinking I can just add boot.initrd.systemd.users.root.shell = “/usr/bin/systemd-tty-ask-password-agent”; however that does not match with the advice in the warning to use systemctl default. I don\t really understand what goes where…

Can anyone help me change my config correctly, so that I will not be locked out?

1 Like

AFAICT the wiki is correct and the warning is not. I was able to remotely unlock a server after an upgrade to 26.05 by removing boot.initrd.network.ssh.shell and setting boot.initrd.systemd.users.root.shell as the wiki advises.

It is telling you to do boot.initrd.network.ssh.authorizedKeys = [ ''command="systemctl default" ${key}'' ];.

  1. systemctl default will run systemd-tty-ask-password-agent --watch on the terminal while it waits for the initrd to finish the stage 1 setup. Compared to just running the agent, this has the benefit of outputting information about failed units when the boot process has a problem.
  2. That’s the old, obsolete wiki. The official wiki does not make the same suggestion, though that page also could use a good amount of improvement…

The warning tells you not to do that because that’s not a good way to do that. It does work but it’s not what I would recommend. Setting the root user’s shell also affects the rescue shell, which is definitely not what you want when you’re just trying to restrict what remote logins can do. That’s why the warning tells you that you should simply… restrict what remote logins can do, which is what setting command= in your authorizedKeys does.

3 Likes

Thanks for the explanation - boot.initrd.network.ssh.authorizedKeys = [ ''command="systemctl default" ${key}'' ]; works as I expect.