作者声明:本文仅作安装过程整理,在ThinkPad X1 Carbon 2021上安装成功。后续有空的话我可能会对本文进行更新,增加实机演示图片和各阶段的具体解释。

Archlinux安装——UEFI 全盘加密(btrfs LUKS) 安全启动(systemd-boot UKI) TPM2自动解锁

本文大量参考https://wiki.archlinuxcn.org/wiki/%E5%AE%89%E8%A3%85%E6%8C%87%E5%8D%97

1 基础环境准备

进入Arch Linux安装镜像后

1 关闭reflector.service以避免在后台自动更改镜像源干扰网络速度

1
systemctl stop reflector.service 

2 检查启动模式为EFI

1
ls /sys/firmware/efi/efivars

3 联网

1
2
3
4
5
6
iwctl #进入交互式命令行
device list #列出无线网卡设备名,如无线网卡名为wlan0
station wlan0 scan #扫描网络
station wlan0 get-networks #列出所有wifi网络
station wlan0 connect wifi-name #进行连接,注意这里无法输入中文,回车后输入密码即可
exit #连接成功后退出

若遇到网卡锁定问题

1
2
rfkill list #查看无线连接 是否被禁用(blocked: yes)
ip link set wlan0 up #如无线网卡名为wlan0

若看到类似Operation not possible due to RF-kill的报错,继续尝试rfkill unblock wifi来解锁无线网卡

如果是虚拟机没有网络连接检查虚拟机软件设置中的桥接网卡是不是与物理机联网网卡对应

使用ping www.bilibili.com测试网络连通性

4 系统时间同步

1
2
timedatectl set-ntp true #将系统时间与网络时间进行同步
timedatectl status #检查服务状态

5 配置软件源

1
vim /etc/pacman.d/mirrorlist

增加以下内容

1
Server = https://mirrors.ustc.edu.cn/archlinux/$repo/os/$arch #中国科学技术大学开源镜像站

2 存储分区与加密

1 分区

1
2
lsblk #显示当前分区情况
cfdisk #分区工具

采用GPT分区表,划分512M作为EFI系统分区,剩余空间全部分配为Linux文件系统

2 加密分区

1
2
cryptsetup luksFormat --type luks2 /dev/nvme0n1p2 #对主分区进行LUKS2标准的加密
cryptsetup open /dev/nvme0n1p2 linuxroot #解密并映射该分区为linuxroot

3 建立文件系统

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
mkfs.vfat -F32 -n EFI /dev/nvme0n1p1 #EFI分区,格式为vfat

mkfs.btrfs -f -L linuxroot /dev/mapper/linuxroot #linuxroot分区,格式为btrfs

mount /dev/mapper/linuxroot /mnt #挂载linuxroot至mnt

#合理的子卷划分隔离系统与用户数据,有利于配合未来的系统快照与回滚,仅供参考
btrfs subvolume create /mnt/@ #建立@(根目录)子卷
btrfs subvolume create /mnt/@home #建立home子卷
btrfs subvolume create /mnt/@var_cache #建立var_cache子卷
btrfs subvolume create /mnt/@var_log #建立var_log子卷
btrfs subvolume create /mnt/@root #建立root子卷
btrfs subvolume create /mnt/@swap #建立swap子卷

btrfs subvolume list /mnt #列出所有子卷,检查

umount /mnt #取消挂载

#挂载所有子卷,启用zstd:1透明压缩以优化I/O性能
mount -t btrfs -o subvol=@,compress=zstd:1 -m /dev/mapper/linuxroot /mnt
mount -t btrfs -o subvol=@home,compress=zstd:1 -m /dev/mapper/linuxroot /mnt/home
mount -t btrfs -o subvol=@var_cache,compress=zstd:1 -m /dev/mapper/linuxroot /mnt/var/cache
mount -t btrfs -o subvol=@var_log,compress=zstd:1 -m /dev/mapper/linuxroot /mnt/var/log
mount -t btrfs -o subvol=@root,compress=zstd:1 -m /dev/mapper/linuxroot /mnt/root
mount -t btrfs -o subvol=@swap,compress=zstd:1 -m /dev/mapper/linuxroot /mnt/swap

mount -m /dev/nvme0n1p1 /mnt/efi #挂载EFI分区

3 核心系统安装与基础配置

1 设置键盘映射为US

1
2
mkdir /mnt/etc
echo "KEYMAP=us" >> /mnt/etc/vconsole.conf

2 使用pacstrap安装基础系统、内核、微代码、加密与网络工具

