Skip to content

bootc: customize composefs disks through the bootc deployment mount - #6

Closed
cgwalters-bot wants to merge 6 commits into
mainfrom
bot/bootc-composefs-deployment-mount
Closed

cgwalters-bot wants to merge 6 commits into
mainfrom
bot/bootc-composefs-deployment-mount

Conversation

@cgwalters-bot

@cgwalters-bot cgwalters-bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Collaborator

For bootc containers with the composefs backend (a UKI, or a container built for it: setup-root-conf.toml and no ostree prepare-root.conf, see #4), mount the deployment for the customization stages with osbuild's new org.osbuild.bootc.deployment mount, which runs bootc install mount from the build root, instead of refusing the customizations. Users, groups, directories, files and the subscription then land in the deployment's /etc and /var as with ostree. Kernel arguments on UKIs, ignition, bootloader and extra mountpoints stay refused (the commit message says why). Manifests without customizations are unchanged, which a new test checks.

Needs cgwalters-forge/osbuild#1 (the mount), and a bootc with install mount (bootc-dev/bootc#2483, not in a release yet) in the build root, which is the target container unless a separate build container is given. Stacked on #4; only the last commit is new. The README.md review marker that the repository's AGENTS.md requires comes from #4.

Testing, on a 16-core RHEL 10 devspace (cgwalters-devspace-37017367119; logs):

  • go test -count=1 -race ./... in a privileged Fedora 43 container (as the unit test CI job): the same 16 cmd/image-builder tests fail as on the base commit; everything else passes, including TestRawBootcImageSerializeComposefs, TestManifestComposefsCustomizationsWarn, TestRawBootcImageSerializeComposefsNoCustomizations and TestBootcDeploymentMountSerialized. go vet and gofmt clean.
  • tools/gen-manifest-checksums.sh: no checksum changes.
  • End to end: this branch's container, with osbuild from mounts: Add org.osbuild.bootc.deployment, running the build root's bootc osbuild#1, built a qcow2 from a composefs image built from bootc main (7d6df9a0, BOOTC_variant=composefs on fedora-bootc:44: the marker, no prepare-root.conf, no composefs install configuration), with a blueprint adding a user with an SSH key, a group, /etc files and kargs. The customization stages use org.osbuild.bootc.deployment. It boots (UEFI, qemu-kvm) to a composefs (BLS, grub) deployment; the user logs in with the key and has its groups, the files are there, correctly labelled, and the karg is on the command line.
  • The same blueprint on stock quay.io/fedora/fedora-bootc:44 (ostree) still uses org.osbuild.ostree.deployment, and boots an ostree deployment with all of the customizations.

Related: cgwalters-forge/tracker#164

Generated-by: https://github.com/cgwalters/#llms


Review draft in cgwalters-forge, not upstream yet. This section is removed when the PR is opened upstream.

  • Upstream: osbuild/image-builder, base main
  • Board item: PVTI_lADOE9oHIs4BlJLczg9kEXw
  • Fork CI: off; the devspace testing described above is this PR's CI, and upstream CI runs once it is opened there

To review:

  • Approve, or comment /promote on a line of its own, to open it upstream, ready for review. Either covers only the commits pushed so far.
  • If upstream requires DCO, approving also signs off: promote adds Signed-off-by: Colin Walters <walters@verbum.org> to the commits lacking it (the bot's and yours; anyone else's only if you ask), with you as committer.
  • Add a /draft line (in the same comment or before) to open it upstream as a draft (/ready undoes that).
  • Close to drop it.
  • Edit the title and description freely: they become the upstream PR's. Review comments are squashed into the commits they concern, with a reply here.

bootc-image-builder prints manifest warnings instead of failing, but
they were written without a prefix or trailing newline, so the next
progress message ran into the warning text ("...not supported: fooDone
generating manifest") and it was easy to miss. Print each warning as a
"WARNING:" line like the other warnings of the CLI. This also changes
the output of "image-builder manifest/build --ignore-warnings", which
uses the same code.

Generated-by: AI
For a bootc image with a unified kernel, the raw_bootc pipeline skips
every customization stage after "bootc install" and drops the kernel
arguments, since the command line is baked into the UKI. Users, files,
kargs and extra mountpoints given in the blueprint were therefore
silently ignored, and the build succeeded with an image that lacks
them (e.g. no login user).

Report them the same way as other unsupported blueprint options: as a
manifest warning, which the image-builder CLI turns into an error
unless --ignore-warnings is given and bootc-image-builder prints. The
container's own partition table and the default kargs from our image
definitions are not user input and are not reported.

Supporting the /etc and /var customizations is tracked in osbuild#2560.

Generated-by: AI

@cgwalters-bot cgwalters-bot left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review guide for head 7225bf6347: where to look closely and what is safe to skim. It is advice from the bot's reviewer and doesn't replace reading the diff; the review app walks it.

Stacked on #4; only the last commit (7225bf6) is new, and this guide covers only it. For composefs disks (UKI or the composefs-backend install config) the customization stages now use the new osbuild org.osbuild.bootc.deployment mount instead of being skipped, so users, groups, directories, files and subscription are no longer refused. Most of the raw_bootc.go diff is a re-indent from removing the outer if !composefs block (read it with -w). Manifest stability: the new mount is only attached to post-install stages, and with no customizations postStages is empty and the SELinux relabel is skipped, so composefs manifests without customizations are unchanged. The checksum run does not include composefs configs, so that rests on code reading and has no unit test. Remaining refusals (UKI kargs, ignition, bootloader, extra mountpoints) match the stages still skipped for composefs. The extra-mountpoint refusal rationale (no fstab) is weaker now that /etc is writable through the new mount; that could be a follow-up. Subscription is un-refused but was not exercised end to end.

Hotspots

  1. look-closely · logic — pkg/manifest/raw_bootc.go:209-218 (7225bf6): The mount choice. Everything that can change a composefs manifest flows from here; check that nothing unconditional (fstab, grub2.d, ignition, relabel) now picks these mounts up when there are no customizations.
  2. note · logic — pkg/manifest/raw_bootc.go:221-233 (7225bf6): fstab/mount-unit stages are still skipped for composefs, although the deployment /etc is now writable through the bootc mount. That is what keeps extra mountpoints refused; it could likely be enabled as a follow-up.
  3. note · test-gap — pkg/manifest/raw_bootc.go:400-415 (7225bf6): The SELinux relabel of /etc and /var is gated on len(postStages) > 0, which is what keeps no-customization composefs manifests unchanged. No test pins that; an assertion that composefs without customizations has no bootc.deployment mount and no selinux stage after install would guard it.
  4. note · api — pkg/distro/defs/bootc_imagetype.go:881-905 (7225bf6): The remaining refusals. UKI kargs, ignition and bootloader correspond to stages still skipped for composefs, so the set is consistent. The doc comment has an overlong unwrapped line (887).

Safe to skim

  • pkg/osbuild/bootc_deployment_mount.go: thin options type mirroring the ostree deployment mount
  • pkg/osbuild/bootc_deployment_mount_test.go: JSON serialization fixture
  • pkg/distro/defs/bootc_image_test.go:762-800: expected warnings removed for the now-supported customizations

@cgwalters-bot
cgwalters-bot force-pushed the bot/bootc-composefs-deployment-mount branch from 7225bf6 to cd64d94 Compare September 29, 2026 02:47
@cgwalters-bot

Copy link
Copy Markdown
Collaborator Author

Squashed into cd64d94 (review 5346756983): added TestRawBootcImageSerializeComposefsNoCustomizations (composefs/UKI without customizations: no bootc.deployment mount, no fstab, grub2.d or post-install selinux stage; ostree as the positive control), rewrapped the doc comment, and the commit message now says why fstab, ignition and grub2 console stay unsupported. go test and manifest checksums rerun.

Per AGENTS.md, for the human author to remove once reviewed.

Generated-by: AI
bootc installs a container with the composefs backend, even without a
UKI, when it ships /usr/lib/composefs/setup-root-conf.toml and has no
ostree prepare-root.conf (see "The storage backend" in
bootc-installation(7)). Record that so the disk image code can take it
into account.

Generated-by: AI
osbuild's bootc install-to-filesystem stage runs bootc from the
container, which installs a container that ships setup-root-conf.toml
and no ostree prepare-root.conf with composefs even though it has no
UKI. The customization stages after it then fail to mount the ostree
deployment ("Could not find deployment").

Treat such containers like UKI images: pass the composefs option, skip
the stages that work on the ostree deployment and report the
customizations that are dropped. Kernel arguments are still passed to
bootc install, which puts them in the BLS entries. The PXE tar image
type builds its live root from the ostree deployment, so it is refused
for these containers.

Generated-by: AI
Users, groups, directories, files and the subscription were refused
for bootc containers with the composefs backend (and dropped for UKI
images before that), because every customization stage worked on the
deployment through org.osbuild.ostree.deployment, which only knows
ostree's layout.

osbuild's org.osbuild.bootc.deployment mount has bootc from the build
root assemble the deployment instead (`bootc install mount`), for
either backend. Use it for composefs, so these customizations land in
the deployment's /etc and /var as they do with ostree. Manifests
without customizations don't change: the mount is only used by the
customization stages.

The fstab, ignition and grub2 console stages still aren't generated
for composefs, so those customizations stay refused:
- bootc finds the root and /boot of a composefs system without an fstab
  (from the kernel command line, or from the partition types with a
  UKI) and doesn't write one. Adding one for extra mountpoints is
  possible now that /etc is reachable, but whether image-builder should
  start managing an fstab there is a question of its own.
- ignition and the grub2 console config write to /boot directly,
  assuming ostree's grub layout; a composefs system may use
  systemd-boot and UKIs, and bootc lays out /boot differently, so they
  need to be done per bootloader.

This needs a build root with a bootc that has `install mount`
(bootc-dev/bootc#2483, not in a release yet), which is the target
container itself unless a separate build container is given.

Generated-by: AI
@cgwalters-bot
cgwalters-bot force-pushed the bot/bootc-composefs-deployment-mount branch from cd64d94 to b1e47f6 Compare October 2, 2026 14:46
@cgwalters-bot

Copy link
Copy Markdown
Collaborator Author

Rebased onto #4 as reworked (now 97fe5d1) with no conflicts; this commit (now b1e47f6) is unchanged. Retested end to end with a bootc-main composefs image that selects composefs via setup-root-conf.toml, plus an ostree control; see the description.

Generated-by: https://github.com/cgwalters/#llms

@cgwalters-bot

Copy link
Copy Markdown
Collaborator Author

Folded into #7, which uses the bootc deployment mount whenever the build root's bootc has install mount instead of detecting composefs.

Generated-by: https://github.com/cgwalters/#llms

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

1 participant