Archlinux安装——UEFI 全盘加密(btrfs LUKS) 安全启动(systemd-boot UKI) TPM2自动解锁 基于ThinkPad X1 Carbon Gen 9(2021)
作者声明:本文整理自在 ThinkPad X1 Carbon Gen 9(2021)上的一次完整安装与日常使用过程,带有个人取舍,不代表唯一或最佳实践。详细信息请参考https://wiki.archlinuxcn.org/
Archlinux安装——UEFI 全盘加密(btrfs LUKS) 安全启动(systemd-boot UKI) TPM2自动解锁 基于ThinkPad X1 Carbon Gen 9(2021)
0 这套架构在解决什么问题
在动手之前,有必要先理清整套配置的逻辑。全盘加密、安全启动、UKI 与 TPM2 这四样东西并不是各自独立的功能堆叠,而是环环相扣、彼此补位的:
- LUKS 全盘加密 解决的是"设备丢失或被盗"——硬盘一旦离开本机,就只是一堆无法读取的密文。代价是每次开机都要手动输入一长串解密密码。
- TPM2 自动解锁 把这把密码交给主板上的 TPM 芯片保管,开机自动放行,省去手输。但它随即带来一个新问题:如果有人物理接触机器、替换了内核或往引导链里塞了东西,TPM 是否还会乖乖交出钥匙?
- 安全启动 + UKI(Measured Boot) 正是用来堵这个洞。UKI 把内核、initramfs 与启动参数打包成单个文件,并用你自己的密钥签名;开机时 TPM 会先核对整条引导链的度量值(PCR),只要有任何一环被改动,度量值就对不上,TPM 拒绝解锁,自动回退到手动输入密码。
- 三者合起来的效果是:平时无感自动开机,引导链一旦被篡改就降级到密码保护,硬盘离机则完全无法读取。
本文环境:
- 硬件:ThinkPad X1 Carbon Gen 9(2021,i7-1185G7 Tiger Lake 4C8T + Iris Xe 核显,32G 内存,512G NVMe);无线 Intel Wi-Fi 6 AX201 + 蓝牙,Quectel EM05-CE 4G 模组,Synaptics 指纹(06cb:00fc),Syntek 摄像头,Thunderbolt 4 ×2
- 系统:Arch Linux + KDE Plasma (Wayland) + SDDM
- 存储:LUKS2 全盘加密 → btrfs(
compress=zstd:1,子卷@@home@var_cache@var_log@root@swap@snapshots)+ snapper 快照 - 内存/交换:zram(8G,zstd)
- 引导:systemd-boot + UKI(Measured Boot)+ Secure Boot(sbctl 自管密钥,保留微软厂商密钥)+ TPM2 自动解锁 LUKS
- 网络:NetworkManager(4G 走 ModemManager,默认关闭)
1 基础环境准备
这一节处理安装前的准备工作:联网、对时、配置镜像源,都是后续 pacstrap 下载软件包的前提,没有难点,但每一步都不能少。
进入 Arch Linux 安装镜像后:
1. 关闭 reflector.service,以避免它在后台自动更改镜像源、干扰网络速度
1 | systemctl stop reflector.service |
2. 检查启动模式为 EFI
1 | ls /sys/firmware/efi/efivars |
3. 联网
1 | iwctl # 进入交互式命令行 |
若遇到网卡锁定问题:
1 | rfkill list # 查看无线连接是否被禁用 (blocked: yes) |
若看到类似 Operation not possible due to RF-kill 的报错,继续尝试 rfkill unblock wifi 来解锁无线网卡。
如果是虚拟机没有网络连接,检查虚拟机软件设置中的桥接网卡是不是与物理机联网网卡对应。
使用 ping www.bilibili.com 测试网络连通性。
4. 系统时间同步
1 | timedatectl set-ntp true # 将系统时间与网络时间进行同步 |
5. 配置软件源
1 | vim /etc/pacman.d/mirrorlist |
在文件顶部增加以下内容:
1 | Server = https://mirrors.ustc.edu.cn/archlinux/$repo/os/$arch # 中国科学技术大学开源镜像站 |
2 存储分区与加密
本节完成全盘加密的底层铺设:先用 GPT 划分 EFI 与主分区,再对主分区做 LUKS2 加密,最后在解密后的设备上建立 btrfs 与子卷。后文所有的快照与回滚,都依赖这里的子卷划分。
1. 分区
1 | lsblk # 显示当前分区情况 |
采用 GPT 分区表,划分 512M 作为 EFI 系统分区,剩余空间全部分配为 Linux 文件系统。
2. 加密分区
1 | cryptsetup luksFormat --type luks2 /dev/nvme0n1p2 # 对主分区进行 LUKS2 标准的加密 |
关于 SSD TRIM(discard):如果希望 TRIM 指令能穿透 LUKS 传到 SSD(延长寿命、保持性能),需要在内核 cmdline 中加上 rd.luks.options=discard(见 4.2),并启用 fstrim.timer(见第 8 节)。不过要清楚,这会带来轻微的安全权衡——攻击者可据此推断哪些块未被使用、大致判断文件系统类型。个人笔记本通常可以接受;介意的话就别开。
3. 建立文件系统
1 | mkfs.vfat -F32 -n EFI /dev/nvme0n1p1 # EFI 分区,格式为 vfat |
3 核心系统安装与基础配置
加密与文件系统就绪后,这一节用 pacstrap 把基础系统装进去,并完成时区、locale、主机名等最基本的本地化配置。
1. 设置键盘映射为 US
1 | mkdir /mnt/etc |
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 | arch-chroot /mnt # 切换进入新系统环境 |
5. 本地化
1 | ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime # 设置时区(按需改为 Pacific/Auckland 等) |
编辑 /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 内核引导
本节的目标,是把内核、initramfs 和内核参数合并成一个统一内核映像(UKI),放进 ESP 由 systemd-boot 直接加载。之所以要合成单个文件,是因为只有这样它才能在后面被安全启动整体签名、被 TPM 整体度量——这是第 5、6 节的前提。
1. mkinitcpio Hooks 配置
编辑 /etc/mkinitcpio.conf,由于采用了 systemd 引导架构,修改为以下配置:
1 | HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck) |
说明:systemd 方案下,keyboard 负责加载键盘硬件模块(用于在解密界面输入密码),sd-vconsole 负责读取 /etc/vconsole.conf 设置控制台键位与字体。两者已经足够,不需要再叠加旧的 keymap / consolefont 钩子——那是非 systemd 方案的等价物,重复加上去只是冗余。
2. 统一内核映像(UKI)配置
1 | blkid # 查看各分区 UUID |
配置 LUKS 解密与 Btrfs 根目录挂载参数,编辑 /etc/kernel/cmdline:
1 | rd.luks.name=<LUKS分区UUID>=linuxroot root=/dev/mapper/linuxroot rootfstype=btrfs rootflags=subvol=/@ rd.luks.options=discard rw loglevel=3 |
<LUKS分区UUID> 要替换成上一步 blkid 查到的 加密分区本身(/dev/nvme0n1p2)的 UUID,注意不是 btrfs 文件系统的 UUID,也不要把字面的 UUID 直接留在里面。rd.luks.options=discard 用于打开 TRIM 穿透(安全权衡见第 2 节),不想开就删掉这一段。
3. mkinitcpio preset 配置
编辑 /etc/mkinitcpio.d/linux.preset:
1 | ALL_config="/etc/mkinitcpio.conf" |
1 | mkinitcpio -P # 生成映像 |
4. 系统环境配置
1 | systemctl mask systemd-networkd # 屏蔽底层网络守护进程 |
至此我们已经可以正常进入系统。
5 安全启动
这一节用 sbctl 生成并注册属于自己的安全启动密钥,再给引导链上的每个 .efi 文件签名。完成后,固件只会放行你亲手签过的引导程序,任何被替换或篡改的文件都无法启动。
强烈建议在操作前用 efi-readvar 备份现有的 PK、KEK、db、dbx 密钥。 efi-readvar 来自 efitools 包,没有就先 pacman -S efitools。
1. 备份当前变量
1 | efi-readvar -v PK -o old_PK.esl |
2. 生成并注册自定义安全启动密钥
1 | sbctl status |
sbctl enroll-keys 要求固件处于 Setup Mode(已清空 PK)。如果报错,先进 BIOS 把 Secure Boot 切到 Setup Mode 或清除现有密钥,再回来执行。
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 |
同样的思路也适用于 fwupd 的胶囊更新引导器:Secure Boot 开启后,fwupd 找的是签过名的 .signed 文件,自签密钥的机器需要手动签一次,否则联想固件更新会失败——具体做法见第 8 节(固件更新 fwupd)。
6 TPM2.0 自动解锁
全盘加密带来的唯一不便,就是每次开机都要手输一长串密码。这一节把解密密钥封存进主板的 TPM2 芯片,让引导链未被篡改时自动放行——平时无感开机,出了问题再回退到密码。
第一步永远是先生成恢复密钥。 TPM 与密码同时出问题时,这是唯一的保底——这一点下面会再次印证。
1. 生成恢复密钥以防 TPM 模块故障 / 策略失效
1 | systemd-cryptenroll --recovery-key /dev/nvme0n1p2 |
2. 将 LUKS 槽位注册到 TPM2 设备
1 | systemd-cryptenroll --tpm2-device=auto /dev/nvme0n1p2 |
关于 PCR 7:一个迟早会遇到的现象。 systemd-cryptenroll --tpm2-device=auto 默认把密钥绑定到 PCR 7,也就是 Secure Boot 状态。这意味着某天 fwupd 推送一次 UEFI dbx 更新(Secure Boot 吊销数据库)之后,由于 dbx 属于 PCR 7 度量内容的一部分,PCR 7 一变,TPM 就按设计拒绝放钥匙,开机重新要求输入 LUKS 密码。日志大致是:
1 | systemd-cryptsetup: TPM policy does not match current system state. |
这是防篡改机制的正常反应。用现有 LUKS 密码授权后重新绑定即可:
1 | sudo systemd-cryptenroll --wipe-slot=tpm2 --tpm2-device=auto --tpm2-pcrs=7 /dev/nvme0n1p2 |
一个实测规律值得记住:dbx 更新或 Secure Boot 密钥变动会让自动解锁失效(改了 PCR 7),而 BIOS / EC / Intel ME 固件升级不会(只改 PCR 0/2,本机实测 BIOS 1.77 升级后无需重绑)。这也正是上面第一步恢复密钥的意义所在——它是 TPM 和密码都出问题时的最后保底。
7 进阶系统配置
系统已经能正常使用,这一节补齐日常所需的配置:网络、用户、快照、桌面环境与输入法。
1. 网络配置
1 | nmcli dev wifi list # 显示附近的 Wi-Fi 网络 |
2. 添加新用户
1 | useradd -G wheel -m newUser # 添加 newUser 用户 |
3. 安装 fastfetch 查看系统信息
1 | pacman -S fastfetch |
4. 配置 snapper 快照
需要专门创建一个 @snapshots 子卷挂载至 /.snapshots,这样在回滚根目录时才不会把快照本身一起丢掉。
1 | pacman -S snapper snap-pac # 安装软件包 |
在 /etc/fstab 中补充挂载条目(UUID 换成自己的 btrfs 文件系统 UUID):
1 | # <设备> <挂载点> <类型> <参数> |
编辑快照配置 /etc/snapper/configs/snap:
1 | # 1. 权限设置:允许 wheel 组用户管理快照 |
1 | systemctl enable --now snapper-timeline.timer # 启用定时快照(只想要 pacman 自动快照可不开) |
5. 安装并加固 ssh 服务
1 | sudo pacman -S openssh |
sshd 默认是"监听 0.0.0.0:22 + 允许密码登录",在公网或多设备环境下务必先做基础加固:仅密钥登录、禁用 root、限制重试。新建一个 drop-in 配置文件:
1 | # /etc/ssh/sshd_config.d/10-hardening.conf |
改之前一定要先确认密钥能登录,顺序不能错,否则会把自己锁在门外:
- 先从客户端
ssh-copy-id部署公钥,确认服务器上~/.ssh/authorized_keys就位(目录 700 / 文件 600) - 写入上面的配置后用
sshd -t校验,报错就先别动 systemctl reload sshd(reload 不会断开当前连接)- 保持当前会话不要关,另开一个窗口用密钥登录成功,才算完成
确认无误后启用服务:
1 | sudo systemctl enable --now sshd |
6. 安装桌面环境
1 | sudo pacman -S plasma plasma-workspace kde-applications |
7. 中文输入法
1 | sudo pacman -S fcitx5-im fcitx5-chinese-addons |
KDE Wayland 下配置 /etc/environment:
1 | XMODIFIERS=@im=fcitx |
安装词库:
1 | sudo pacman -S fcitx5-pinyin-zhwiki |
8. zsh 配置
1 | chsh -s /usr/bin/zsh # 将 Zsh 设置为当前用户的默认 Shell |
插件装上只是第一步:没有
compinit、或插件加载顺序不对(autosuggestions → syntax-highlighting → history-substring-search),这些插件都等于白装。完整的.zshrc与配置思路内容较多,单独整理在了 我的 zsh 配置里。
9. 收紧 EFI 分区权限(可选)
genfstab 生成的 EFI 挂载条目默认是 fmask=0022,意味着所有用户都能读取 ESP 里的引导文件。想收紧到只有 root 可读,编辑 /etc/fstab,把 EFI 那一行的参数改成:
1 | fmask=0137,dmask=0027 |
注意:这个改动必须改 fstab 然后重启才生效。 vfat 的 fmask/dmask 是超级块级别的选项,在运行中的系统上直接 mount -o remount 或重新挂载都不会生效(旧的超级块会被各种服务的挂载命名空间占用、静默复用,新参数被忽略)。别在运行时折腾,改好 fstab 重启即可。
8 硬件适配(ThinkPad X1 Carbon Gen 9)
https://wiki.archlinux.org/title/Lenovo_ThinkPad_X1_Carbon_(Gen_9)
以上流程对大多数机器通用,这一节按"不装就用不了 → 按需 → 开箱即用"的顺序,逐项列出本机各部件实测后需要的包与配置。
可以先把硬件相关的包一次装齐,再看下面每项的说明与验证:
1 | sudo pacman -S --needed \ |
1. 声音(必需,否则完全无声)
Tiger Lake 的声卡走 Sound Open Firmware(SOF),不装就 没有任何声音输出:
1 | sudo pacman -S sof-firmware alsa-ucm-conf |
驱动是 sof-audio-pci-intel-tgl,声卡名 sof-hda-dsp,cat /proc/asound/cards 应能看到 sofhdadsp。内置的四阵列麦克风(DMIC)也归 SOF 管,装好 sof-firmware + alsa-ucm-conf 后通常即可使用;个别情况下麦克风识别不出来,是 DMIC 与 HDA codec 的加载顺序问题,可参考 Arch Wiki 的 Gen 9 页面麦克风小节处理。
外放偏闷,可选装 easyeffects 并套用预设包里的 “Laptop” 预设改善:
1 | sudo pacman -S easyeffects |
2. CPU 微码(必需)
1 | sudo pacman -S intel-ucode |
通过第 4 节 HOOKS 里的 microcode 早加载。调频驱动是 intel_pstate,HWP(硬件管理 P-states)已生效,cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver 应为 intel_pstate。dmesg 里没有 “microcode: updated early” 也属正常——说明 BIOS 自带微码已不低于包里的版本。
3. 核显 / 视频加速(必需)
1 | sudo pacman -S mesa intel-media-driver vulkan-intel |
内核驱动用默认的 i915 即可,DMC/GuC/HuC 固件随 linux-firmware 自动加载,无需折腾 xe。VA-API 走 iHD(intel-media-driver),不要装老的 libva-intel-driver(i965,那是给老核显的)。验证:vainfo | grep "Driver version" 应显示 Intel iHD。
4. Wi-Fi(AX201)+ 无线监管库(必需)
Wi-Fi 驱动 iwlwifi 与固件随 linux-firmware 自带,但 wireless-regdb 很容易漏装:
1 | sudo pacman -S linux-firmware wireless-regdb |
缺了它,dmesg 会报 cfg80211: failed to load regulatory.db,监管域退回 country 00(信道与发射功率不受正确约束)。装上重启后用 iw reg get 确认不再是 country 00。(NetworkManager 的安装与连接见第 7 节。)
5. 蓝牙(AX201)(必需)
1 | sudo pacman -S bluez bluez-utils |
固件随 linux-firmware(Intel ibt 系列)自动加载。bluez-utils 提供 bluetoothctl,也容易漏装。之后在 KDE 系统托盘的蓝牙图标里配对即可。
6. 电池充电阈值(ThinkPad 特色,延长电池寿命)
内核的 thinkpad_acpi 直接暴露 sysfs 接口,不需要 TLP 全家桶。写一个 oneshot 服务在开机时设置即可(本机用 75/80):
1 | # /etc/systemd/system/battery-charge-threshold.service |
1 | sudo systemctl enable --now battery-charge-threshold.service |
7. 电源管理
KDE 生态选 power-profiles-daemon(Plasma 电池菜单里直接集成三档调度):
1 | sudo pacman -S power-profiles-daemon |
CPU 调度走 intel_pstate 的 powersave governor + balance_performance EPP,无需额外配置。注意 TLP 与 PPD 二选一,不要同时装。
8. 固件更新:fwupd
1 | sudo pacman -S fwupd |
联想把 BIOS / EC / Intel ME / UEFI dbx 都推到了 LVFS,用 Discover 或 fwupdmgr 即可直接升级。
不过开启 Secure Boot 自签密钥的机器这里有个坑:UEFI 胶囊更新需要重启进入 fwupd 的 EFI 引导器来刷固件,而 Secure Boot 开启时 fwupd 找的是 签过名的 .signed 文件,Arch 不会替你签(密钥在你手里),于是固件更新会报错 fwupdx64.efi.signed cannot be found。手动签一次即可(-s 记入 sbctl 数据库,以后 fwupd 包升级会自动重签,一劳永逸):
1 | sudo sbctl sign -s -o /usr/lib/fwupd/efi/fwupdx64.efi.signed /usr/lib/fwupd/efi/fwupdx64.efi |
若机器没有 shim,再在 /etc/fwupd/fwupd.conf 追加:
1 | [uefi_capsule] |
之后固件即可正常升级。提醒:刷 EC 必须插着电源;过程中会自动重启多次,看到 Lenovo logo 进度条耐心等就好。
9. 指纹识别(可选)
本机的指纹模块是 Synaptics Prometheus(06cb:00fc),libfprint 原生支持:
1 | sudo pacman -S fprintd |
fprintd 是 dbus 激活的,不用 enable 服务。若想让登录、sudo、解锁屏幕也走指纹,再在 /etc/pam.d/ 的相应文件里加 pam_fprintd.so(具体见 Arch Wiki 的 fprint 词条)。验证:lsusb -d 06cb:00fc 能看到设备。若型号不同,fprintd-enroll 报错就说明你的批次暂未被 libfprint 支持。
10. WWAN 4G 模组(按需)
本机带 Quectel EM05-CE 蜂窝模组,默认保持关闭,需要插 SIM 上网时再启用:
1 | sudo pacman -S modemmanager |
EM05-CE 在 Linux 下基本开箱即用,启用 ModemManager 后用 mmcli -L 能看到模组,NetworkManager 可直接管理蜂窝连接。(注意:部分 Fibocom 模组需要额外的 FCC unlock,EM05-CE 不需要。)
11. Thunderbolt 4 / USB4(开箱即用)
thunderbolt 驱动已自动绑定,无需额外包。若想对外接 TB 设备做授权管理,可选装 bolt(用 boltctl 管理授权)。
12. 屏幕亮度 / 旋转传感器
1 | sudo pacman -S iio-sensor-proxy |
提供环境光传感器(自动亮度)与加速度计(自动旋转)支持,KDE 会自动接入。
13. 摄像头 / TrackPoint / 触控板(开箱即用)
摄像头(Syntek)走 uvcvideo,TrackPoint 与触控板由 psmouse + libinput 处理,都不用额外配置。TrackPoint 默认灵敏度若不顺手,可改 /sys/devices/platform/i8042/serio*/sensitivity(取值 0–255,60 左右是个不错的起点)。
14. zram(内存压缩交换)
1 | sudo pacman -S zram-generator |
1 | # /etc/systemd/zram-generator.conf |
配合官方推荐的内核参数:
1 | # /etc/sysctl.d/99-zram.conf |
15. SSD:TRIM 穿透 LUKS
内核 cmdline 已加 rd.luks.options=discard(见 4.2),再启用定时 TRIM:
1 | sudo systemctl enable --now fstrim.timer |
16. 散热:不要装 thermald
这台机器 不要装 thermald——散热已由三层自管,实测在跑:HWP 硬件 P-states 让 CPU 按 PL1/PL2/Tjmax 自主降频;DPTF 固件散热(proc_thermal 驱动 + ACPI INT3400 热区,Lenovo BIOS 实现了完整动态热框架);以及 ThinkPad EC 独立控制风扇曲线。thermald 只对没有 HWP、OEM 固件散热又差的老机型才有意义,本机安装后会提示无法启用服务。
17. 其他细节
- 睡眠(挂起)方式:Tiger Lake 这代普遍走 s2idle(Windows modern standby),而非传统 S3;Lenovo 官方也建议现代 Intel 平台用这种方式。
cat /sys/power/mem_sleep可看当前在用的(方括号里那个)。若挂起耗电偏高,优先升级 BIOS,它对 s0ix 残留功耗有改善。 - BIOS(firmware)阶段本机就要约 10 秒,想缩短可去 BIOS 里关掉不用的启动项。
启动耗时参考:firmware 10.3s(BIOS 层面)+ loader 2.4s + kernel 1s + initrd 3.7s + userspace 6.7s。
验证速查
装完之后,这几条命令可以快速核对各部件状态:
1 | lspci -k # 各 PCI 设备的内核驱动绑定 |
结语
这套配置乍看环节很多,但拆开来每一步都不复杂,真正的价值在于它们组合起来之后那种"平时无感、出事兜底"的安全感。安装过程难免踩坑,卡住了多查 Arch Wiki、多看日志,绝大多数问题都能定位下来。如有出入或更好的做法,欢迎在评论区指正。
最后祝各位折腾顺利。