1
pacstrap -K /mnt base base-devel linux linux-firmware intel-ucode util-linux vim cryptsetup btrfs-progs sbctl networkmanager sudo 

3 生成挂载表fstab

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

4 进入系统终端

1
2
arch-chroot /mnt #切换进入新系统环境
passwd #设置root密码

5 本地化

1
2
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime #设置时区为上海
hwclock --systohc #同步硬件时钟

编辑/etc/locale.gen,然后取消en_GB.UTF-8 UTF-8和其他需要的区域设置前的注释

执行locale-gen生成locale信息

创建locale.conf文件,并编辑设定LANG变量

1
echo "LANG=en_GB.UTF-8" > /etc/locale.conf

设置的LANG变量需与locale设置一致,否则会出现以下错误:
Cannot set LC_CTYPE to default locale: No such file or directory

6 主机名设定

1
echo "archlinux" > /etc/hostname

4 内核引导

1 Mkinitcpio Hooks配置

编辑/etc/mkinitcpio.conf

由于采用了systemd引导架构,修改为以下配置

1
HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck)

2 统一内核映像配置

1
blkid #查看UUID

配置LUKS解密与Btrfs根目录挂载参数

编辑/etc/kernel/cmdline

1
rd.luks.name=UUID=linuxroot root=/dev/mapper/linuxroot rootfstype=btrfs rootflags=subvol=/@ rw loglevel=3

3 Mkinitcpio配置

编辑/etc/mkinitcpio.d/linux.preset

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ALL_config="/etc/mkinitcpio.conf"
ALL_kver="/boot/vmlinuz-linux"

PRESETS=('default')
#PRESETS=('default' 'fallback')

#default_config="/etc/mkinitcpio.conf"
#default_image="/boot/initramfs-linux.img"
default_uki="/efi/EFI/Linux/arch-linux.efi"
default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"

#fallback_config="/etc/mkinitcpio.conf"
#fallback_image="/boot/initramfs-linux-fallback.img"
#fallback_uki="/efi/EFI/Linux/arch-linux-fallback.efi"
#fallback_options="-S autodetect"
1
mkinitcpio -P #生成映像

4 系统环境配置

1
2
3
4
5
systemctl mask systemd-networkd #屏蔽底层网络守护进程
systemctl enable NetworkManager #启用现代网络管理器
bootctl install --esp-path=/efi #安装引导加载程序
sync #将内存缓冲写入硬盘
systemctl reboot #重启系统

至此我们已经可以正常使用系统

5 安全启动

强烈建议在操作前使用efi-readvar备份现有的PK、KEK、db、dbx密钥

1 备份当前变量

1
2
3
4
efi-readvar -v PK -o old_PK.esl
efi-readvar -v KEK -o old_KEK.esl
efi-readvar -v db -o old_db.esl
efi-readvar -v dbx -o old_dbx.esl

2 生成并注册自定义安全启动密钥

1
2
3
4
5
6
7
sbctl status
sbctl create-keys #生成密钥
sbctl enroll-keys -m #注册密钥
sbctl verify
sbctl sign -s /efi/EFI/BOOT/BOOTX64.EFI
sbctl sign -s /efi/EFI/Linux/arch-linux.efi
sbctl sign -s /efi/EFI/systemd-bootx64.efi #数字签名

3 使用pacman钩子自动签署

sbctl默认带有pacman钩子,可在日后内核更新时自动进行重签名

如果通过Systemd-boot启用了systemd-boot-update.service,那么引导加载程序只会在重启后升级,导致sbctl的Pacman钩子不签署新的文件

