OpenZFS

本文为在zfs上安装arch的根分区的教程
以及双盘双池,根和home分开,根分区的盘经常性格式化的情况下的处理思路

安装前的准备

我们有两种方式来使liveCD里加入archzfs

一. 使用archiso-zfs项目

先制作一个原iso制作的liveCD,并进入liveCD

reflector 会为你选择速度合适的镜像源,但其结果并不准确,同时会清空配置文件中的内容,对于新人来讲并不适用,我们首先对其进行禁用。

systemctl stop reflector.service

联网,用iwd连wifi,或者用有线

timedatectl set-ntp true

编辑镜像源,选择ustc等源提前

vim /etc/pacman.d/mirrorlist

更新一下所有的包

pacman -Syu

加载zfs模块(由于代理等问题,如果无法通过此脚本安装,请用方法二)

curl -s https://ghproxy.com/https://raw.githubusercontent.com/eoli3n/archiso-zfs/master/init | bash -x
modprobe zfs

二. 自己制作archiso

首先在已经开机的arch上,在/etc/pacman.conf里加入archzfs源

[archzfs]
Server = http://archzfs.com/$repo/$arch

安装archiso工具,并设置路径

sudo pacman -Sy archiso
mkdir ~/iso
cp -r /usr/share/archiso/configs/releng/* ~/iso

在archiso路径下的pacman.conf输入zfs相关配置

echo -e '
[archzfs]
Server = http://archzfs.com/$repo/$arch
SigLevel = Optional TrustAll' >> ~/iso/pacman.conf

echo -e '
linux-headers
archzfs-dkms
zfs-utils' >> ~/iso/packages.x86_64

构建iso

sudo mkarchiso -vo ~/iso/out ~/iso

通过etcher等工具把iso烧录到u盘

手动加入zfs key

如果在开始安装过程中无法通过eoli3n的zfs脚本直接安装和挂载zfs模块
或者archzfs key导入失败等
请用以下方式

首先在已经开机的arch上,在/etc/pacman.conf里加入archzfs源

[archzfs]
Server = http://archzfs.com/$repo/$arch

然后手动装archzfs key加入信任

pacman-key -r DDF7DB817396A49B2A2723F7403BD972F75D9D76
pacman-key --lsign-key DDF7DB817396A49B2A2723F7403BD972F75D9D76

硬盘分区

网上过多一块硬盘装arch在zfs的教程,本教程讲两块盘,两个池
我的目的是一块盘做一个池装根分区,另一个盘做另一个池做home目录
我的盘是一块nvme,一块sata,所以以下内容可以看出是哪块盘

parted /dev/nvme0n1
parted /dev/sda

cfdisk /dev/nvme0n1
cdfisk /dev/sda

nvme0n1p1 分区 type 选 efi
nvme0n1p2 分区 type 选 Solaris root

sda1 分区 type 选 Solaris home

创建zfs pools

把 nvme0n1p2 入加到名为 zroot 的池中

zpool create -f -o ashift=12           \
             -O acltype=posixacl       \
             -O relatime=on            \
             -O xattr=sa               \
             -O dnodesize=legacy       \
             -O normalization=formD    \
             -O mountpoint=none        \
             -O canmount=off           \
             -O devices=off            \
             -O compression=lz4        \
             -R /mnt                   \
             zroot /dev/nvme0n1p2

把 sda1 入加到名为 zhome 的池中

zpool create -f -o ashift=12           \
             -O acltype=posixacl       \
             -O relatime=on            \
             -O xattr=sa               \
             -O dnodesize=legacy       \
             -O normalization=formD    \
             -O mountpoint=none        \
             -O canmount=off           \
             -O devices=off            \
             -O compression=lz4        \
             -R /mnt                   \
             zhome /dev/sda1

创建dataset

在zroot下创建arch为arch的根目录
在zhome下创建home为home目录

zfs create -o mountpoint=/ -o canmount=noauto zroot/arch
zfs create -o mountpoint=/home zhome/home

mountpoint是挂载点,不要搞错,zroot都是-R /mnt下,但是zhome和zhome/home,要么前者-R /mnt,要么后者mountpoint=/home

然后挂载dataset和efi

zfs mount zroot/arch
zfs mount zhome/home

mkdir /mnt/efi
mount /dev/nvme0n1p1 /mnt/efi

然后检查一下我们的挂载是否正确,结果应该是
zroot/arch———/mnt
zhome/home—–/mnt/home
nvme0n1p1——/mnt/efi

df -h

对dataset做最后处理

设置bootfs

zpool set bootfs=zroot/arch zroot

设置zpool.cache

zpool set cachefile=/etc/zfs/zpool.cache zroot
zpool set cachefile=/etc/zfs/zpool.cache zhome

mkdir /mnt/etc
mkdir /mnt/etc/zfs
cp /etc/zfs/zpool.cache /mnt/etc/zfs/zpool.cache

对/mnt做一些基本处理

往/mnt里安装一些基本包

pacstrap /mnt base base-devel linux-zen linux-zen-headers linux-firmware dhcpcd iwd vim bash-completion fish networkmanager zfs-dkms

生成fstab文件

genfstab -U /mnt >> /mnt/etc/fstab

注释掉fstab中zfs的内容

vim /mnt/etc/fstab

arch-chroot

arch-chroot /mnt

设置zpool.cache

zpool set cachefile=/etc/zfs/zpool.cache zroot
zpool set cachefile=/etc/zfs/zpool.cache zhome

开启32位源[multilib],加入archzfs源

vim /etc/pacman.conf

archzfs源

[archzfs]
Server = http://archzfs.com/$repo/$arch

编辑镜像源,选择ustc等源提前

vim /etc/pacman.d/mirrorlist

时区设置

设置时区,在 /etc/localtime 下用/usr 中合适的时区创建符号连接。如下设置上海时区。

ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

随后进行硬件时间设置,将当前的正确 UTC 时间写入硬件时间。

hwclock --systohc

设置 Locale 进行本地化

vim /etc/locale.gen             #en_US.UTF-8 所在行以及 zh_CN.UTF-8 所在行的注释符号(#)
locale-gen

/etc/locale.conf 导入内容

echo 'LANG=en_US.UTF-8' > /etc/locale.conf

设置主机名

vim /etc/hostname               #加入你想为主机取的主机名

接下来在/etc/hosts设置与其匹配的条目。

vim /etc/hosts
127.0.0.1   localhost
::1         localhost
127.0.1.1   archname

编辑resolv.conf,删除已有条目,并将如下内容加入其中,并固化文件

vim /etc/resolv.conf
nameserver 8.8.8.8
nameserver 2001:4860:4860::8888
nameserver 8.8.4.4
nameserver 2001:4860:4860::8844
chattr +i /etc/resolv.conf

为 root 用户设置密码

passwd root

安装微码

pacman -S intel-ucode           #Intel
pacman -S amd-ucode             #AMD

安装引导程序

pacman -S grub efibootmgr       #grub是启动引导器,efibootmgr被 grub 脚本用来将启动项写入 NVRAM。

配置内核hook

vim /etc/mkinitcpio.conf

删掉fsck(我们不用ext3/4,所以不需要), 加入zfs

HOOKS=(base udev autodetect modconf kms keyboard keymap consolefont block filesystems zfs)
mkinitcpio -P

开启zfs服务

systemctl enable zfs.target zfs-import-cache zfs-mount zfs-import.target

修复GRUB的bug,生成引导

修复grub的bug

vim /etc/grub.d/10_linux

把以下行换成下面一行

rpool=`${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true`

改成

rpool=`zdb -l ${GRUB_DEVICE} | grep " name:" | cut -d\' -f2`

生成引导

grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=Arch
grub-mkconfig -o /boot/grub/grub.cfg

准备非 root 用户

useradd -m -G wheel -s /bin/fish testuser  #wheel附加组可sudo,以root用户执行命令 -m同时创建用户家目录

设置新用户 testuser 的密码

passwd testuser

编辑 sudoers 配置文件

EDITOR=vim visudo              #需要以 root 用户运行 visudo 命令

找到下面这样的一行,把前面的注释符号 # 去掉,:wq 保存并退出即可。

#%wheel ALL=(ALL) ALL

完成安装,重启

exit

umount /mnt/efi
zfs umount zroot/arch          # 卸载dataset
zfs umount zhome/home
zpool export zroot             # export是导出池,相当于卸载池
zpool export zhome
zfs umount -a

reboot

开启swap

先在zroot池中建立swap的dataset

我由于要编译rom,所以这里示例开16G swap

zfs create -V 16G zroot/swap

格式化swap

/dev/zvol 是指定zfs卷

mkswap -f /dev/zvol/zroot/swap

在fstab中加入swap

vim /etc/fstab

/dev/zvol/zroot/swap none swap defaults 0 0

激活swap

swapon -av

今后重装nvme后的处理

在今后如果重装了nvme,但是依然保留zhome的池和文件
那么按以下方法可以快速导入已存在的zhome池并完成重装

创建nvme的zroot池后

zpool create -f -o ashift=12           \
             -O acltype=posixacl       \
             -O relatime=on            \
             -O xattr=sa               \
             -O dnodesize=legacy       \
             -O normalization=formD    \
             -O mountpoint=none        \
             -O canmount=off           \
             -O devices=off            \
             -O compression=lz4        \
             -R /mnt                   \
             zroot /dev/nvme0n1p2

创建zroot上的dataset并挂载

zfs create -o mountpoint=/ -o canmount=noauto zroot/arch
zfs mount zroot/arch

导入上zhome

zpool import zhome -R /mnt
zfs mount zhome/home

后面就是正常的挂载efi什么的,生成fstab,等后续操作