Skip to main content

Prerequisites

Before building custom Zirconium images, ensure you have:
  • Podman or Docker installed
  • Root/sudo access for bootable image creation
  • At least 20GB free disk space
  • Fedora or compatible Linux distribution (for ISO/disk creation)

Basic image build

The simplest way to build a Zirconium container image:
podman build -t zirconium:latest .
This creates a standard Zirconium image tagged as zirconium:latest in your local container storage.

Building NVIDIA variant

For systems with NVIDIA graphics cards:
podman build --build-arg BUILD_FLAVOR=nvidia -t zirconium:nvidia .
The BUILD_FLAVOR argument controls which build scripts execute. When set to “nvidia”, the NVIDIA driver installation scripts run during the build.

Using Justfile commands

Zirconium includes a Justfile with convenient build automation commands. These recipes handle complex operations with sensible defaults.

Creating bootable ISO

Generate a bootable ISO installer:
just iso
This command:
  1. Pulls the specified image (default: zirconium:latest)
  2. Runs bootc-image-builder in a privileged container
  3. Creates an ISO with Btrfs root filesystem
  4. Outputs the ISO to the ./output directory
just iso

Creating disk images

Build a raw disk image for deployment:
just disk-image
This creates a 20GB disk image at ./bootable.img with ext4 filesystem by default.
1

Create the image file

The recipe uses fallocate to create a sparse 20GB file:
fallocate -l 20G bootable.img
2

Install bootc to disk

Runs bootc install to-disk via loopback mount:
just bootc install to-disk --via-loopback /data/bootable.img --filesystem ext4 --wipe

Filesystem options

Change the root filesystem type:
just disk-image

Quick iteration workflow

For rapid development and testing:
just quick-iterate
This recipe:
  1. Builds the image locally: podman build -t zirconium:latest .
  2. Transfers it to root account: just rootful
  3. Creates a disk image in /tmp: BUILD_BASE_DIR=/tmp just disk-image
The quick-iterate command uses /tmp for disk images, which will be lost on reboot. This is intentional for fast testing cycles.

Modifying the Containerfile

Adding new build layers

To add custom software or configuration, insert a new RUN layer:
RUN --mount=type=bind,from=ctx,source=/,target=/ctx \
    --mount=type=tmpfs,dst=/var \
    --mount=type=tmpfs,dst=/tmp \
    --mount=type=tmpfs,dst=/run \
    --mount=type=tmpfs,dst=/boot \
    /ctx/build/03-custom-fetch.sh
Place your custom layer between the theme layer (01) and misc layer (99) to maintain logical build order.

Changing the base image

To use a different Fedora version:
FROM quay.io/fedora/fedora-bootc:45

Adding files to the context

Include additional resources in the build context:
FROM scratch AS ctx

COPY assets /assets
COPY build_files /build
COPY system_files /files
COPY my_custom_files /custom  # Add this line
COPY cosign.pub /files/usr/share/pki/containers/zirconium.pub
Then access them in build scripts via /ctx/custom/.

Testing custom builds

Local container testing

Run your built image as a container:
podman run -it --rm zirconium:latest /bin/bash

Validation checks

Verify the image passes bootc requirements:
podman run --rm zirconium:latest bootc container lint

Testing in a VM

After creating a disk image:
qemu-system-x86_64 \
  -enable-kvm \
  -m 4G \
  -smp 2 \
  -drive file=bootable.img,format=raw \
  -display gtk

ISO testing

Test the ISO in a VM:
qemu-system-x86_64 \
  -enable-kvm \
  -m 4G \
  -smp 2 \
  -cdrom output/bootiso/install.iso \
  -boot d \
  -drive file=test-disk.img,format=raw \
  -display gtk

Environment variables

Customize builds with environment variables:
VariableDescriptionDefault
IMAGE_FULLFull image referencezirconium:latest
BUILD_FLAVORBuild variant (empty or “nvidia”)
BUILD_FILESYSTEMRoot filesystem typeext4
BUILD_BASE_DIROutput directory for disk images. (current dir)
Environment variables can be set inline with commands:
BUILD_FLAVOR=nvidia IMAGE_FULL=my-custom:latest just iso

Troubleshooting

Build fails during package installation

If DNF operations fail:
  1. Check your internet connection
  2. Verify COPR repositories are accessible
  3. Try clearing the cache: podman build --no-cache

NVIDIA build issues

If NVIDIA drivers fail to build:
  • Ensure you’re using a compatible kernel version
  • Check /usr/src/nvidia-* for driver source availability
  • Review the patch application in 02-nvidia-fetch.sh:26-30 for kernel compatibility

ISO creation fails

If just iso fails:
  1. Ensure you have root/sudo access
  2. Check that /var/lib/containers/storage is accessible
  3. Verify the image exists: sudo podman images | grep zirconium
  4. Make sure output/ directory exists and is writable

Disk image won’t boot

If the disk image fails to boot:
  • Verify the image was created successfully: ls -lh bootable.img
  • Check it’s at least 1GB: Images smaller than this may be incomplete
  • Ensure you used --wipe flag or the disk was empty
  • Try a different filesystem: BUILD_FILESYSTEM=btrfs just disk-image