Skip to content

osbuild: use bootc install to deploy the container#4224

Open
jbtrystram wants to merge 11 commits intocoreos:mainfrom
jbtrystram:osbuild-bootc-install-fs
Open

osbuild: use bootc install to deploy the container#4224
jbtrystram wants to merge 11 commits intocoreos:mainfrom
jbtrystram:osbuild-bootc-install-fs

Conversation

@jbtrystram
Copy link
Member

Instead of deploying the container to the tree then copy all the contents to the disk image, use bootc to directly manage the installation to the target filesystems.

Right now this requires to use the image as the buildroot so this requires python (for osbuild). This is tracked in [1].

[1] bootc-dev/bootc#1410 Requires osbuild/osbuild#2149

@openshift-ci
Copy link

openshift-ci bot commented Jul 17, 2025

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

The pull request introduces changes to use bootc install to deploy the container, which simplifies the image build process. There are a few critical issues in the YAML manifest related to copy-paste errors that lead to incorrect configurations for the 4k image builds and missing options for loopback devices. These issues need to be addressed.

@dustymabe
Copy link
Member

dustymabe commented Jul 17, 2025

I switched the CI on this to run against rawhide (contains python) so we could actually test the change.

@dustymabe
Copy link
Member

A few diffs picked up by cosa diff --metal from #4226

cosa-diff-metal.txt

