Encrypted root with single password prompt

I have a LUKS setup on my laptop. Grub runs the bootloader from GPT and then initrd asks me for the decryption password. Then Gnome loads and I need to log in.

I’d like to have a setup similar to windows and macos where the disk is encrypted and your password is used both to decrypt the disk and to log you in.

I wonder if that’s achievable? I know that the loginwindow code in OS X was loathed by their developers and they didn’t want to make any changes to it, so I assume that an early GUI with credentials capture is a somewhat hard problem.

I also wonder about how to implement the login, perhaps something akin to ssh-agent with a PAM plugin allowing a single login shortly after decryption?

I have a TPM module too, not sure if that would be useful here.

3 Likes

I enabled auto-logon in the display manager, because if someone can unlock my LUKS container there’s not much the session manager can do to prevent unauthorized access.

4 Likes

This blog post covers the current state of the art in Linux world, and why it isn’t really possible to do exactly what those OSes do: Authenticated Boot and Disk Encryption on Linux

It also features a proposal for how we can get there, and there were calls to implement it in NixOS when that post surfaced. You might want to track sign bootloader to make it compatible with UEFI secure boot? · Issue #42127 · NixOS/nixpkgs · GitHub.

@emmanuelrosa’s suggestion is the best interim, but don’t be tempted to not set a password/have no lock screen, since that makes your system susceptible to run-time attacks.

1 Like

One way of achieving that is to have the disk unencrypted (or encrypted with keys in TPM) and then encrypt the actually sensitive data (your home directory) with a separate key (your user login).

TPM decryption isn’t a think in NixOS yet AFAICT and kinda requires a verified boot to be truly effective (only really protects against a stolen disk without; a stolen machine would still expose system data).

Home directory encryption with user login is a thing systemd-homed implements but it’s also not implemented in NixOS yet: systemd-homed support · Issue #91243 · NixOS/nixpkgs · GitHub

3 Likes

:wave:t2: Came here researching this same question.

It is indeed possible to achieve a single password authentication flow and I have been doing it for years on my Gentoo system. But, I am working on migrating to NixOS and trying to figure out how to achieve this same experience right now. :sweat_smile:

The way I solved this on Gentoo is by using Dracut as my initrd system and using systemd with systemd-cryptsetup for managing LUKS partitions. It uses the systemd-ask-password under the hood for password prompting which has an option --keyname that is set to cryptsetup when it is invoked by the systemd-cryptsetup. The passphrase will be cached in the kernel keyring and accessible for 2.5 minutes, then expire. I then use pam_gdm PAM module to try and read the stored password from keyring and inject it into the PAM stack.

For this to work my user password has to be synchronized with my LUKS passphrase. I enable autologin and when the system is cold-booting, I get prompted for LUKS passphrase once and then go all the way to my desktop and even get my GNOME Keyring automatically unlocked.

This of course has a bunch of security implications, but I am comfortable with the trade-off this presents (not everyone is or should be based on their risk/threat profile).

I believe systemd is now available in stage1 in NixOS, so I hope to get something like this working on NixOS as well.

1 Like

It is, but not by default. It is as simple as enabling boot.initrd.systemd.enable then using a single systemd-cryptenroll command to enroll the root disk.

I think there are multiple ways to enable secure boot, I use GitHub - nix-community/lanzaboote: Secure Boot for NixOS [maintainers=@blitz @raitobezarius @nikstur]

2 Likes

Have you found a way to achieve this on nixos?

Here’s what I did: I put the root filesystem (actually /nix because I used impermanence, but that doesn’t matter) on one luks partition, and /home/aleksana on another luks partition.

When booting, systemd’s initrd will try to unlock the root partition. If I use systemd-cryptenroll to make TPM generate a luks key and put it into a slot of the root partition, as long as the status of the device hardware, BIOS, and secure boot state (These are called TPM pcrs, you can read systemd-cryptenroll’s manpages for more information) does not change when booting again, initrd will automatically unlock the root partition, otherwise I would need to enter the password.

Then I set the luks password of the home directory to be the same as my account password, so that pam_mount will help me unlock the partition when logging in (pam_mount also supports encryption methods such as zfs and fscrypt).

In this way, I only entered the password once during the boot process, and if the initrd asked me to enter the password, there must be something wrong. For example, if I upgrade the BIOS, or change the status of secure boot, or use another hard disk but keep the data unchanged, the key calculated by TPM will change, causing the root partition to fail to unlock. I recently discovered that changing the hard drive from one m2 slot to another also causes the keys calculated by the TPM to change.

Unfortunately, home-manager will have problems with pam_mount, because home-manager wants the user’s directory to appear as soon as possible. I use a hack that converts the activation script from a systemd service to a systemd-user service so that it runs after login.

This is the idea of ​​my current setup. If you need more details, I can expand on that.

1 Like

I can share how I did this:

{ inputs, lib, pkgs, ... }:

{
  # Read their document https://github.com/nix-community/lanzaboote
  imports = [ inputs.lanzaboote.nixosModules.lanzaboote ];
  boot = {
    loader.systemd-boot = {
      enable = lib.mkForce false; # required by lanzaboote
      editor = false; # not secure
    };
    lanzaboote = {
      enable = true;
      pkiBundle = "/nix/persist/etc/secureboot";
    };
    # systemd initrd
    initrd.systemd.enable = true;
  };
  environment.systemPackages = [ pkgs.sbctl ]; # manage your secure boot keys
  users.users.aleksana = {
    pamMount = {
      path = "/dev/disk/by-partuuid/<the-part-uuid-to-your-home-partition>";
      fstype = "crypt";
      options = "compress=lzo,nofail";
    };
  };
  # To set up encrypted swap
  swapDevices = [
    {
      device = "/dev/disk/by-partuuid/<some-part-uuids>";
      randomEncryption = {
        enable = true;
        allowDiscards = true;
      };
    }
  ];
}

The configuration of your luks partition will be generated by nixos-generate-config when installing NixOS.

This is the home-manager hack that works with pam_mount: Activation as user service · Issue #3415 · nix-community/home-manager · GitHub

1 Like