Most Arch install guides read like someone dumped their terminal history into a blog and called it a day. I wanted more than that.

I wanted a system that was secure, fast, and didn’t ask me for a password every time I booted. I wanted TPM2-backed full-disk encryption, a modern boot process with UKI, and a layout that respected my time. And I wanted it to be repeatable — no more tinkering for hours every six months.

I wrote a script to make that possible. It’s called archtpm-install.sh.

It works well enough to trust. It’s not perfect. But it got me over the line — and it might help you too.

⚠️ Not Production-Ready

This script is a personal experiment. It worked for me — once — and then I kept tweaking it.

It is not production-grade. It assumes a lot. It wipes your disk. It doesn’t ask for confirmation. And parts of it — especially the START_STAGE feature — are completely untested.

There is no warranty, no guarantee it won’t destroy your data, and no promise it will behave the same way twice.

If you run it, you’re taking full responsibility. Please read it line by line, understand what it does, and adapt it for your own setup.

You’ve been warned.


The Diagram

Here’s how it all ties together:

Arch Linux boot process with TPM2 and UKI

This isn’t just a boot sequence. It’s a system of trust. From power-on to decrypted root, each step confirms the last — hardware, firmware, bootloader, kernel, unlock.


Why systemd-boot Instead of GRUB?

GRUB tries to support everything. And that’s kind of the problem.

In contrast, systemd-boot is:

  • Simpler — just drops UKIs into the EFI partition and lists them
  • Faster — no grub-mkconfig, no scanning partitions or OSes
  • Predictable — it’s just a boot menu for .efi files

GRUB is powerful, but most of that power comes with complexity I don’t need. Kernel updates don’t require touching a config. Just rebuild the UKI, and you’re done.

I didn’t switch to systemd-boot because I hate GRUB. I switched because I wanted to understand my boot process — and own it.


Why Dracut over mkinitcpio?

Arch uses mkinitcpio by default — and it’s good. But dracut is what Fedora, RHEL, Gentoo, and Debian use. It’s:

  • More modular — builds your initrd from systemd-style config
  • UKI-native — supports bundling directly into unified kernel images
  • Less magic — no hooks, just config

In this setup, dracut builds a self-contained UKI file that includes:

  • The initramfs
  • The kernel
  • The kernel command line
  • An embedded splash image (optional)

You just copy that one file into /boot/efi/EFI/Linux/, and systemd-boot loads it directly.

mkinitcpio vs dracut: What’s the Difference?

Featuremkinitcpiodracut
Config StyleBash-based hookssystemd-style .conf files
UKI SupportRequires manual stepsNative UKI generation
ModularityLess modularHighly modular
Package UsageDefault in Arch LinuxDefault in Fedora, RHEL, Debian
Ease of DebugFamiliar to Arch usersMore verbose logs, dependency-based
Snapshot-awareNoPartial (via systemd integration)
Bootloader HooksManualIntegrated with systemd-boot/UKI
mkinitcpio vs dracut: What's the Difference?

TL;DR: If you’re using UKIs with systemd-boot, dracut just works — no duct tape, no guessing.


A Quick Word on TPM2

When you enrol your LUKS volume with systemd-cryptenroll --tpm2, you’re telling the system: only decrypt this if the environment matches.

That includes:

  • The kernel image
  • Secure Boot state (if enabled)
  • PCR values (measured boot)
  • The TPM’s internal secrets

This isn’t just a stored passphrase. It’s a sealed secret — bound to your system’s identity and boot sequence.

It’s secure, fast, and invisible when it works.


Is the UKI Encrypted?

No — and that’s by design.

The UKI lives on the EFI System Partition (ESP), which has to stay unencrypted so the firmware can read it and begin the boot process.

It contains:

  • A UEFI boot stub (systemd-stub)
  • The kernel
  • The initrd (built by dracut)
  • The kernel command line

You can think of it like a hotel room safe: there’s a printed label on the door that says, “Enter your PIN and turn the knob.”

That label is public. But it doesn’t help unless you know the code.

The UKI works the same way. It tells the system how to boot, but it can’t actually boot unless the TPM agrees — unless the system proves it’s genuine, untampered, and running on the right hardware.

Anyone can read the UKI. But without the right key — sealed inside the TPM — your root stays locked tight.


Why Btrfs?

I used to think Btrfs was overkill. But once you get used to it, it’s hard to go back.

Strengths

  • Subvolumes: Mount /home, /var, /opt, etc. separately — without separate partitions.
  • Snapshots: Roll back from a bad pacman -Syu in seconds.
  • Space-efficient: Snapshots are copy-on-write. Fast, cheap, reliable.
  • No fsck: It self-heals with checksums. No surprise boot-time scans.
  • Compression (if enabled): Save disk space on logs and source code.

Cons

  • Not a drop-in replacement for ext4: You need to understand subvolume layout.
  • Bootloader integration: You can’t boot from encrypted Btrfs without an initramfs.
  • Still maturing in edge cases: RAID5/6 is still experimental.
  • Debugging is more complex: Especially with layered subvolume mount points.

In this setup, Btrfs was worth it. I could snapshot before risky upgrades. Roll back if a dracut rebuild went sideways. And I never had to repartition to separate state from logs.


What the Script Does

I wrote archtpm-install.sh to automate this setup — not to hide the details, but to make the process reliable and repeatable.

Here’s what it actually does, broken into two clear stages:

Part 1: Disk Setup and Encryption

  • Wipes your disk (seriously — be careful)

  • Partitions for EFI and LUKS-encrypted Btrfs

  • Sets up TPM2-based unlocking with systemd-cryptenroll

  • Mounts a structured set of Btrfs subvolumes:

    @           → /
    @home       → /home
    @var        → /var
    @opt        → /opt
    @tmp        → /tmp
    @.snapshots → /.snapshots
    @nix        → /nix
    

Part 2: Installing Arch and Boot Configuration

  • Installs Arch with pacstrap, configures locale, users, time
  • Installs dracut and sets up a UKI build
  • Boots with systemd-boot, no GRUB

It’s minimal. It’s opinionated. But it works.


Try It (If You Dare)

Boot into an Arch ISO, then run:

curl -sL <https://gist.githubusercontent.com/oliverdaff/c3c037b0509ba9d961c8c1039a70706e/raw/archtpm-install.sh> | bash

Please: READ THE SCRIPT FIRST. Change the variables at the top. Know what it’s doing.

You don’t want to learn about cryptsetup from the other side of dd if=/dev/zero.


What Comes After

Once I had the base working, I layered on:

  • i3 — lightweight, keyboard-driven window manager
  • Nix + Home Manager — to declaratively manage system config, packages, and dotfiles
  • tmux — for persistent, multiplexed terminal workflows
  • Neovim — as my full-time editor, tuned just the way I like it

Everything’s reproducible from a single Git repo. I can reinstall Arch, decrypt the disk, and be back in my working environment in under 30 minutes — tiling windows, terminal sessions, and all.

The script gave me a clean base. This stack made it mine.

How it all fits together — boot to browser, terminal to tags — is a story for another day.


Final Words

This setup boots in seconds. It unlocks itself. It snapshots. It rolls back. And I can reinstall it in under 20 minutes.

It’s not for everyone. But if you’ve been fighting Arch installs and want a repeatable way to build a secure, modern Linux system — this might help.

I didn’t write this script to automate everything. I wrote it to restore trust — in my tools, my machine, and how I boot.