We should probably profile each diff (maybe in coreos/fedora-coreos-tracker#1827) and evaluate whether it's a change we want to make or not.

@dustymabe
Copy link
Member

I can't get a built qemu image to boot. I suspect probably the root= and boot= UUIDs added on the kernel command line?

@jbtrystram
Copy link
Member Author

I can't get a built qemu image to boot. I suspect probably the root= and boot= UUIDs added on the kernel command line?

do you mind sharing more logs ? What I am getting locally is ignition failing on coreos/fedora-coreos-tracker#1250

@dustymabe
Copy link
Member

Ahh. I see that too now:

[    4.726843] ignition[875]: Ignition failed: failed to create users/groups: failed to configure users: failed to create user "core": exit status 10: Cmd: "useradd" "--root" "/sysroot" "--create-home" "--password" "*" "--comment" "CoreOS Admin" "--groups" "adm,sudo,systemd-journal,wheel" "core" Stdout: "" Stderr: "useradd: cannot lock /etc/group; try again later.\n"

@jbtrystram

This comment was marked as outdated.

@jbtrystram

This comment was marked as outdated.

@jbtrystram
Copy link
Member Author

I can't get a built qemu image to boot. I suspect probably the root= and boot= UUIDs added on the kernel command line?

looks like removing those make the boot process go further (ignition completes), and out of the initramfs but fail to mount the boot partition.

@jbtrystram
Copy link
Member Author

Blocked on bootc-dev/bootc#1441

@jbtrystram
Copy link
Member Author

ok this works with the following PRs :

for the bootc PR, it can be built then added into the image through overrides/rootfs. Make sure to build rawhide.

@jbtrystram
Copy link
Member Author

follow-up : either find a way to get the boot components inside cosa, or change the bootc code to call bootupd from the deployed root . I think the latter is preferable.
I filed bootc-dev/bootc#1455

@jbtrystram
Copy link
Member Author

jbtrystram commented Jul 29, 2025

follow-up : either find a way to get the boot components inside cosa, or change the bootc code to call bootupd from the deployed root . I think the latter is preferable. I filed bootc-dev/bootc#1455

Made bootc-dev/bootc#1460
With this, we no longer require to use the container as the buildroot, cosa works, so we could do that on all streams.

@jbtrystram jbtrystram force-pushed the osbuild-bootc-install-fs branch 4 times, most recently from bb4270f to 310bd60 Compare July 30, 2025 07:38
@jbtrystram
Copy link
Member Author

Alright, marking this as ready for review as all the bits are in place.
I guess i need to update the osbuild manifest or the other arches as well, but I'll do that after a review to reduce the amount of back and forth.

This will need a release of bootc.

@jbtrystram jbtrystram marked this pull request as ready for review July 30, 2025 07:44
Copy link
Member

@dustymabe dustymabe left a comment

Choose a reason for hiding this comment

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

Some comments.

I think there are a few things we need to iron out before we can really move forward with this:

  1. supporting both old and new paths at the same time

Do we need to? Usually when we make a change this large we roll it out slowly, which means we have to support both ways for some time.

This PR is ignoring that fact, but TBH looking at OSBuild configs that support both would be pretty intimidating, so I'm not excited about trying to do that either. I'd be interested in @jlebon or @travier's thoughts.

  1. We need to make sure any/every diff that exists between images generated this way and the old way are considered and acknowleged as acceptable before we'd make this change.

@jbtrystram
Copy link
Member Author

ext.config.boot.grub2-install is fixed with bootc-dev/bootc#1816 which basically replicates what we've been doing before in osbuild

@jbtrystram jbtrystram force-pushed the osbuild-bootc-install-fs branch from 01b2a13 to 4a85c6c Compare December 2, 2025 12:13
jbtrystram added a commit to jbtrystram/coreos-assembler that referenced this pull request Dec 2, 2025
this rpm provides locales under `/usr/share/locale`.
grub2 install these files inside the /boot partition using what
exist on the host. Mooving to bootc install results in an empty
folder because those files don't exist in the buildroot, so add them.

In the previous manifest we were using a chroot before calling bootupd
which made sure bootupd (and by extension grub2) would pull content
from the target root.

It would be nicer to have bootc install also chroot before calling
bootupd, it would have the added benefit to use the bootupd (and other)
binaries that are shipped on the image rather than what is in the buildroot.

Again, this is a complication coming from not having python in the image
so we can't use ourselves as the buildroot, which would alleviate a lot
of pain.

See coreos#4224 (comment)
And bootc-dev/bootc#1559
jbtrystram added a commit to jbtrystram/coreos-assembler that referenced this pull request Dec 3, 2025
this rpm provides locales under `/usr/share/locale`.
grub2 install these files inside the /boot partition using what
exist on the host. Mooving to bootc install results in an empty
folder because those files don't exist in the buildroot, so add them.

In the previous manifest we were using a chroot before calling bootupd
which made sure bootupd (and by extension grub2) would pull content
from the target root.

It would be nicer to have bootc install also chroot before calling
bootupd, it would have the added benefit to use the bootupd (and other)
binaries that are shipped on the image rather than what is in the buildroot.

Again, this is a complication coming from not having python in the image
so we can't use ourselves as the buildroot, which would alleviate a lot
of pain.

See coreos#4224 (comment)
And bootc-dev/bootc#1559
@jbtrystram jbtrystram force-pushed the osbuild-bootc-install-fs branch from 4a85c6c to d85142f Compare December 3, 2025 13:05
@jbtrystram
Copy link
Member Author

Rebased to drop the osbuild patch since my changes have landed in a release

@jbtrystram jbtrystram force-pushed the osbuild-bootc-install-fs branch from d85142f to b2bd8ef Compare January 14, 2026 14:21
jbtrystram added a commit to jbtrystram/coreos-assembler that referenced this pull request Jan 14, 2026
this rpm provides locales under `/usr/share/locale`.
grub2 install these files inside the /boot partition using what
exist on the host. Mooving to bootc install results in an empty
folder because those files don't exist in the buildroot, so add them.

In the previous manifest we were using a chroot before calling bootupd
which made sure bootupd (and by extension grub2) would pull content
from the target root.

It would be nicer to have bootc install also chroot before calling
bootupd, it would have the added benefit to use the bootupd (and other)
binaries that are shipped on the image rather than what is in the buildroot.

Again, this is a complication coming from not having python in the image
so we can't use ourselves as the buildroot, which would alleviate a lot
of pain.

See coreos#4224 (comment)
And bootc-dev/bootc#1559
@supakeen
Copy link

supakeen commented Jan 22, 2026

Right now this requires to use the image as the buildroot so this requires python (for osbuild). This is tracked in [1].

Just got there through another related PR and didn't read the entire backlog here so if I get this wrong let me know but:

It's possible to use a separate container as the buildroot. You can generate a manifest with:

image-builder manifest \
  --bootc-ref quay.io/fedora/fedora-bootc:43 \
  --bootc-build-ref quay.io/fedora/fedora-bootc:43 \
  --bootc-default-fs ext4 \
  qcow2

to see what that would look like (example uses Fedora 43 as it has bootc 1.12.1 which fixes some bugs) but it's basically a org.osbuild.container-deploy in the build pipeline :)

I don't know how useful that is to you since I seem to remember that CoreOS doesn't use the buildroot from osbuild itself but uses the host (which is itself a container) as the buildroot?

@jbtrystram
Copy link
Member Author

It's possible to use a separate container as the buildroot. You can generate a manifest with:

Thanks, that's a neat tip !

I don't know how useful that is to you since I seem to remember that CoreOS doesn't use the buildroot from osbuild itself but uses the host (which is itself a container) as the buildroot?

yes, we use coreos-assembler as the buildroot. This has several implications that still need to be solved in bootc :) One of them is that you need to read prepare-root.conf to set up the ostree repo, in which you will pull the image.