变通的方法是直接在```/usr/lib/``中签署引导加载程序,这样bootctl install与update将会自动识别并复制.efi.signed(如果有的话)到ESP,而不是普通的.efi文件

1
sbctl sign -s -o /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi

6 TPM2.0自动解锁

为了免去每次开机手动输入冗长LUKS密码的繁琐,可将解密密钥绑定至主板的TPM2芯片

1 生成恢复密钥以防TPM模块故障

1
systemd-cryptenroll --recovery-key /dev/nvme0n1p2

2 将LUKS槽位注册到TPM2设备

1
2
3
systemd-cryptenroll --tpm2-device=auto /dev/nvme0n1p2
systemd-cryptenroll /dev/nvme0n1p2 #列出当前已注册的密钥槽位
systemd-cryptenroll /dev/sda2 --wipe-slot empty

7 进阶系统配置

1 网络配置

1
2
3
4
5
nmcli dev wifi list # 显示附近的 Wi-Fi 网络
nmcli dev wifi connect "Wi-Fi名(SSID)" password "网络密码" # 连接指定的无线网络
#如果上面报错运行以下命令
nmcli dev wifi connect "Wi-Fi名(SSID)" --ask
nmtui #图形界面

2 添加新用户

1
2
3
useradd -G wheel -m newUser #添加newUser用户
echo "newUser ALL=(ALL:ALL) ALL" >> /etc/sudoers.d/newUser #给予sudo权限
passwd newUser #修改密码

3 安装fastfetch查看系统信息

1
pacman -S fastfetch

4 配置snapper快照

需要创建一个专门的@snapshots子卷挂载至/.snapshots,以确保在回滚根目录时不会丢失快照本身

1
2
3
4
5
6
7
8
9
10
pacman -S snapper snap-pac #安装软件包
snapper -c snap create-config / #新建一个配置
btrfs subvolume delete /.snapshots #删除默认配置的快照子卷
mkdir /.snapshots #在根目录新建快照保存文件夹
mount /dev/mapper/linuxroot /mnt #把顶层子卷挂载到一个临时位置
btrfs subvolume create /mnt/@snapshots #新建快照存放子卷
umount /mnt
mount -t btrfs -o subvol=@snapshots,compress=zstd:1 -m /dev/mapper/linuxroot /.snapshots #把子卷挂载到文件夹
chown :wheel /.snapshots #权限管理
chmod 750 /.snapshots #权限管理

/etc/fstab中补充挂载条目

1
2
# <设备>  <挂载点>  <类型>  <参数>
UUID=aacd8c72-ee57-41f2-8122-e957967de330 /.snapshots btrfs rw,relatime,compress=zstd:1,ssd,space_cache=v2,subvol=/@snapshots 0 0

编辑快照配置/etc/snapper/configs/snap

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
#1.权限设置
#允许wheel组用户管理快照
ALLOW_GROUPS="wheel"

#2.自动快照开关
#开启时间线快照(每小时自动打)
TIMELINE_CREATE="yes"
#开启清理服务(必须开启,否则只增不减)
TIMELINE_CLEANUP="yes"

#3.保留策略(最关键部分)
#默认设置保留太多了,建议大幅减少
#-------------------------------------

#至少保留多久的快照不被删除(单位:秒)。1800秒=30分钟
TIMELINE_MIN_AGE="1800"

#每小时保留多少个?建议5个(覆盖过去5小时)
TIMELINE_LIMIT_HOURLY="5"

#每天保留多少个?建议7个(覆盖过去一周)
TIMELINE_LIMIT_DAILY="7"

#每周/每月/每年建议设为0,除非你有长期归档需求
#个人电脑通常不需要回滚到一年前,且占用空间巨大
TIMELINE_LIMIT_WEEKLY="0"
TIMELINE_LIMIT_MONTHLY="0"
TIMELINE_LIMIT_YEARLY="0"

#4.这里的cleanup也要开
#用于处理手动创建的快照数量限制
NUMBER_CLEANUP="yes"
NUMBER_LIMIT="50" #总共保留50个手动/pacman快照
NUMBER_LIMIT_IMPORTANT="10"
1
2
3
4
systemctl enable --now snapper-timeline.timer #启用定时快照(可选,如果你只需要 pacman 自动快照,这个可以不开)
systemctl enable --now snapper-cleanup.timer #启用自动清理服务(不开的话快照只增不减)
snapper -c snap create -d "My First Snapshot" #手动创建快照
snapper -c snap list #快照列表

5 安装ssh服务

1
sudo pacman -S openssh

6 安装桌面环境

1
sudo pacman –S plasma plasma-workspace kde-applications

7 中文输入法

1
sudo pacman –S fcitx5-im fcitx5-chinese-addons

kdewayland配置/etc/environment

1
XMODIFIERS=@im=fcitx

安装词库

1
sudo pacman –S fcitx5-pinyin-zhwiki

8 zsh配置

1
2
3
chsh -s /usr/bin/zsh #将Zsh设置为当前用户的默认Shell
zsh #启动Zsh(如果尚未启动)
sudo pacman -S zsh-autosuggestions zsh-completions zsh-history-substring-search zsh-syntax-highlighting #zsh插件

8 硬件适配(针对ThinkPad X1 Carbon)

安装sof-firmware以驱动声卡,并可通过easyeffects配合社区预设优化外放音频效果

1
2
sudo pacman –S sof-firmware
sudo pacman –S easyeffects