在 LUKS 上设置 ZFS

来自 Alpine Linux

原生加密

ZFS 现在原生支持加密。与 LUKS 上的 ZFS 相比,这有许多优点,包括多磁盘、加密的 zfs send、跨 *BSD/Linux 的可移植性等。

有关使用原生加密的 Root on ZFS 指南,请参阅此处

简介

本文档描述了如何设置使用 ZFS 的 Alpine Linux,其池位于加密分区中。为了加密分区,使用了设备映射器加密 (dm-crypt) 模块和 Linux 统一密钥设置 (LUKS)。

请注意,您必须将 /boot/ 目录安装在未加密的分区上才能正确启动。

我们将使用 syslinux 引导加载程序和传统的 BIOS 引导。

要求

注意:我们不能使用来自安装 ISO 的实时环境,因为我们将安装 ZFS 内核模块,而这对于只读 /boot(由 ISO 提供)是不可能的。

硬盘设备名称

以下文档使用 /dev/sda 设备作为安装目的地。如果您的环境对硬盘使用不同的设备名称,请在示例中使用相应的设备名称。

在 LUKS 分区之上设置使用 ZFS 的 Alpine Linux

要将 Alpine Linux 安装在 LUKS 加密分区之上的 ZFS 池中,您不能使用官方安装程序。安装需要您必须在 Alpine Linux Live CD 环境中运行的几个手动步骤。

准备安装环境

在您开始在您打算从中启动的介质上安装 Alpine Linux 之前,请准备您已有的安装

  • 更新 apk 缓存
# apk update
  • 安装设置 ZFS 和 LUKS 所需的以下软件包
# apk add cryptsetup e2fsprogs syslinux zfs zfs-$(uname -r | rev | cut -d'-' -f1 | rev)
# modprobe zfs

创建分区布局

Linux 需要未加密的 /boot/ 分区才能启动。您可以为加密的 ZFS 池分配剩余空间。

  • 启动 fdisk 实用程序以设置分区
# fdisk /dev/sda
  • 创建 /boot/ 分区
  • 输入 np11100m 以创建一个新的 100 MB 主分区。
  • 设置 /boot/ 分区为活动
  • 输入 a1
  • 创建 LUKS 分区
  • 输入 np2 以开始创建下一个分区。按 Enter 选择默认起始柱面。输入分区大小。例如,512m 表示 512 MB,5g 表示 5 GB。或者,按 Enter 设置最大可用大小。
  • 要验证设置,请按 p。输出应类似于此
Device     Boot  Start      End  Sectors  Size Id Type
/dev/sda1  *      2048   206847   204800  100M 83 Linux
/dev/sda2       206848 41943039 41736192 19.9G 83 Linux
  • w 保存更改。
  • 可选地,用随机值填充 LUKS 分区
# dd if=/dev/urandom of=/dev/sda2 bs=1M
注意:根据分区的大小,此过程可能需要几分钟到数小时。

加密 ZFS 分区

  • 要加密稍后将包含 LVM PV 的分区
# cryptsetup luksFormat /dev/sda2
注意:Alpine Linux 在提示输入密码以在启动时加密分区时使用 en-us 键盘映射。如果您在临时环境中更改了键盘映射,则在此步骤中加密分区期间输入的密码可能与您在系统启动期间输入的密码不匹配。
如果您喜欢设置单独的哈希算法和哈希模式
  • 要运行基准测试
# cryptsetup benchmark
  • 要使用单独的设置加密分区,请输入,例如
# cryptsetup -v -c aes-xts-plain64 -s 256 --hash sha256 --iter-time 2000 --use-urandom luksFormat /dev/sda2

查阅 cryptsetup --help 以获取选项。

创建文件系统

  • 打开 LUKS 分区
# cryptsetup open --type luks /dev/sda2 crypt

创建 ZFS 池

# zpool create -o ashift=12 -O normalization=formD -O atime=off -m none -R /mnt -O compression=lz4 tank /dev/mapper/crypt

zpool create 选项的含义

选项 含义
zpool create 创建 zpool
-o ashift=12 4K 块
-O normalization=formD 将默认 Unicode (UTF-8) 规范化设置为 'formD'
-O atime=off 禁用对文件访问时间的更新。这减少了对磁盘的写入,但可能会导致邮件程序(如 mutt)出现问题。
-m none 无挂载点,因为我们稍后会处理它。
-R /mnt 将 altroot 设置为 /mnt。它就像池的临时挂载点。
-O compression=lz4 对池使用 lz4 压缩。通常建议使用。
tank 池名称。tank 将在本指南中通篇使用。
/dev/mapper/crypt ZFS 将使用的块设备的路径。

完成此操作后,确认池已创建