I don't know how useful that is to you since I seem to remember that CoreOS doesn't use the buildroot from osbuild itself but uses the host (which is itself a container) as the buildroot?

I'll give it a try :)

@jbtrystram jbtrystram force-pushed the osbuild-bootc-install-fs branch from b2bd8ef to 4a81e4e Compare February 16, 2026 14:07
jbtrystram added a commit to jbtrystram/coreos-assembler that referenced this pull request Feb 16, 2026
this rpm provides locales under `/usr/share/locale`.
grub2 install these files inside the /boot partition using what
exist on the host. Mooving to bootc install results in an empty
folder because those files don't exist in the buildroot, so add them.

In the previous manifest we were using a chroot before calling bootupd
which made sure bootupd (and by extension grub2) would pull content
from the target root.

It would be nicer to have bootc install also chroot before calling
bootupd, it would have the added benefit to use the bootupd (and other)
binaries that are shipped on the image rather than what is in the buildroot.

Again, this is a complication coming from not having python in the image
so we can't use ourselves as the buildroot, which would alleviate a lot
of pain.

See coreos#4224 (comment)
And bootc-dev/bootc#1559
Copy link
Member

@dustymabe dustymabe left a comment

Choose a reason for hiding this comment

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

Thanks for pushing this up hill for so long JB.

Since this PR has been open for a long time it might help to reset it by adding an initial commit that just copies the coreos.osbuild.x86_64.mpp.yaml to coreos.osbuild.x86_64.bootc.mpp.yaml and then apply your changes on top in later commits.

Eventually that initial commit would do the copy for all architectures, but for now just x86_64 would suffice.

(cd ${workdir}; bash ${tmp_builddir}/cmd.sh |& tee /dev/virtio-ports/cosa-cmdout) || rc=\$?
else
(cd ${workdir}; bash)
(cd ${workdir}; RUNVM_SHELL=${RUNVM_SHELL:-} bash)
Copy link
Member

Choose a reason for hiding this comment

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

I'm on the fence about this suggestion but it may be a little more obvious what this var is used for if we came up with a new var for it:

Suggested change
(cd ${workdir}; RUNVM_SHELL=${RUNVM_SHELL:-} bash)
(cd ${workdir}; RUNVM_INTERACTIVE=${RUNVM_SHELL:-} bash)

# cosa initialized dir and use `src/config`.
# We redirect the output to /dev/null to avoid the noisy `dirs` output.
set +u
pushd "${configdir:-src/config}" > /dev/null
Copy link
Member

Choose a reason for hiding this comment

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

honestly, even with your comment above I'm not sure I understand why using $configdir is needed here. This was clearly working before (only callers being in cmd-fetch and cmd-build) and cmd-osbuild doesn't call prepare_build, which is where $configdir gets set, right?

Copy link
Member Author

@jbtrystram jbtrystram Mar 2, 2026

Choose a reason for hiding this comment

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

because when called from the cmd-osbuild context, the current working directory is some temporary directory IIRC, so we need to move to $configdir to find the manifest.

Comment on lines -748 to -751
cat <<EOF >> "${vmpreparedir}/hostfiles"
/usr/lib/osbuild/stages/org.osbuild.coreos.live-artifacts.mono
/usr/lib/osbuild/stages/org.osbuild.coreos.live-artifacts.mono.meta.json
EOF
Copy link
Member

Choose a reason for hiding this comment

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

this was added in aea526e and should have been cleaned up long ago. Can you put it in a separate commit?

src/cmdlib.sh Outdated
Comment on lines 773 to 776
# Include arbitrary files from the host
# cat <<EOF >> "${vmpreparedir}/hostfiles"
# /usr/lib/osbuild/stages/org.osbuild.ln
# /usr/lib/osbuild/stages/org.osbuild.ln.meta.json
Copy link
Member

