Arch Linux 配置记录:shim + systemd-boot + UKI + MOK
参考
本文使用:
- shim(AUR
shim-signed) + systemd-boot + UKI + MOK - BTRFS 子卷
@、@home、@snapshots
没有使用:sbctl、GRUB、传统 initramfs
关键流程
shim-signed 在 AUR,安装阶段必须关闭 Secure Boot。进入系统装好 AUR 包、签名、导入 MOK 后,再进固件开启。
TL;DR
- SB 关 → 安装系统 → UKI + systemd-boot → 重启进桌面
- 装 AUR 的
shim-signed→ 生成 MOK key → 签名 systemd-boot 和 UKI mokutil --import→ 重启 → MokManager 确认 → 进固件开 SB → 完成- pacman hook + mkinitcpio post hook 自动签名,此后更新无感
一、启动链
UEFI → shim (BOOTx64.EFI,微软签名)
→ systemd-boot (grubx64.efi,MOK 签名)
→ UKI (arch-linux.efi,MOK 签名)shim 默认加载同目录 grubx64.efi,所以把 systemd-boot 改名为 grubx64.efi 即可——不是 GRUB,只借了名字。
二、分区与 BTRFS
| 分区 | 类型 | 挂载点 |
|---|---|---|
/dev/sdX1 | vfat (ESP) | /efi |
/dev/sdX2 | BTRFS | / |
/dev/sdX3 | swap | — |
mkfs.btrfs -L arch /dev/sdX2
mount /dev/sdX2 /mnt
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@snapshots
umount /mnt子卷职责:
@— 根文件系统/@home— 用户数据/home,独立于系统快照@snapshots— 只读快照存放位置,挂载到/.snapshots
# 挂载
mount -o subvol=/@ /dev/sdX2 /mnt
mkdir -p /mnt/{home,.snapshots,efi,boot}
mount -o subvol=/@home /dev/sdX2 /mnt/home
mount -o subvol=/@snapshots /dev/sdX2 /mnt/.snapshots
mkfs.fat -F32 /dev/sdX1 && mount /dev/sdX1 /mnt/efi设备路径替换为你实际的。
三、安装基础系统
pacstrap -K /mnt base base-devel linux linux-firmware \
btrfs-progs intel-ucode networkmanager sudo vim zsh \
efibootmgr sbsigntools mokutil grml-zsh-config
genfstab -U /mnt >> /mnt/etc/fstabfstab 关键挂载参数:
# BTRFS
UUID=... / btrfs rw,noatime,compress=zstd:3,space_cache=v2,subvol=/@ 0 0
UUID=... /home btrfs rw,noatime,compress=zstd:3,space_cache=v2,subvol=/@home 0 0
UUID=... .snapshots btrfs rw,noatime,compress=zstd:3,space_cache=v2,subvol=/@snapshots 0 0
# ESP
UUID=... /efi vfat rw,relatime,fmask=0022,dmask=0022,errors=remount-ro 0 2挂载参数说明:
| 参数 | 作用 |
|---|---|
noatime | 禁止访问时间戳更新,减少写入 |
compress=zstd:3 | 透明压缩,zstd level 3 兼顾速度与压缩比 |
space_cache=v2 | BTRFS 第二版空间缓存 |
subvol=/@ | 指定挂载的子卷 |
四、基础配置 (chroot)
arch-chroot /mntln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && hwclock --systohc
locale-gen # 先编辑 /etc/locale.gen,取消 en_US.UTF-8 和 zh_CN.UTF-8
echo "LANG=en_US.UTF-8" > /etc/locale.conf
echo "archbox" > /etc/hostname
passwd
useradd -m -G wheel -s /bin/zsh yoimiya && passwd yoimiya
EDITOR=vim visudo # %wheel ALL=(ALL:ALL) ALL
systemctl enable NetworkManager bluetooth五、UKI + systemd-boot
5.1 内核命令行
mkdir -p /etc/cmdline.d
cat > /etc/cmdline.d/root.conf << 'EOF'
rootdelay=5 root=UUID=... rootflags=subvol=@ rw
EOFrootdelay=5:给设备就绪等待,避免移动硬盘初始化慢导致挂载失败rootflags=subvol=@:指定 BTRFS 根子卷
确认 /etc/mkinitcpio.conf:
HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block filesystems fsck)
systemdhook 用于 systemd-based initramfs;filesystems自动处理 BTRFS。
5.2 mkinitcpio preset
# /etc/mkinitcpio.d/linux.preset
ALL_kver="/boot/vmlinuz-linux"
PRESETS=('default')
default_uki="/efi/EFI/Linux/arch-linux.efi"
default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"生成 UKI:
mkinitcpio -p linux5.3 systemd-boot
bootctl install# /efi/loader/loader.conf
default @saved
timeout 3
console-mode keep
editor nodefault @saved— 记住上次启动项timeout 3— 3 秒选择超时editor no— 禁止启动时编辑内核参数(安全考量)
UKI 放在 EFI/Linux/ 下 systemd-boot 自动发现,不需要手写 entries。
exit # 退出 chroot
umount -R /mnt
reboot # SB 保持关闭,先进桌面六、进桌面后:Secure Boot 配置
此时 Secure Boot 仍然是关闭的。
6.1 装 shim-signed (AUR)
paru -S shim-signed6.2 信任链
| 组件 | ESP 路径 | 签名者 | 被谁信任 |
|---|---|---|---|
| shim | EFI/BOOT/BOOTx64.EFI | 微软 | UEFI db |
| systemd-boot | EFI/BOOT/grubx64.efi | MOK | shim |
| UKI | EFI/Linux/arch-linux.efi | MOK | shim(shim_lock) |
6.3 生成 MOK 密钥
cd ~
openssl req -newkey rsa:4096 -nodes -keyout MOK.key \
-new -x509 -sha256 -days 3650 \
-subj "/CN=my Machine Owner Key/" -out MOK.crt
openssl x509 -outform DER -in MOK.crt -out MOK.cer
sudo mkdir -p /etc/ssl/private/secure_boot
sudo cp MOK.key MOK.crt /etc/ssl/private/secure_boot/
sudo chown root:root /etc/ssl/private/secure_boot/*
sudo chmod 400 /etc/ssl/private/secure_boot/MOK.key离线备份私钥和证书。没有私钥将来无法签新内核。
6.4 摆放 shim、签名、创建启动项
# shim 替代 fallback 位置
mv /efi/EFI/BOOT/BOOTx64.EFI /efi/EFI/BOOT/grubx64.efi
cp /usr/share/shim-signed/shimx64.efi /efi/EFI/BOOT/BOOTx64.EFI
cp /usr/share/shim-signed/mmx64.efi /efi/EFI/BOOT/
KEY=/etc/ssl/private/secure_boot/MOK.key
CRT=/etc/ssl/private/secure_boot/MOK.crt
# 签名
sudo sbsign --key $KEY --cert $CRT /efi/EFI/BOOT/grubx64.efi --output /efi/EFI/BOOT/grubx64.efi
sudo sbsign --key $KEY --cert $CRT /efi/EFI/Linux/arch-linux.efi --output /efi/EFI/Linux/arch-linux.efi
# EFI 启动项
sudo efibootmgr --create --disk /dev/sdX --part 1 \
--loader '\EFI\BOOT\BOOTx64.EFI' --label 'Arch Linux (shim)' --unicode6.5 导入 MOK
cp MOK.cer /efi/
sudo mokutil --import MOK.cer # 设置临时密码
reboot重启后 MokManager 蓝屏 → Enroll MOK → 选 MOK.cer → 输入临时密码 → 确认 → 重启。
重启后 dmesg | grep -i secure 应输出 Secure boot enabled(如果固件已开启)。
如果之前关了 SB,MOK 导入成功后进固件重新开启 Secure Boot。
七、自动化签名
7.1 systemd-boot 更新时自动签名
# /etc/pacman.d/hooks/80-secureboot.hook
[Trigger]
Operation = Install
Operation = Upgrade
Type = Path
Target = usr/lib/systemd/boot/efi/systemd-boot*.efi
[Action]
Description = Signing systemd-boot for Secure Boot
When = PostTransaction
Exec = /bin/sh -c 'while read -r f; do /usr/lib/systemd/systemd-sbsign sign --private-key /etc/ssl/private/secure_boot/MOK.key --certificate /etc/ssl/private/secure_boot/MOK.crt --output "${f}.signed" "$f"; done'
Depends = sh
NeedsTargetssystemd-sbsign 生成的 .signed 被 bootctl update 自动部署。
7.2 UKI 生成时自动签名
# /etc/initcpio/post/uki-sbsign (chmod +x)
#!/usr/bin/env bash
uki="$3"
[[ -n "$uki" ]] || exit 0
key=/etc/ssl/private/secure_boot/MOK.key
cert=/etc/ssl/private/secure_boot/MOK.crt
if ! sbverify --cert "$cert" "$uki" &>/dev/null; then
sbsign "$uki" --key "$key" --cert "$cert" --output "$uki"
fi验证:
sudo mkinitcpio -p linux
sudo sbverify --list /efi/EFI/Linux/arch-linux.efi八、最终 ESP 布局
/efi
├── EFI
│ ├── BOOT
│ │ ├── BOOTx64.EFI # shim(微软签名)
│ │ ├── grubx64.efi # systemd-boot(MOK 签名)
│ │ └── mmx64.efi # MokManager
│ ├── Linux
│ │ └── arch-linux.efi # UKI(MOK 签名)
│ └── systemd
│ └── systemd-bootx64.efi
├── loader
│ ├── loader.conf
│ └── entries/ # 空,UKI 自动发现
└── MOK.cer九、验证与排错
sudo mokutil --list-enrolled
sudo sbverify --list /efi/EFI/Linux/arch-linux.efi
sudo sbverify --list /efi/EFI/BOOT/grubx64.efi
sudo efibootmgr -v
dmesg | grep -i secureprohibited by secure boot policy 常见原因:MOK 未确认导入 / 文件未签名 / 系统时间错误导致证书未生效。
十、日常维护速查
| 场景 | 操作 |
|---|---|
| 内核更新 | mkinitcpio -p linux(post hook 自动签名)→ 重启 |
| systemd 更新 | pacman hook 自动签名 → bootctl update → 重启 |
| 更换 MOK key | 新 key → 重签所有 EFI → mokutil --import → 重启确认 → mokutil --delete 旧证书 |
十一、BTRFS 快照回滚 (PoC)
# 拍快照
sudo btrfs subvolume snapshot -r / /.snapshots/pre-neovim_$(date +%Y%m%d_%H%M%S)
sudo pacman -S neovim
which nvim # installed
# 回滚(从 livecd 或另一个系统)
mount -o subvolid=5 /dev/sdX2 /mnt/btrfs
mount /dev/sdX1 /mnt/btrfs/efi
mv /mnt/btrfs/@ /mnt/btrfs/@_broken
btrfs subvolume snapshot /mnt/btrfs/.snapshots/pre-neovim_* /mnt/btrfs/@
reboot # 回到快照状态
# 清理
btrfs subvolume delete /mnt/btrfs/@_broken
btrfs subvolume delete /mnt/btrfs/.snapshots/pre-neovim_*删除子卷前注意是否有嵌套子卷。用 sudo btrfs subvolume list /mnt/btrfs 检查 top level 字段,先删除嵌套子卷再删父子卷。
十二、与 Gentoo shim + GRUB 方案对比
| Arch 方案(本文) | Gentoo 方案 | |
|---|---|---|
| 引导器 | systemd-boot | GRUB |
| 内核格式 | UKI(单文件) | vmlinuz + initramfs(分离) |
| UKI / initramfs 签名 | mkinitcpio post hook 自动 sbsign | 手动 sbsign vmlinuz |
| bootloader 签名 | pacman hook → systemd-sbsign → bootctl update | Portage SECUREBOOT_SIGN_* / 手动 |
| 模块签名 | 无需单独处理(Arch 内核包自带) | Portage MODULES_SIGN_* 自动 |
| 自动化程度 | 高(全自动钩子链) | 中(模块自动签,镜像需手动) |
| 快照 | BTRFS 子卷快照 | 无内置(需外部工具) |
十三、总结
- 全自动:内核更新 → mkinitcpio 生成 UKI → post hook 自动签名 → 重启即可。systemd-boot 更新同理,pacman hook 自动签名 + 部署
- 启动快:UKI 单文件加载,systemd-boot 原生支持,无 GRUB 解析开销
- 排查方便:信任链清晰(shim → systemd-boot → UKI),每步都能用
sbverify独立验证 - 可回滚:BTRFS 快照提供系统级回滚。更新前拍个快照,出问题
mv @ @_broken && snapshot @_good @即可 - 代价:
- 初始流程多一步:SB 关 → 桌面 → AUR shim → MOK enroll → SB 开
- 需理解 shim/MOK/UKI 三层信任关系
- BTRFS 带来额外维护心智成本
附录:完整包列表 (pacman -Qqe)
archlinuxcn-keyring
baobab
base
bluez-utils
chromium
chrony
clash-party-bin
cockpit
dconf-editor
efibootmgr
extension-manager
fastfetch
fd
firefox-i18n-zh-cn
fzf
gdm
gnome-backgrounds
gnome-characters
gnome-logs
gnome-shell-extension-appindicator
gnome-shell-extension-dash-to-dock
gnome-shell-extension-gsconnect
gnome-shell-extension-vitals
gnome-text-editor
gnome-tweaks
gradia
ibus-rime
intel-ucode
kvantum
libgda6
libva-nvidia-driver
linux
linux-firmware
linuxqq
loupe
mokutil
nano
noto-fonts-cjk
noto-fonts-emoji
nvidia-open
nvtop
pacman-contrib
papers
paru
pnpm
ptyxis
qt6ct
refine
resources
ripgrep
sbsigntools
shim-signed
showtime
sudo-rs
sushi
telegram-desktop
tree
ttf-cascadia-mono-nerd
vim
visual-studio-code-bin
zsh-autocomplete