# zpool status

应返回类似以下内容

  pool: tank
 state: ONLINE
  scan: none requested
config:

	NAME         STATE     READ WRITE CKSUM
	tank         ONLINE       0     0     0
	  crypt      ONLINE       0     0     0

errors: No known data errors

创建必需的数据集

# zfs create -o mountpoint=none -o canmount=off tank/ROOT
# zfs create -o mountpoint=/ tank/ROOT/alpine

创建可选数据集(随意添加您自己的)

# zfs create -o mountpoint=/home tank/HOME
# zfs create -o mountpoint=/var/log tank/LOG

创建 /boot 文件系统

# mkfs.ext4 /dev/sda1

挂载 /boot 文件系统

  • 创建 /mnt/boot/ 目录并在该目录中挂载 /dev/sda1 分区
# mkdir /mnt/boot/
# mount -t ext4 /dev/sda1 /mnt/boot/

安装 Alpine Linux

在此步骤中,您将在 /mnt/ 目录中安装 Alpine Linux,其中包含已挂载的文件系统结构。

  • 安装 Alpine Linux
# setup-disk -m sys /mnt/
安装程序下载最新的软件包以安装基本安装。此外,安装程序还会自动在 fstab 文件中创建挂载点的条目(但我们稍后必须手动编辑它),这些挂载点当前挂载在 /mnt/ 目录中。
注意:在此步骤中,自动写入主引导记录 (MBR) 失败。稍后,您将手动将 MBR 写入磁盘。
  • 要使操作系统能够在启动时解密 LUKS 分区,请创建 /mnt/etc/crypttab 文件。在文件中输入以下行,以使用 luks 模块解密 /dev/sda2 分区,并将其映射到 lvmcrypt 名称
crypt    /dev/sda2    none    luks
  • 删除 /mnt/etc/fstab 中的 zfs 条目,因为 ZFS 会自动挂载它们。您的 fstab 应类似于此
 UUID=6b4f2c9c-0a0f-4a8c-a73b-d2b47920ad6f	/boot	ext4	rw,relatime,stripe=4,data=ordered	0 2
  • 编辑 /mnt/etc/mkinitfs/mkinitfs.conf 文件,并将 cryptsetupzfs 模块附加到 features 参数
features="ata base ide scsi usb virtio ext4 lvm cryptsetup zfs"
  • 重建初始 RAM 磁盘
# mkinitfs -c /mnt/etc/mkinitfs/mkinitfs.conf -b /mnt/ $(ls /mnt/lib/modules/)
该命令使用 mkinitfs.conf 文件中设置的设置(在 -c 参数中)来生成 RAM 磁盘。该命令在 /mnt/ 目录中执行,并且 RAM 磁盘是使用已安装内核的模块生成的。如果不使用 $(ls /mnt/lib/modules/) 选项设置内核版本,则 mkinitfs 尝试使用临时环境中安装的内核版本生成 RAM 磁盘,这可能与 setup-disk 实用程序安装的最新版本不同。
  • 编辑 /mnt/etc/update-extlinux.conf 文件,设置根 ZFS 数据集,并将以下内核选项附加到 default_kernel_opts 参数
root=tank/ROOT/alpine
default_kernel_opts="... cryptroot=/dev/sda2 cryptdm=crypt rootfstype=zfs"
cryptroot 参数设置包含根文件系统的设备的名称。cryptdm 参数设置先前在 crypttab 文件中设置的映射的名称。rootfstype 选项将根文件系统类型设置为 zfs。
  • 由于 update-extlinux 实用程序仅在 /boot/ 目录上运行,因此暂时将根更改为 /mnt/ 目录并更新引导加载程序配置
# chroot /mnt/
# update-extlinux
# exit
忽略 update-extlinux 实用程序显示的错误。
  • 将 MBR 写入 /dev/sda 设备
# dd bs=440 count=1 conv=notrunc if=/mnt/usr/share/syslinux/mbr.bin of=/dev/sda

卸载文件系统

  • 卸载 /mnt/boot/
# umount /mnt/boot/
  • 卸载所有 zfs 文件系统
# zfs unmount -a
  • 导出所有 zfs 池
# zpool export -a
  • 关闭 lvmcrypt 设备
# cryptsetup luksClose crypt
  • 重启系统
# reboot

故障排除

通用步骤

如果您的系统无法启动,您可以验证设置并修复不正确的配置

  • 加载 ZFS 内核模块
# modprobe zfs
# zpool import -R /mnt tank
# mount -t ext4 /dev/sda1 /mnt/boot
  • 验证您是否正确运行了安装 Alpine Linux部分中描述的步骤。如有必要,更新配置。
待办事项:LUKS 上的多磁盘 ZFS?