Jack77793's Blog

Quo Fata Vocant

03 Oct 2023

NixOS 上的磁盘加密

起因

两天前,我的笔记本又坏了,这次是磁盘掉了,修好了之后启动项十分奇怪地消失了,重装系统的时候尝试了磁盘加密——不包含启动分区——并成功了,遂有此记。

前言

本次尝试使用 dm-crypt 进行磁盘加密,使用 LUKS 模式加密磁盘并使用 LVM on LUKS 方案,具有未加密的启动分区与加密的根分区和交换区,可以正常休眠。

操作

分区

首先对磁盘进行分区,对于使用 UEFI 引导的设备,建议使用 GUID 分区表(GPT),并划分出大于 512MiB 的分区作为启动分区,接着使用剩余的部分创建第二个分区,该分区将被加密并分配给根分区与交换区。第一个分区的类型应为 EFI 系统(GUID: C12A7328-F81F-11D2-BA4B-00A0C93EC93B),第二个分区的类型应为 (Linux) LVM(GUID: E6D6D379-F507-44C2-A23C-238F2A3DF928)。

加密

在加密磁盘之前,请确认内核模块 dm_crypt 已被加载,并可以使用 cryptsetup 工具。

接着加密先前准备好的第二个分区:

1
cryptsetup luksFormat /path/to/your/second/part

根据提升输入并验证密码后,加密便完成了,若希望通过密钥文件加密磁盘,请使用命令:

1
cryptsetup luksFormat /path/to/your/second/part /path/to/your/keyfile

准备逻辑卷

加密完成后,首先解密磁盘:

1
cryptsetup open /path/to/your/encrypted/device <name>

该磁盘现在可通过 /dev/mapper/<name> 访问。随后在解密的 LUKS 容器上创建物理卷:

1
pvcreate /dev/mapper/<name>

接着创建卷组并将先前所创建的物理卷加入其中:

1
vgcreate <vgname> /dev/mapper/<name>

在卷组中创建所需的逻辑卷(本例中创建两个逻辑卷,一为交换区,一为根分区):

1
2
lvcreate -L <your_swap_size> <vgname> -n swap # create swap
lvcreate -L 100%FREE <vgname> -n root # create root

逻辑卷准备完成,此时逻辑卷可通过 /dev/<vgname>/<volumename> 访问。

格式化分区

对于启动分区,建议使用 32 位的 vfat 文件系统,至于根分区,使用任意一个你喜欢的文件系统即可,本例中使用 btrfs 作为根分区的文件系统。

1
2
3
mkfs.vfat -F 32 -n BOOT /path/to/your/boot # format boot
mkfs.swap -L SWAP /path/to/your/swap # format swap
mkfs.btrfs -L ROOT /path/to/your/root # format root

完成后,正常挂载文件系统即可。

配置 NixOS

在配置文件中添加配置:

1
2
3
4
5
boot.initrd.luks.devices."<name>" = {
    device = "/path/to/your/encrypted/device";
    preLVM = true;
    allowDiscards = true; # when using ssd, enable this
};

接着使用 nixos-install 安装系统。完成后,具有加密的根文件系统的 NixOS 即已成功安装。

其它操作系统

理论上讲,在一般的 Linux 系统上,使用上述操作完成磁盘配置以及分区后,还需配置 initramfs 与内核参数——实际上,操作中最后一步里的配置就是做了这些事——对于使用 systemd 的系统,一般需要添加内核模块 sd-encryptlvm2 和内核参数 rd.luks.name=<encrypted_device_uuid>=cryptlvm root=UUID=<decrypted_device_uuid>。因此,使用 Dracut 时,需要添加设置:

1
2
kernel_cmdline="rd.luks.name=<encrypted_device_uuid>=cryptlvm root=UUID=<decrypted_device_uuid> rd.luks.allow-discards=<encrypted_device_uuid>"
add_dracutmodules+=" sd-encrypt lvm2"

使用 mkinitcpio 时,需要在钩子中添加 sd-encryptlvm2,并在引导加载程序中设置相应的内核参数。

注意:本节内容未经本人测试,仅供参考,本人不保证其正确性与可用性,请读者根据自己的经验与其它信息自行验证

参考资料

  1. dm-crypt - Arch Linux 中文维基
  2. dm-crypt full disk encryption - Gentoo Wiki
  3. Full Disk Encryption - NixOS Wiki
  4. Installation of NixOS with encrypted root
  5. dracut - ArchWiki
  6. Dracut - Gentoo Wiki
  7. Dracut - Fedora Project Wiki
  8. mkinitcpio - Arch Linux 中文维基
Next time, we'll talk about "nothing"