Choose a reason for hiding this comment

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

Can clean this up now the ln stage is in a release of osbuild and also included in the RPM.

Copy link
Member Author

Choose a reason for hiding this comment

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

I left it commented so it can be a reference to how someone can use this in the future

Copy link
Member Author

Choose a reason for hiding this comment

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

That was left before and helped me understand what i needed to do :)

partition:
mpp-format-int: '{image.layout[''boot''].partnum}'
target: /boot
- type: org.osbuild.ln
Copy link
Member

Choose a reason for hiding this comment

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

To me something like this begs for a comment. i.e. "For backwards compatibility..."

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes. That said it's worth discussing if we should drop that entirely. It's mostly used when debugging (and in some scripts, but checking for both is easy), so the name of the file doesn't matter too much

@jbtrystram
Copy link
Member Author

osbuild and bootc released all the changes we need for this. I am waiting a few days to get the RPMs in fedora and will update this, hopefully in it's almost final form :D

The log disk usage message comming every 10 seconds is quite noisy,
hide it when we are in a shell in osbuild.

I aslo added a couple of helpful tips in comments given by @dustymabe
to work with osbuild.
@jbtrystram jbtrystram force-pushed the osbuild-bootc-install-fs branch 2 times, most recently from 7169ace to 4b73ee0 Compare March 2, 2026 15:26
These have been released into osbuild ages ago so there is no need to
manually copy it into the supermin VM
Prep work to add a knob for using bootc install in osbuild.
Refactor the override logic in a helper function so we can easily add
those knobs down the line.
This is some scaffholding to be able to use another osbuild manifest.
This will allow to keep the legacy build path with a new path that
leverage bootc install to filesystem.
Right now the manifest is a copy of the existing x86 manifest to make
reviewing the following comments easier.
Instead of deploying the container to the tree then copy all the contents
to the disk image, use bootc to directly manage the installation to the
target filesystems.

We can keep the manifest duplicated until we are confident to roll this
to all streams or move to image-builder.

Requires:
bootc-dev/bootc#1460
bootc-dev/bootc#1451
osbuild/osbuild#2149
osbuild/osbuild#2152
bootc-dev/bootc#1978
bootc-dev/bootc#1909
Properly label the filesystem mount points before calling bootc,
otherwise `/sysroot` and `/boot` end up being `unlabeled_t`
Create symlinks to the aleph file created by bootc so our tests and
tooling find the aleph at the expected path.

Note that when moving to image-build we will likely move this to
an overlay in the config, that's way easier than having to wire up a
blueprint option to allow creating arbitrary symlinks.
Bootc is looking for the prepare-root config file in the buildroot
environnement because the main assumption is that it's run from the
target container.
However, in osbuild, it's run from te buildroot, because podman inside
bwrap (inside supermin in our case) causes issues.
It's fine for RHCOS and SCOS where we use the target container as the
buildroot but we cannot do that for FCOS because we require python in
the buildroot.

For now, insert a prepare-root file in the supermin VM (use as the
buildroot for osbuild) until either :
- bootc learn to look into the container for it [1]
- we ship python in our images and can use them as buildroot.

Another approach would be to layer python and the osbuild dependencies
on top of our image and use that as the buildroot, but that would create
room for packages drift (what was in the repos at build time?). At least
using COSA it's easier to keep track of versions.

[1] bootc-dev/bootc#1410
Add a bootc install config file[1] to set ostree repo options so we inject
the `grub_users` config on non-default entries.

[1] https://bootc-dev.github.io/bootc/man/bootc-install-config.5.html#ostree

See bootc-dev/bootc#1909
By default bootc calls bootups with the `--write-uuid` option that
write a stamp file with the boot partition UUID in the UEFI parition.
We want to restamp those UUID at first boot, so adding this option make
sure bootc does not pass that flag to bootupd.

See bootc-dev/bootc#1978
@jbtrystram jbtrystram force-pushed the osbuild-bootc-install-fs branch from 4b73ee0 to dfe14ee Compare March 2, 2026 15:52
@openshift-ci
Copy link

openshift-ci bot commented Mar 2, 2026

@jbtrystram: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/rhcos c10da62 link true /test rhcos

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants