Secure Boot • UKI • TPM2 • BTRFS/Snapper • Immutable /usr
Arch Linux Secure Immutable Workstation — Dracut Edition
A novice-safe, copy-pasteable, audit-grade build: dracut-only initramfs, signed UKIs via systemd-ukify, Secure Boot owner keys via sbctl, TPM2 PCR-bound disk unlock, and Snapper rollback.
Boot-chain integrity
Signed systemd-boot and signed UKIs reduce mutable boot surface and defend against offline tampering.
Resilience
BTRFS subvolumes + Snapper snapshots enable deterministic rollback after bad updates.
0. Reading Rules (Novice-Safe)
- Only execute commands shown in code blocks.
- DESIGN NOTE blocks are informational, non-actionable.
- VERIFY blocks are checkpoints you must pass before proceeding.
- Device assumptions (adjust only if different):
/dev/nvme0n1(system),/dev/nvme1n1(home),/dev/nvme2n1(archives/backups).
1. Security Architecture (What This Build Guarantees)
Boot-chain integrity
- UEFI Secure Boot with owner-controlled keys (sbctl).
- UKI embeds kernel + initramfs + cmdline, reducing mutable boot surface.
Disk confidentiality + anti-evil-maid
- Root LUKS2 unlock is TPM2-bound with explicit PCR policy.
- Recovery passphrase remains available.
Rollback + recoverability
- BTRFS subvolumes + Snapper snapshots enable rollback after bad updates.
Immutability
/usris treated as runtime immutable via bind+RO model.
3. BIOS / UEFI Checklist
- Boot mode: UEFI only
- CSM: Disabled
- Secure Boot: Enabled (keys enrolled later)
- TPM/fTPM: Enabled
- IOMMU: Enabled
- Above 4G Decoding: Enabled
4. Disk & Encryption Plan (3× NVMe)
nvme0n1 (System): ESP (1GiB) mounted at /boot, then LUKS2 → BTRFS (@root, @var, @snapshots).
nvme1n1 (Home): LUKS2 → BTRFS (@home).
nvme2n1 (Archives/Backups): LUKS2 → BTRFS (@archives) and LUKS2 → BTRFS (@backups).
5. Live ISO Preparation
ls /sys/firmware/efi/efivars
timedatectl set-ntp true
timedatectl status
6. Partitioning (GPT)
lsblk -o NAME,SIZE,MODEL,TYPE
Use gdisk to create:
/dev/nvme0n1: p1 = 1GiB ESP (ef00), p2 = root (8304)/dev/nvme1n1: p1 = home (8302)/dev/nvme2n1: p1 archives, p2 backups (8300)
mkfs.fat -F32 /dev/nvme0n1p1
7. LUKS2 + BTRFS Subvolumes
cryptsetup luksFormat /dev/nvme0n1p2
cryptsetup open /dev/nvme0n1p2 cryptroot
mkfs.btrfs -L arch-root /dev/mapper/cryptroot
mount /dev/mapper/cryptroot /mnt
btrfs subvolume create /mnt/@root
btrfs subvolume create /mnt/@var
btrfs subvolume create /mnt/@snapshots
umount /mnt
8. Mounting + pacstrap
mount -o noatime,compress=zstd,ssd,space_cache=v2,subvol=@root \
/dev/mapper/cryptroot /mnt
mkdir -p /mnt/{boot,var,.snapshots,home,archives,backups}
mount -o noatime,compress=zstd,ssd,space_cache=v2,subvol=@var \
/dev/mapper/cryptroot /mnt/var
mount -o noatime,compress=zstd,ssd,space_cache=v2,subvol=@snapshots \
/dev/mapper/cryptroot /mnt/.snapshots
mount /dev/nvme0n1p1 /mnt/boot
pacstrap /mnt \
base linux linux-zen linux-hardened linux-firmware \
btrfs-progs snapper sudo neovim \
systemd efibootmgr \
dracut systemd-ukify sbctl \
tpm2-tools openssl \
networkmanager
genfstab -U /mnt > /mnt/etc/fstab
arch-chroot /mnt
10. Dracut (Initramfs) Configuration
mkdir -p /etc/dracut.conf.d
cat > /etc/dracut.conf.d/10-base.conf <<'EOF'
hostonly="yes"
use_systemd="yes"
add_dracutmodules+=" crypt systemd btrfs "
EOF
11. TPM2 PCR-bound unlock (systemd-cryptenroll)
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+2+7 /dev/nvme0n1p2
systemd-cryptenroll /dev/nvme0n1p2
12. systemd-boot + UKI via systemd-ukify
bootctl install
mkdir -p /boot/EFI/Linux
ROOT_UUID="$(blkid -s UUID -o value /dev/nvme0n1p2)"
mkdir -p /etc/kernel/cmdline.d
cat > /etc/kernel/cmdline <<EOF
quiet
rd.luks.name=${ROOT_UUID}=cryptroot
root=/dev/mapper/cryptroot rootflags=subvol=@root
rd.luks.options=${ROOT_UUID}=tpm2-device=auto
EOF
pacman -S --needed amd-ucode
ukify build \
--linux /boot/vmlinuz-linux \
--initrd /boot/amd-ucode.img \
--initrd /boot/initramfs-linux.img \
--cmdline @/etc/kernel/cmdline \
--output /boot/EFI/Linux/arch-linux.efi
13. Secure Boot via sbctl
sbctl create-keys
sbctl enroll-keys -m
sbctl sign -s /boot/EFI/Linux/*.efi
sbctl verify
14. BTRFS + Snapper rollback
snapper -c root create-config /
systemctl enable --now snapper-timeline.timer snapper-cleanup.timer
snapper -c root create -d "pre-update"
pacman -Syu
snapper -c root create -d "post-update"
snapper -c root list
snapper -c root rollback <SNAPSHOT_ID>
15. Immutable /usr (Bind-RO Model)
cat > /etc/systemd/system/usr-immutable.service <<'EOF'
[Unit]
Description=Bind-mount and remount /usr read-only (runtime immutability)
DefaultDependencies=no
After=local-fs.target
Before=multi-user.target
[Service]
Type=oneshot
ExecStart=/usr/bin/mount --bind /usr /usr
ExecStart=/usr/bin/mount -o remount,bind,ro /usr
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
systemctl enable usr-immutable.service
findmnt /usr
touch /usr/IMMUTABLE_TEST 2>/dev/null || echo "OK: /usr is read-only"
16. Pacman Hooks (dracut → ukify → sbctl)
mkdir -p /etc/pacman.d/hooks
Use the hook blocks from your Markdown guide (unchanged), then validate with:
sbctl verify
ls -la /boot/EFI/Linux
17. Profile Split (Gaming vs SecOps)
- Gaming:
linux-zen+ relaxed runtime posture for usability. - SecOps:
linux-hardened+ stricter posture for security work.
18. Pre-Reboot Validation (Runbook)
set -euo pipefail
echo "== Boot mode =="
ls /sys/firmware/efi/efivars >/dev/null && echo "UEFI: OK"
echo "== ESP mounted at /boot =="
findmnt /boot
echo "== UKIs present =="
ls -la /boot/EFI/Linux
file /boot/EFI/Linux/*.efi
echo "== systemd-boot status =="
bootctl status
bootctl list
echo "== Secure Boot tooling state =="
sbctl status
sbctl verify
echo "== TPM presence =="
systemd-cryptenroll /dev/nvme0n1p2 | sed -n "1,120p"
echo "== Snapper status =="
snapper -c root list | tail -n 5
echo "== /usr immutability (expected read-only) =="
findmnt /usr
touch /usr/IMMUTABLE_TEST 2>/dev/null && { echo "FAIL: /usr writable"; exit 1; } || echo "OK: /usr RO"
19. Operational SOP (Update • Verify • Rollback)
snapper -c root create -d "pre-update"
pacman -Syu
snapper -c root create -d "post-update"
sbctl verify
If boot fails after update: unlock with passphrase (if needed) → boot → snapper rollback → reboot.
20. SOC Alignment (Telemetry, Evidence, Controls)
- Boot:
bootctl status,sbctl status,sbctl verify - Disk unlock:
systemd-cryptenroll /dev/nvme0n1p2 - Immutability:
systemctl status usr-immutable.service,findmnt /usr - Rollback readiness:
snapper -c root list - Logs:
journalctl -b -p warning..alert,journalctl -k -b
Appendix A — Threat Model
Assets: disk confidentiality, boot integrity, admin control, operational continuity.
Threats: evil maid/offline tampering, malicious boot artifact replacement, bad updates, runtime persistence, TPM drift.
Mitigations: owner-key Secure Boot + signed UKIs, TPM2 PCR policy, LUKS2, Snapper rollback, runtime /usr immutability.
Appendix B — Break-Glass Recovery
TPM unlock fails (PCR mismatch)
systemd-cryptenroll --wipe-slot=tpm2 /dev/nvme0n1p2 || true
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+2+7 /dev/nvme0n1p2
Secure Boot blocks boot (signature failure)
sbctl sign -s /boot/EFI/Linux/*.efi
sbctl verify
Appendix C — Footguns
- Enrolling Secure Boot keys before UKIs are built, signed, and verified.
- Forgetting to re-sign UKIs after kernel/initramfs/cmdline changes.
- Using global immutable attributes (e.g.,
chattr +i) that break package management. - Firmware updates changing PCR measurements (expected passphrase fallback).
- Rolling back without validating Secure Boot artifacts afterward.
Appendix D — Profile Split Reference
- Initramfs:
/boot/initramfs-*.img - UKIs:
/boot/EFI/Linux/*.efi - Cmdlines:
/etc/kernel/cmdline* - Boot entries:
/boot/loader/entries/*.conf
Appendix E — Pre-Reboot Checklist (Printable)
- [ ] ESP mounted at
/boot - [ ] UKIs present in
/boot/EFI/Linux - [ ]
sbctl verifypasses - [ ]
bootctl statushealthy - [ ] TPM2 slot present (
systemd-cryptenroll) - [ ] Snapper snapshots present
- [ ]
/usrread-only
Appendix F — SOC Alignment Checklist (Printable)
- [ ] Capture
sbctl status+sbctl verify - [ ] Capture
bootctl status - [ ] Capture
systemd-cryptenroll /dev/nvme0n1p2 - [ ] Capture
snapper -c root list - [ ] Capture
journalctl -b -p warning..alert - [ ] Capture
systemctl status usr-immutable.service