Hi, I’m new to NixOS and I was trying to setup a full disk encryption to unlock via boot when the key is on a different partition over a USB. However I didn’t quite get how to achieve that, during the first boot up it says that can’t find the partition with the key and can’t create the mount point /usbstick.
After the partitioning is done, I have generate the configuration file.
I’m not sure everything is in place here:
{ config, lib, pkgs, ... }:
let
PRIMARYUSBID = "27XE-1D71";
in
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
# Kernel modules needed for mounting USB VFAT devices in initrd stage
boot.initrd.kernelModules = [ "usb_storage" "vfat" "nls_cp437" ];
# Mount USB key before trying to decrypt root filesystem
boot.initrd.postDeviceCommands = pkgs.lib.mkBefore ''
mkdir -m 0755 -p /usbstick
sleep 2 # To make sure the usb key has been loaded
mount -n -t vfat -o ro `findfs UUID=${PRIMARYUSBID}` /usbstick
'';
boot.initrd.luks.devices."crypted" = {
keyFile = "/usbstick/keyfile";
# I don't have LVM partitions, so I'm sure this is necessary
preLVM = false; # If this is true the decryption is attempted before the postDeviceCommands can run
};
}
<SNIP>
In another distribution I have the same setup but I’m using systemd-boot to let it know where the key is with:
Those cyrptdevice= and cryptkey= parameters are features of your initramfs on that other distro. NixOS has similar stuff but it’s different.
This seems like it would benefit quite a bit from the systemd-based initrd (note, this is a different thing than systemd-boot). The slightly odd little quirk would be getting the file system mounted, though you’ve given me an idea (more on that later).
This should actually be all you need. preLVM has no effect in systemd initrd, because systemd handles dependencies dynamically. And postDeviceCommands doesn’t exist with systemd initrd, because systemd initrd uses declarative systemd units instead of imperative shell script fragments. With this, systemd should basically figure everything out for you.
Explanation: When a key file is specified, systemd automatically creates a dependency on having all the file systems in the path to the key file being mounted. The /etc/fstab trick I did there then adds an fstab to initrd, which it normally doesn’t have (don’t worry, there’s a different fstab for your root file system that it uses), and this fstab file causes systemd to understand how to mount /usbstick during stage 1. Systemd automatically handles all the dependencies and ordering, and everything should just work. You should even be able to just plug in the USB stick whenever you want and systemd will just wait for it to appear.
Now, about that idea I said I had… It makes me want a new option, like boot.initrd.fileSystems, that generates the in-initrd /etc/fstab file like the one I just put up there. Then it could have been as simple as:
Thanks for the help!
I’m still having some issue but at least I’m able to get ahead during the first booting steps.
It seems now it’s upset about the font used (maybe) did some quick googling.
<SNIP>
[FAILED] Failed to start Virtual Console Setup.
<SNIP>
I’ll try to change to another font rather than the one used by default in the config file, if I get to succeed I’ll mark the post as solved.
Almost the whole config file.
I have removed some of the entries listed not really relevant to shorten everything, where <SNIP> is used everything is left commented.
dit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page, on
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
{ config, lib, pkgs, ... }:
let
PRIMARYUSBID = "27XE-1D71";
in
{
imports =
[ # Include the results of the hardware scan.
./hardware-configuration.nix
];
# Kernel modules needed for mounting USB VFAT devices in initrd stage
boot.initrd.kernelModules = [ "uas" "usbcore" "usb_storage" "vfat" "nls_cp437" "nls_iso8859_1" ];
boot.initrd.luks.devices.crypted.keyFile = "/usbstick/keyfile";
boot.initrd.systemd = {
enable = true;
contents."/etc/fstab".text = ''
UUID=${PRIMARYUSBID} /usbstick vfat ro
'';
};
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# networking.hostName = "nixos"; # Define your hostname.
# Pick only one of the below networking options.
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
# Set your time zone.
<SNIP>
# Configure network proxy if necessary
<SNIP>
# Select internationalisation properties.
i18n.defaultLocale = "en_US.UTF-8";
console = {
font = "Lat2-Terminus16";
# keyMap = "us";
useXkbConfig = true; # use xkb.options in tty.
};
# Enable the X11 windowing system.
# services.xserver.enable = true;
# Configure keymap in X11
# services.xserver.xkb.layout = "us";
# services.xserver.xkb.options = "eurosign:e,caps:escape";
# Enable CUPS to print documents.
# services.printing.enable = true;
# Enable sound.
<SNIP>
# Enable touchpad support (enabled default in most desktopManager).
# services.libinput.enable = true;
# Define a user account. Don't forget to set a password with ‘passwd’.
<SNIP>
# List packages installed in system profile. To search, run:
# $ nix search wget
environment.systemPackages = with pkgs; [
vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
# wget
];
<SNIP>
}