Docs → Fresh root-on-ZFS install
Fresh install: encrypted root-on-ZFS Omarchy
For a machine whose disk you are willing to erase. You get Omarchy Quattro on a natively-encrypted ZFS pool, booted by ZFSBootMenu, with one passphrase prompt and boot environments you can roll back to.
Steps
The 2026.08.20.1 image was taken through this exact sequence before publishing. Fresh disk, fresh UEFI variables, no manual repair. Ending at a logged-in desktop. That is the bar for a release, rather than "it worked once on the author's machine". It is still young software that repartitions disks. Do not point it at a machine holding the only copy of anything.
1. Download and verify the ISO
curl -LO https://dl.omarchy-zfs.com/omarchy-zfs-2026.08.20.1-x86_64-quattro.iso
curl -LO https://dl.omarchy-zfs.com/omarchy-zfs-2026.08.20.1-x86_64-quattro.iso.sha256
sha256sum -c omarchy-zfs-2026.08.20.1-x86_64-quattro.iso.sha256
You want OK. About 6.2 GB. It carries a full offline package
mirror so the install never touches the network.
Prefer to build it yourself? iso/build.sh in the repo
clones the official Omarchy ISO at a pinned commit and applies a small overlay. No fork. It needs Docker and about 15 GB.
2. Write it to a USB stick
# Find the stick. Get this wrong and you erase the wrong disk.
lsblk -o NAME,SIZE,MODEL,TRAN
sudo dd if=omarchy-zfs-2026.08.20.1-x86_64-quattro.iso of=/dev/sdX bs=4M \
status=progress oflag=sync
dd will happily overwrite your system disk. /dev/sdX
is the whole stick, not a partition (/dev/sdb, not
/dev/sdb1).
3. Boot it, and catch the 15-second question
Boot the stick in UEFI mode with Secure Boot off. The live environment comes up and asks:
Install with root-on-ZFS + ZFSBootMenu (experimental)?
Yes [No]
←→ toggle · enter submit · y Yes · n No
Press y. If you miss it, the stock Omarchy installer takes over and you get a normal btrfs install. Which is a perfectly good outcome, just not this one. Reboot the stick to try again.
4. Answer the installer
Questions come in this order. Defaults are in brackets.
| Question | What to pick |
|---|---|
| Pool mode | Create a new pool. (The other option adopts a pool you already made. Useful for recovery, see route 2.) |
| Pool topology | single, mirror,
raidz1, raidz2, raidz3. One disk
means single. A mirror needs two disks of similar size and
survives one failing. |
| Disk | The disk that gets both the EFI partition and the pool. Everything on it is destroyed. |
| Wipe confirmation | It lists the exact devices. Read the list. |
| Pool passphrase (twice, ≥8 chars) | This is the encryption passphrase and your login password, so there is one secret to remember on day one. You can split them later. See below. |
| Hostname [omarchy] | Anything. |
| Timezone [UTC] | e.g. America/New_York. |
| Locale [en_US.UTF-8] | Anything valid. |
| Username [user] | Your daily login, not root. |
Then it runs unattended for roughly 10–15 minutes and finishes with
Bootstrap complete. Along the way it prints two verifications worth
noticing:
omarchy-zfs-embed-pool-key: verified etc/zfs/zroot.key present in /boot/initramfs-linux.img
✓ Verified: pool key embedded in the in-pool initramfs (single passphrase prompt)
✓ Boot-readiness verified: kernel+initramfs pairs, ZBM image, hostid
If instead you see “pool key is NOT embedded”, the install is still fine. You will simply be asked for the passphrase twice at boot. If a boot-readiness check fails, the installer refuses to finish and leaves everything mounted so you can look around. It stops rather than hand you a system that cannot boot.
What it builds
A GPT disk with a 1 GB EFI partition and the rest given to a pool named
zroot:
zpool create -o ashift=12 -o autotrim=on \
-o compatibility=openzfs-2.4-linux \
-O acltype=posixacl -O xattr=sa -O dnodesize=auto \
-O compression=zstd -O normalization=formD \
-O relatime=on -O atime=off \
-O encryption=aes-256-gcm -O keyformat=passphrase zroot ...
compatibility=openzfs-2.4-linux caps the feature flags to what
ZFSBootMenu release builds can read. A pool with newer features enabled is a
pool ZBM cannot open.
| Dataset | Mounted at | Why separate |
|---|---|---|
zroot/ROOT/default | / | The boot environment. canmount=noauto. ZFSBootMenu chooses it. |
zroot/data/home | /home | Survives reinstalling or rolling back the OS. |
zroot/data/root | /root | Same, for root's home. |
zroot/var/log, zroot/var/log/journal | /var/log | Logs should not vanish when you roll back the OS. journal gets acltype=posixacl because journald needs it. |
zroot/var/cache, zroot/var/tmp | /var/cache, /var/tmp | Churn you never want in a snapshot of the OS. |
zroot/var/lib/docker, libvirt, machines | under /var/lib | Container and VM images, kept out of OS snapshots. |
zroot/keystore | /etc/zfs/keys | Key material for any secondary pools. |
5. First boot
Remove the USB stick and reboot. You should see, in order:
- ZFSBootMenu asking
Enter passphrase for 'zroot':. Type the passphrase you chose. - A brief boot, then the Omarchy greeter.
- Log in with the same passphrase.
One prompt, not two. That works because the pool keyfile lives inside the
initramfs that is itself stored in the encrypted pool: ZFSBootMenu unlocks the
pool to read /boot, then the kernel it boots finds the key already
there. The key never touches the unencrypted EFI partition, and
omarchy-refresh-zbm fails loudly if it ever finds it there.
At the ZBM menu you can pick an older boot environment, roll a snapshot back before booting it, edit the kernel command line, or drop to a recovery shell with your pool imported. All before the OS starts. This is the thing a btrfs+snapper setup gives you too, and the reason a ZFS root beats ZFS-on-/home if you want it.
6. Verify what you got
omarchy-fs-type # -> zfs
zpool status # ONLINE, no errors
zfs list -o name,used,mountpoint
zpool get compatibility zroot # openzfs-2.4-linux
systemctl is-enabled zfs-import-cache zfs-mount zfs.target
systemctl list-timers omarchy-zfs-scrub.timer
All the ZFS services must be enabled. If any says
disabled, enable it. A pool that imports but never mounts its
datasets produces a system with no /home, and the symptom is a
greeter that accepts your password and then bounces you straight back. It looks
exactly like a wrong password.
sudo systemctl enable zfs-import-cache.service zfs-mount.service \
zfs-zed.service zfs-import.target zfs.target
Changing the passphrase later
The pool's wrapping key is the contents of /etc/zfs/zroot.key,
which is what gets embedded in the initramfs. Your login password is a separate
thing that merely started out identical. To change either:
Login password only
passwd # does not touch the pool
Pool passphrase
# 1. Put the new passphrase in the keyfile, with NO trailing newline
printf '%s' 'new-passphrase-here' | sudo tee /etc/zfs/zroot.key >/dev/null
sudo chmod 600 /etc/zfs/zroot.key
# 2. Re-wrap the pool key from that file
sudo zfs change-key -o keylocation=file:///etc/zfs/zroot.key zroot
# 3. Rebuild the initramfs + ZFSBootMenu so the embedded key matches
sudo omarchy-refresh-zbm
The install-and-boot path above is verified on every image we publish. This
rotation procedure is not in that automated matrix: it follows
OpenZFS's documented behaviour for change-key (the new wrapping
key is read from the location you name), but you should prove it on your own
machine rather than take it on faith.
So: reboot once and confirm the new passphrase unlocks at ZFSBootMenu
before you discard the old one. If you skip step 3, ZBM will
want the new passphrase while the initramfs still carries the old key. That
is a second prompt, not a lockout, and
sudo omarchy-refresh-zbm fixes it.
When it goes wrong
“Datasets above are not mounted; refusing to continue”
The installer's own gate. It means a dataset's mountpoint would have been shadowed, so writes would land in the wrong dataset and disappear at boot. Nothing has been unmounted. You can inspect. Upgrade to the current ISO; this was a real bug in the 2026.08.20 image, fixed in 2026.08.20.1.
Asked for the passphrase twice
The pool key is not in the initramfs. Harmless but annoying:
sudo omarchy-zfs-embed-pool-key # rebuild the in-pool initramfs with the key
sudo omarchy-refresh-zbm # or do both plus ZBM in one step
“pool was previously in use from another system”
Usually not a problem: ZFSBootMenu leaves the pool imported when it
hands off to the kernel, and the import retries and succeeds. If a boot really
does stop here, the hostid in the initramfs disagrees with the pool label. Compare hostid with what the message reports, and check
/etc/hostid exists. omarchy-zfs keeps
/etc/hostid in every initramfs with a static mkinitcpio drop-in so
this stays boring.
Emergency shell, no pool
Boot the ISO again, then:
zpool import -f -R /mnt zroot
zfs load-key zroot # or: zfs load-key -L prompt zroot
zfs mount zroot/ROOT/default
zfs mount -a
arch-chroot /mnt
From there you can rebuild the initramfs (omarchy-refresh-zbm),
fix a password (passwd <user>), or read
/var/log/journal.
Next
- Hibernation is experimental.
sudo omarchy-zfs-hibernation-setupcreates an encrypted zvol swap and wires upresume, which the target initramfs performs after ZFSBootMenu hands off. Suspend-to-disk itself is not in the test matrix, and OpenZFS discourages swap on a zvol because it can deadlock under memory pressure. A plain swap partition outside the pool is the conservative fallback. - Snapshots, scrubs and replication. Applies to a ZFS root too.
- Kernel upgrades and zfs-dkms. The one operational cost of ZFS you should understand before you depend on it.