Status: proposed

Context

Issue #11 points out two facts. Every installable artefact that Corium produces (the qcow2, the raw disk and the installer ISO) goes through bootc-image-builder. And upstream archived that project on 2026-06-18. These are the facts, checked against the registries and the upstream source, not against the announcement:

  • mise.toml and both workflows track quay.io/centos-bootc/bootc-image-builder:latest. Its last build was on 2026-06-18 at 11:31 UTC, from commit a686afe, “readme: migration notice”, which is the archive commit. Its digest is sha256:2b52843ea2bfda73b0a08d97e76b734393b1d3a804681b9fabb26723bd3a2f0b. It is built on Fedora 42, which reached end of life on 2026-05-13, a month before the image was built. The tag that we follow stopped moving three months ago. Nobody noticed, because nothing broke.
  • The code did not stop. Upstream merged it into osbuild/image-builder. That project releases weekly (v78.0.0 through v83.0.0 between mid-August and 2026-09-16). It publishes three images from one workflow, all on Fedora 44. ghcr.io/osbuild/image-builder and ghcr.io/osbuild/image-builder-cli are the same digest under two names. ghcr.io/osbuild/bootc-image-builder holds the same binary, installed as /usr/bin/bootc-image-builder, with the old entry point, flags, and output layout. Each image has a tag per release. For the compatibility image, v83.0.0 is sha256:e7aadce6b3f5639cd47d83354791931ea219891a0d113c2fe74a0f0d352b165c.
  • The deprecation notice commits to keep that entry point for the life of RHEL 10, and to drop it in RHEL 11. It says the same about the anaconda-iso image type: deprecated, removed in RHEL 11, with the container-based installers as the path forward.

The issue asked three questions. We answered each one from the image-builder source at v83.0.0 and the documentation in its tree. The published pages describe the image types, but they do not say what the types do.

Is image-builder build --bootc-ref a drop-in replacement?

For the qcow2 and the raw disk, yes in substance and no in detail. The command becomes image-builder build --bootc-ref <image> qcow2. It runs from ghcr.io/osbuild/image-builder, with the same privileged flags and the same mount of the root container store. The container must already be in local storage. The release workflow already does this today, because it pulls the image first. The builder reads the root filesystem type from the bootc install configuration of the container (/usr/lib/bootc/install/00-corium.toml, per ADR 2). So --bootc-default-fs is not necessary. Two things differ:

  • The output layout. image-builder writes <distro>-<type>-<arch>/<distro>-<type>-<arch>.<ext>. For a bootc input, this is bootc-based-qcow2-x86_64/bootc-based-qcow2-x86_64.qcow2. bootc-image-builder writes qcow2/disk.qcow2. --output-dir and --output-name restore today’s paths. So deploy/proxmox/ and the publish step, which only consume files, do not need to change.
  • A warning during manifest generation stops the build, unless you pass --ignore-warnings. This is a feature, because the release path must fail loudly. But it is a change in behavior to expect on the first run.

For the ISO, no. If you give the CLI a bootc reference, it refuses the type outright:

image type bootc "anaconda-iso" is not supported with image-builder,
please consider switching to "bootc-installer" or use bootc-image-builder

The comment above that check gives the reason. Without the mTLS plumbing that the old tool set up, the behavior would differ in small ways. Upstream chose an error over a quiet incompatibility. anaconda-iso is reachable only through the compatibility entry point. In upstream’s own image definitions, that code path (bootc_legacy_iso) carries the note “we want to get rid of it”.

Can bootc-generic-iso carry a custom kickstart?

Not the way [customizations.installer.kickstart] does today, because the generic ISO reads no build configuration at all. In the source, manifestForGenericISO is the only image function that never receives the blueprint. The ISO that it produces is the container itself, converted to a squashfs and booted live. Its GRUB menu comes from /usr/lib/image-builder/bootc/iso.yaml inside the container. When that ISO boots, it does what the container does when it boots. Upstream’s reference has three parts: a fedora-bootc container with Anaconda installed by dnf, an iso.yaml that boots it with inst.stage2=, and a kickstart at /usr/share/anaconda/interactive-defaults.ks. The kickstart holds a single bootc --source-imgref … --target-imgref … line. --bootc-installer-payload-ref copies the image to install into the container store of the squashfs. This is what makes the install work offline.

So the kickstart does not go away. It moves. It is no longer a build input that the builder receives. It becomes a file in an installer container that Corium must build and own: a second Containerfile beside the appliance and ZFS variants. The RAID root procedure in docs/raid.md is still an Anaconda kickstart, with the same content and the same three manual steps. Only its delivery changes. It must be tested again on two disks, because the earlier test used the ISO type that this decision retires.

