Last edited on 2026-04-16 • Tagged under #chimera #linux #zfs #encrypt #zfsbootmenu
Chimera Linux is a delightful community-driven Linux distribution built from scratch that does things differently: musl instead of the typical glibc for C library, dinit over systemd for system init, and a userland derived from FreeBSD core tools.
Using the Chimera base install image and working my way through this excellent installation guide for configuring Chimera with the OpenZFS filesystem and the ZFSBootMenu bootloader, I show the choices I make to create an encrypted, minimal Linux system with “just enough” to provide a solid foundation to build upon further: whether that be setting up a desktop, laptop, or server.
- 1. Start Here
- 2. Configure the Live Environment
- 3. Prepare the DISK
- 4. ZFS Pool Creation
- 5. Installation
- 6. Configure the New System
- 7. ZFSBootMenu
- 8. Finish Up
- 9. Resources
1. Start Here
Throughout this HOWTO, if you see square brackets [] in code blocks, that means the word of code (square brackets included) should be replaced with something else. This is detailed in the instructions before or after the code block.
Chimera Linux is installed as the sole operating system on a single disk using a three-partition layout:
- Partition
espserves as the EFI system partition and is formatted with thefat32file system. - Partition
swapprovides auto-initialised swap space with encryption at boot courtesy ofdm-crypt. - Partition
poolcontains the root filesystem and is formatted with thezfsfile system using native encryption.
A few assumptions:
- Target device is
x86_64architecture using UEFI to boot. - Secure boot is disabled on target device.
- Network access during install uses a wired interface.
- System does not require hibernation support.
Acquire an installation image
The latest RELEASE as of April, 2026 is 20251220.
The latest live ISO install images are available here: repo.chimera-linux.org
Download chimera-linux-x86_64-LIVE-20251220-base.iso, the sha256sums.txt file, then verify the image integrity:
sha256sum -c --ignore-missing sha256sums.txt
Prepare USB installation medium
Write the installer to an unmounted USB storage device running the dd command as root.
WARNING
Be very careful to note the proper device (which can be identified with the lsblk command). All contents on the device will be lost!
Example: On a Linux system, if a USB stick appears as sdx1, then write the installer to sdx (omit partition number):
dd bs=4M conv=fsync oflag=direct status=progress if=chimera-linux-x86_64-LIVE-20251220-base.iso of=/dev/sdx
2. Configure the Live Environment
Boot the target device from the Chimera installation media. Login and password is root:chimera.
Set larger console font
If the existing font size appears too small, running:
setfont -d
… will double the size.
Console fonts are located in /usr/share/consolefonts/ and a different font can be set with setfont omitting the path and file extension.
Set temporary console keyboard
Default console keymap is us. Available keymaps are listed in /usr/share/keymaps/.
If some other keymap is desired, set a different keymap temporarily with loadkeys:
loadkeys [keymap]
…where [keymap] is the desired keyboard layout.
Example: I configure the system to use my preferred colemak layout, which is available in /usr/share/keymaps/i386/colemak:
loadkeys colemak/en-latin9
Verify boot mode
Confirm target device is using UEFI boot mode:
cat /sys/firmware/efi/fw_platform_size
If the command returns 64, then system is booted in UEFI with 64-bit x64 UEFI and we are good to go.
NOTE
If the file does not exist, the device is not using UEFI.
Connect to internet
Wired network interfaces should be auto-enabled and connected at boot.
Verify the network interface is active, has been assigned an address, and the internet is reachable:
ip addr
ping -c 5 chimera-linux.org
Remote login to installer
Make this manual installation process easier (i.e. cut-n-paste commands) by remotely logging into the installer via ssh from another computer.
Start the sshd daemon:
dinitctl start sshd
Switch to the other computer and ssh into the target device as anon:chimera:
ssh anon@[ip_address]
… where [ip_address] is the target device’s address obtained with the ip addr command above.
Switch to root:
doas -s
Define ID variable
File /etc/os-release defines variables that describe the current operating system. Use the $ID variable to set the short name of the Linux distribution in later commands:
. /etc/os-release && export ID && echo $ID
Generate hostid
Generate hostid hexadecimal identifier for use by ZFSBootMenu:
zgenhostid "$(hostid)" && hostid
NOTE
Musl doesn’t read /etc/hostid and will always display 00000000. Its not an issue.
3. Prepare the DISK
Set up a custom partition layout on a single disk before implementing the Chimera base installation.
Install:
apk update && apk add --no-interactive gptfdisk parted
Define DISK variables
Identify the disk where Chimera will be installed by listing block devices:
lsblk -f
Set DISK variables for either a SATA or NVMe disk:
SATA
Example disk: sda
export DISK="/dev/sda"
export ESP_PART="1"
export SWAP_PART="2"
export POOL_PART="3"
export ESP_DEVICE="${DISK}${ESP_PART}"
export SWAP_DEVICE="${DISK}${SWAP_PART}"
export POOL_DEVICE="${DISK}${POOL_PART}"
echo $ESP_DEVICE && echo $SWAP_DEVICE && echo $POOL_DEVICE
NVMe
Example disk: nvme0n1
export DISK="/dev/nvme0n1"
export ESP_PART="1"
export SWAP_PART="2"
export POOL_PART="3"
export ESP_DEVICE="${DISK}p${ESP_PART}"
export SWAP_DEVICE="${DISK}p${SWAP_PART}"
export POOL_DEVICE="${DISK}p${POOL_PART}"
echo $ESP_DEVICE && echo $SWAP_DEVICE && echo $POOL_DEVICE
Wipe DISK
If there was previously a ZFS pool on DISK, run:
zpool labelclear -f $DISK
If DISK was previously configured with LVM, bring down the volume group:
vgchange -an
Wipe existing file systems and partition table on DISK:
wipefs -af $DISK && sgdisk --zap-all --clear $DISK
Notify the system of changes to the partition table:
partprobe $DISK
Partition DISK
NOTE
Many partitioning guides assign 256-512M of space to the EFI system partition. I like to future-proof the partition for whatever else Linux might want to store there by assigning a more generous 2G of space.
Create a GPT partition table on DISK with the following layout:
| Number | Size | Code | Format | Use as | Mountpoint |
|---|---|---|---|---|---|
| 1 | 2g | ef00 | vfat | EFI system partition | /boot/efi |
| 2 | 8g | 8200 | swap | Swap partition | (not applicable) |
| 3 | ->END | bf00 | zfs | ZFS pool partition | / |
Create the EFI system partition:
sgdisk -n "${ESP_PART}:1m:+2g" -t "${ESP_PART}:ef00" -c 0:esp $DISK
Create the swap partition:
sgdisk -n "${SWAP_PART}:0:+8g" -t "${SWAP_PART}:8200" -c 0:swap $DISK
Create the ZFS pool partition:
sgdisk -n "${POOL_PART}:0:0" -t "${POOL_PART}:bf00" -c 0:pool $DISK
Display DISK layout:
partprobe $DISK && sgdisk -p $DISK
4. ZFS Pool Creation
When adding disks or partitions to ZFS pools, its good practice to refer to them by the symbolic links created in /dev/disk/by-partuuid (UEFI) so that ZFS will identify the right devices even if disk naming should change at some point. Using traditional device nodes like /dev/sda2 may cause intermittent import failures.
So I create a POOL_ID variable:
POOL_ID=/dev/disk/by-partuuid/$( blkid -s PARTUUID -o value $POOL_DEVICE )
Verify:
ls -al /dev/disk/by-partuuid/ && echo "POOL_ID = $POOL_ID"
Create encryption keyfile
Store the encryption passphrase for the ZFS pool in a keyfile:
echo 'SuperSecretPassphrase' > /etc/zfs/zroot.key
chmod 000 /etc/zfs/zroot.key
Create encrypted ZFS pool
Create the pool with native encryption enabled:
zpool create -f \
-o ashift=12 \
-o autotrim=on \
-o compatibility=openzfs-2.3-linux \
-O acltype=posixacl \
-O xattr=sa \
-O compression=lz4 \
-O encryption=aes-256-gcm \
-O keylocation=file:///etc/zfs/zroot.key \
-O keyformat=passphrase \
-O relatime=on \
-m none zroot "$POOL_ID"
Create ZFS datasets
NOTE
It is necessary to explicitly set the canmount=noauto on every boot environment you create.
zfs create -o mountpoint=none zroot/ROOT
zfs create -o mountpoint=/ -o canmount=noauto zroot/ROOT/${ID}
Set the preferred boot file system:
zpool set bootfs=zroot/ROOT/${ID} zroot
I create an additional home dataset for each system:
zfs create zroot/ROOT/${ID}/home
This allows me to keep user config files unique to each boot environment that I might create in the future. It also separates user data from system data, which is useful for ZFS snapshots and enables system rollbacks while leaving user data untouched.
To share data between boot environments, I create a data dataset to store common files:
zfs create -o mountpoint=/data zroot/data
Export and re-import pool for installation
zpool export zroot
zpool import -N -R /mnt zroot
zfs load-key -L prompt zroot
Mount datasets:
zfs mount zroot/ROOT/${ID}
zfs mount zroot/ROOT/${ID}/home
zfs mount zroot/data
Verify:
# mount -t zfs
zroot/ROOT/chimera on /mnt type zfs (rw,relatime,xattr,posixacl,casesensitive)
zroot/ROOT/chimera/home on /mnt/home type zfs (rw,relatime,xattr,posixacl,casesensitive)
root/data on /mnt/data type zfs (rw,relatime,xattr,posixacl,casesensitive)
Update device symlinks:
udevadm trigger
5. Installation
Install the base-full packages:
chimera-bootstrap /mnt
Copy files into the new operating system:
cp /etc/hostid /mnt/etc/
mkdir /mnt/etc/zfs && cp /etc/zfs/zroot.key /mnt/etc/zfs/
6. Configure the New System
Chroot into the freshly installed Chimera and configure the new OS.
Enter chroot
chimera-chroot /mnt
Set root password
passwd
Create superuser
Create a user account with superuser privileges:
useradd -m -G wheel [username]
… where [username] is the desired name for the account.
Set a password for [username]:
passwd [username]
(Optional) Give root access to [username] with no password using the doas command:
echo 'permit nopass keepenv [username]' >> /etc/doas.conf
Package manager and extra packages
Add the user subrepo and sync mirrors:
apk add --no-interactive chimera-repo-user && apk update
Identify the processor vendor:
grep vendor_id /proc/cpuinfo
Define a variable for an appropriate microcode package to load updates and security fixes:
UCODE="[vendor]"
… where [vendor] for Intel processors is ucode-intel and AMD processors is ucode-amd.
Install:
apk add --no-interactive $UCODE linux-lts-zfs-bin cryptsetup cryptsetup-scripts-initramfs-tools curl efibootmgr font-terminus
Set console font
NOTE
For terminus font settings, see /usr/share/consolefonts/README.Lat2-Terminus16 for details.
Chimera uses the same console-setup system as Debian.
Example: Use TerminusBold as the console font and increase font size by modifying /etc/default/console-setup:
ACTIVE_CONSOLES="/dev/tty[1-6]"
CHARMAP="UTF-8"
CODESET=guess
FONTFACE=TerminusBold
FONTSIZE=12x24
Set console keyboard
Default keyboard is us. If a keymap alternative is desired, see keyboard(5) for options.
Example: I like to use the colemak keymap (available in /usr/share/keymaps/i386/colemak), which I set by modifying /etc/default/keyboard:
KMAP=colemak/en-latin9
XKBMODEL=pc105
XKBLAYOUT=us
Set timezone
Timezones are located in /usr/share/zoneinfo/[Region]/[City], where [Region] is the geographical region (Africa, America, Europe, …) and the [City] within that region.
Example: Create the /etc/localtime symbolic link to the timezone where Toronto is located:
ln -sf /usr/share/zoneinfo/America/Toronto /etc/localtime && date
Assign hostname
Create the hostname file:
echo [hostname] > /etc/hostname
… where [hostname] is the desired name of the system (single word, no spaces):
echo chimeralinux > /etc/hostname
Enable services
Links to services enabled by the admin are in /etc/dinit.d/boot.d/.
Default logging system on Chimera is syslog-ng.
Enable the service:
dinitctl -o enable syslog-ng
Logs are written to /var/log/messages.
You can configure wired networks statically or dynamically with dhcpcd.
Enable the service:
dinitctl -o enable dhcpcd
Default activity is for dhcpcd to configure all interfaces with DHCP. Changes are made in /etc/dhcpcd.conf. See dhcpcd.conf(5) for more details.
Enable the sshd service to allow remote logins:
dinitctl -o enable sshd
Format and mount ESP partition
NOTE
Labels on file systems are optional, but helpful. They are a more reliable way to identify the correct partition than simple device nodes and allow for easy mounting without a UUID.
Create a fat32 file system:
mkfs.fat -n ESP -F 32 $ESP_DEVICE
Mount device:
mount --mkdir $ESP_DEVICE /boot/efi
Add partition to fstab:
echo 'LABEL=ESP /boot/efi vfat defaults 0 0' >> /etc/fstab
Enable swap encryption
Using raw dm-crypt enables the system to generate a random, one-time encryption key at boot that requires no action from the user to encrypt swap. At shutdown the key is discarded, rendering any remaining data effectively destroyed.
To allow the use of a label (as previously done with the ESP) to identify the swap partition that can survive an overwrite, a swap offset can be used. Create this offset by writing a tiny, empty file system on SWAP_DEVICE whose sole purpose is to provide a persistent label for swap creation:
mkfs.ext2 -L cryptswap $SWAP_DEVICE 1M
Configure dm-crypt to set up swap on this cryptswap partition at boot by adding an entry to crypttab:
echo 'swap LABEL=cryptswap /dev/urandom plain,swap,offset=2048,cipher=aes-xts-plain64,size=512,sector-size=4096' >> /etc/crypttab
Add swap device to fstab:
echo '/dev/mapper/swap none swap defaults 0 0' >> /etc/fstab
Regenerate initramfs
Encryption key is stored in /etc/zfs and will automatically be copied into the initramfs.
Set UMASK=0077 as default permissions for newly created files and directories:
mkdir -p /etc/initramfs-tools/conf.d
echo 'UMASK=0077' > /etc/initramfs-tools/conf.d/umask.conf
… and set RESUME=none to disable the cryptsetup command from checking/warning about the lack of hibernate/resume support in our swap partition:
echo 'RESUME=none' > /etc/initramfs-tools/conf.d/resume
Regenerate:
update-initramfs -u -k all
Any warning messages along the lines of:
cryptsetup: WARNING: Couldn't determine root device
… can be safely ignored. In this instance the script is looking for a root mapping that doesn’t exit (root encryption is handled in ZFS).
Install the ZBM bootloader to support Root-on-ZFS boot environments on Linux.
Boot properties
NOTE
Add the hibernate=no argument to ensure that no process can trigger a suspend-to-disk action, which is consistent with the goal of using a non-persistent, random-key swap.
Assign command-line arguments to be used when booting the kernel:
zfs set org.zfsbootmenu:commandline="quiet hibernate=no" zroot/ROOT
Configure key caching:
zfs set org.zfsbootmenu:keysource="zroot/ROOT/${ID}" zroot
Prebuilt executable
Install a prebuilt ZBM executable to the ESP:
mkdir -p /boot/efi/EFI/ZBM
curl -o /boot/efi/EFI/ZBM/VMLINUZ.EFI -L https://get.zfsbootmenu.org/efi
cp /boot/efi/EFI/ZBM/VMLINUZ.EFI /boot/efi/EFI/ZBM/VMLINUZ-BACKUP.EFI
EFI boot entries
efibootmgr -c -d "$DISK" -p "$ESP_PART" -L "ZFSBootMenu (Backup)" -l '\EFI\ZBM\VMLINUZ-BACKUP.EFI'
efibootmgr -c -d "$DISK" -p "$ESP_PART" -L "ZFSBootMenu" -l '\EFI\ZBM\VMLINUZ.EFI'
8. Finish Up
Exit chroot, unmount, and export
Exit chroot:
exit
Unmount everything:
umount /mnt/home && umount /mnt/data && umount /mnt/boot/efi && umount -n -R /mnt
Export the zpool:
zpool export zroot
Reboot
reboot
NOTE
When prompted for passphrase to unlock zpool, keymap is us regardless of keymap that might have been set on system.
User is prompted for the passphrase to unlock the encrypted root partition. Upon success, boot resumes:
chimeralinux login:
Welcome to Chimera!
9. Resources
- ZFSBootMenu: Chimera Linux Guide
- Chimera Linux: Installation Guide
- OpenZFS Man Pages: zpoolprops.7 and zfsprops.7
- Practical ZFS: Linux home directory on ZFS
- Arch Linux Wiki: Persistent block device naming and swap encryption
Next: Chimera Linux: After the First Boot (TODO)
You can like, share, or comment on this post on the Fediverse 💬