在 NixOS 上启用 LUKS 根分区加密的自动解锁

NixOS Wiki 上的内容已经过时。因此使用 systemd-initrd 代替传统的 initramfs,以更好地安排启动顺序。

确保您已经通过下面的命令注册 LUKS 密钥:

1
cryptsetup luksAddKey /dev/disk/by-label/nixos-cryptroot /boot/luks.key

其中,/dev/disk/by-label/nixos-cryptroot 是您的 LUKS 加密分区,/boot/luks.key 是您的密钥文件。密钥文件应该放在一个不加密的分区中,以便在启动时自动解锁。如果您的分区方案不同,请相应地进行更改。

我的分区方案为:

1
2
3
4
sda
├─sda1 btrfs nixos-boot /boot
└─sda2 crypto_LUKS nixos-cryptroot
└─nixos-rootfs btrfs nixos-rootfs /nix/store

编辑 /etc/nixos/hardware-configuration.nix 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
{ config, lib, pkgs, modulesPath, ... }:

{
# 下面的内容为 `nixos-generate-config` 生成的内容,如果不知道是什么不要改。
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];

# 这两行是从 `configuration.nix` 文件中移动过来的,我自己觉得放在这里更加合适。
# 如果你的 `configuration.nix` 文件中有这两行,请删除。
boot.loader.grub.enable = true;
boot.loader.grub.device = "/dev/disk/by-id/你的硬盘ID";

# 添加下面这一行,启用 systemd-initrd
boot.initrd.systemd.enable = true;

# 自动挂载包含 LUKS 密钥的分区,我将 LUKS 密钥放在了 `/boot` 分区中。如果你采用不同的方案,请相应地更改。
boot.initrd.systemd.mounts = [{
what = "/dev/disk/by-label/nixos-boot";
where = "/boot";
type = "btrfs";
}];

# 设置 LUKS 自动解锁,要与上面的 `boot.initrd.systemd.mounts` 中挂载的分区对应。
boot.initrd.luks.devices."nixos-rootfs" = {
device = "/dev/disk/by-label/nixos-cryptroot";
keyFile = "/boot/luks.key";
};

# 挂载解锁后的分区 (加密的 `/` 分区和不加密的 `/boot` 分区),如果您的分区方案不同,请相应地更改。
fileSystems."/" = {
device = "/dev/disk/by-label/nixos-rootfs";
fsType = "btrfs";
};

fileSystems."/boot" = {
device = "/dev/disk/by-label/nixos-boot";
fsType = "btrfs";
};

# 下面的内容是 `nixos-generate-config` 生成的内容,根据自己的需要进行修改。
swapDevices = [ ];

# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault false;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}