Two things follow that are easy to miss:

  • Today’s ISO is unattended, because bootc-image-builder ships a default kickstart for anaconda-iso. That kickstart installs to the first disk with no prompts. In the generic ISO, we must write that default ourselves. It is a few lines, and the quick start and deploy/proxmox/create-vm-iso.sh depend on it.
  • bootc-installer, the other suggested type, is Anaconda-based and does honor the blueprint kickstart. It uses the same kickstart.New(customizations) call as the legacy path. But it also requires two containers. --bootc-ref must be an Anaconda installer environment, and the image to install goes in --bootc-installer-payload-ref. Upstream lists it under “Historical” and says to prefer the generic type. It needs the installer container in both cases, so it saves nothing.

Does pinning buy useful time?

Pinning the Quay digest gives reproducibility and nothing else. The tag is already frozen. A digest makes that explicit, and lets CI record which builder produced an artefact. The release workflow cannot do this today. A digest does not make the builder maintained, and the base of the builder is a Fedora release that no longer receives updates.

Pinning the compatibility image from image-builder gives the time we need. It has the same entry point, the same flags, and the same output paths. The people who wrote it keep them working on purpose, on a current base, with a version number to bump. It still builds anaconda-iso. This is exactly what we need while we rebuild the ISO on the generic type: one change that stops the dependency from decaying, and that does not touch the install path that a release is verified against.

Decision

  1. Now: build with ghcr.io/osbuild/bootc-image-builder, pinned to a release tag and its digest, everywhere the builder is named. These places are mise.toml, the release workflow and the end-to-end workflow. Same command, same three artefact types, same output files. The BIB environment override stays. So if the new image misbehaves, the frozen Quay digest is a one-line fallback. A bump of the pin is a reviewable diff that contains the digest, as build/k0s.lock already does for the k0s binary.

  2. Next, as its own change: the qcow2 and the raw disk move to image-builder build --bootc-ref. They run from ghcr.io/osbuild/image-builder, pinned the same way. --output-dir and --output-name keep output/qcow2/disk.qcow2 and output/image/disk.raw. The end-to-end workflow builds a qcow2 and boots it, and that is the test. After this step, the compatibility image builds the ISO and nothing else.

  3. Then: an installer container, built as bootc-generic-iso. It has three parts: a Containerfile that derives from the Fedora bootc base with Anaconda, an iso.yaml, and a default kickstart. The kickstart installs the embedded Corium image to the first disk, unattended. --bootc-installer-payload-ref passes the image to install, by digest, as today. The RAID root procedure becomes a variant of that container, with a different kickstart file at build time. We test it again by removing a disk, as we did for the first one. The published ISO stays on anaconda-iso until the generic ISO has installed a node through the release verification list, including the Proxmox script and the RAID procedure. Not before, because bare metal is a documented path with one artefact, and this ISO is the only thing that exercises that path.

Step 1 is in this change. Steps 2 and 3 wait for their tests to pass, not for a date. RHEL 11 is the outer limit, not the schedule.

Consequences

Nothing changes today for a person who builds or installs Corium. The commands, the artefacts and their paths stay the same, and the published ISO installs the same way.

The builder becomes a pinned dependency, like the others. This is a small recurring cost: a digest to bump, ideally with each Corium release. In exchange, we know which bytes produced an artefact, and the release job can say so. Today the release job prints the digest of whatever :latest was at that time.

Step 2 changes the command in the same two places. It carries a risk: a warning that bootc-image-builder tolerated can become an error. The end-to-end workflow exists to catch this kind of failure.

Step 3 adds a second container image to build and a verification item to the release list. It also makes the installer ours. A file in this repository defines what the ISO does at boot, not the defaults of the builder. A project that documents a RAID root needs it there. We rewrite the kickstart section of docs/raid.md when step 3 lands, not before.

Upstream warns that a bootc system installed through Anaconda fails systemd-remount-fs.service at boot ( bugzilla 2332319). Today’s ISO also installs through Anaconda. So either this already happens and is harmless, or it does not reproduce here. In both cases, we test it when we test the new ISO, and we do not assume it.

Alternatives considered

Keep tracking quay.io/centos-bootc/bootc-image-builder:latest. It did not move after the archive commit, and it will not move. A tag that is frozen today and returns 404 tomorrow is the failure mode that the issue describes, found during a release. Rejected.

Pin the Quay digest and stop there. This is reproducible and honest about what built an artefact. Otherwise it is identical to the option above: an end-of-life base and an unmaintained binary. We keep it as the fallback that the BIB override uses, not as the decision.

Move everything to image-builder build --bootc-ref in one step. Not possible. The CLI refuses anaconda-iso, and the replacement ISO needs an installer container that does not exist yet. If we do the disks now and the ISO later, we reach the same end state, with a test between the two steps.

Use bootc-installer rather than bootc-generic-iso for the ISO, because it honors [customizations.installer.kickstart] and keeps docs/raid.md closer to its current content. It still requires our own installer container, and upstream marks it historical. It also ties the ISO to Anaconda, where the generic type leaves the choice to the container. It saves nothing. Rejected.

Drop the ISO and publish only disks. The ISO is the documented path onto bare metal, and the RAID root depends on it. deploy/proxmox/create-vm-iso.sh and the appliance image both produce one. Rejected.