Just Enough Chimera Linux
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 System
- 7. ZFSBootMenu
- 8. Finish Up
- 9. Resources
1. Start Here
Chimera Linux is installed as the sole operating system on a single disk using a two-partition layout:
- Partition
poolis formatted with thezfsfile system using native encryption. - Partition
espserves as the EFI system partition and is formatted with thefat32file system. - In lieu of creating a partition for
swap, thezramkernel module is used to create a compressed block device in RAM to provide swap space.
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 live ISO install images are available here: repo.chimera-linux.org
Download chimera-linux-x86_64-LIVE-[RELEASE]-base.iso, the sha256sums.txt file, then verify the image integrity:
sha256sum -c --ignore-missing sha256sums.txt
Prepare the 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-[RELEASE]-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 the 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 the 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 the 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 the 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 the 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. See this discussion.
3. Prepare the DISK
Setup 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 POOL_PART="2"
export ESP_DEVICE="${DISK}${ESP_PART}"
export POOL_DEVICE="${DISK}${POOL_PART}"
echo $ESP_DEVICE && echo $POOL_DEVICE
NVMe
Example disk: nvme0n1
export DISK="/dev/nvme0n1"
export ESP_PART="1"
export POOL_PART="2"
export ESP_DEVICE="${DISK}p${ESP_PART}"
export POOL_DEVICE="${DISK}p${POOL_PART}"
echo $ESP_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 | ->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 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 System
Chroot into the freshly installed Chimera and configure the new OS.
Chroot
chimera-chroot /mnt
Root password
passwd
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 curl efibootmgr font-terminus
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
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
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
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
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
ESP partition
NOTE
Labels on file systems are optional, but helpful. They 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
Initramfs
Encryption key is stored in /etc/zfs and will automatically be copied into the initramfs:
mkdir -p /etc/initramfs-tools/conf.d
echo 'UMASK=0077' > /etc/initramfs-tools/conf.d/umask.conf
Rebuild:
update-initramfs -u -k all
7. ZFSBootMenu
Install this bootloader to support Root-on-ZFS boot environments on Linux.
Boot properties
Assign command-line arguments to be used when booting the kernel:
zfs set org.zfsbootmenu:commandline="quiet" zroot/ROOT
Configure key caching:
zfs set org.zfsbootmenu:keysource="zroot/ROOT/${ID}" zroot
Prebuilt executable
Install a prebuilt ZFSBootMenu executable to the EFI system partition:
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!
Zram swap
Chimera uses dinit for init which supports the management of zramN devices.
Load module:
doas modprobe zram
NOTE
I set size = xG to half of the system’s physical RAM.
Create a configuration file for the zram0 device:
doas tee /etc/dinit-zram.conf >/dev/null <<'EOF'
[zram0]
size = 4G
algorithm = lz4
format = mkswap -U clear %0
EOF
Add zram0 swap to fstab:
echo '/dev/zram0 none swap defaults 0 0' | doas tee -a /etc/fstab >/dev/null
Enable the service:
doas dinitctl enable zram-device@zram0
Activate the swap for the current session:
doas swapon /dev/zram0 && zramctl
9. Resources
- ZFSBootMenu: Chimera Linux Guide
- Chimera Linux: Installation Guide
- OpenZFS Man Pages: zpoolprops.7 and zfsprops.7
- Arch Linux Wiki: Persistent block device naming
- Practical ZFS: Linux home directory on ZFS
- Dinit-chimera: zram-support
Next: Chimera Linux: After the First Boot (TODO)
You can like, share, or comment on this post on the Fediverse 💬
» Next: Configure SSH on NetBSD for Passwordless Logins to Servers
« Previous: FreeBSD: After the First Boot