Skip to content

WIP: Changes for booting composefs native systems#3874

Open
Johan-Liebert1 wants to merge 6 commits into
coreos:testing-develfrom
Johan-Liebert1:bootc-composefs
Open

WIP: Changes for booting composefs native systems#3874
Johan-Liebert1 wants to merge 6 commits into
coreos:testing-develfrom
Johan-Liebert1:bootc-composefs

Conversation

@Johan-Liebert1

@Johan-Liebert1 Johan-Liebert1 commented Nov 10, 2025

Copy link
Copy Markdown
Member

I don't believe what we have here would be the final product. But this might be a good starting point

@Johan-Liebert1 Johan-Liebert1 added the WIP PR still being worked on label Nov 10, 2025
@@ -0,0 +1,4 @@
# Disable services that don't work with bootc/composefs

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should probably add a condition to those unit that makes them not run on composefs native systems.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, that would be better

@@ -0,0 +1,9 @@
[Unit]
After=
After=bootc-initramfs-setup.service

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

An option here could be to create a wrapping unit/script that runs the right command depending on the kernel parameter, to avoid duplicating everything.

@@ -0,0 +1,10 @@
[Unit]
ConditionKernelCommandLine=

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's see if we can figure out a way to include both condition in the unit:

If multiple conditions are specified, the unit will be executed if all of them apply (i.e. a logical AND is applied). Condition checks can use a pipe symbol ("|") after the equals sign ("Condition…=|…"), which causes the condition to become a triggering condition. If at least one triggering condition is defined for a unit, then the unit will be started if at least one of the triggering conditions of the unit applies and all of the regular (i.e. non-triggering) conditions apply. If you prefix an argument with the pipe symbol and an exclamation mark, the pipe symbol must be passed first, the exclamation second. If any of these options is assigned the empty string, the list of conditions is reset completely, all previous condition settings (of any kind) will have no effect.

https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html#Conditions%20and%20Asserts

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah that would the way to do it. I have it in separate drop-ins right now just to keep track of what all I'm changing

@@ -0,0 +1,21 @@
[Unit]
Description=bootc setup root

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We definitely have the dracut module now this shouldn't be necessary

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@cgwalters

Copy link
Copy Markdown
Member

Chatting about confidential computing and stuff so this doesn't get lost: I think we are also going to need to support setting up dm-integrity

@cgwalters

Copy link
Copy Markdown
Member

Also I just want to say here: I have come to the conclusion that I made a mistake in trying to create a stronger conceptual separation between "image mode/bootc" vs "coreos" - especially with respect to Ignition. It's of course very complicated because there was a rationale for that - integration with Anaconda unlocked a lot of use cases.

But still..I think we should prioritize the combined teams working on this PR and making the whole thing feel seamless. I know parts of it have been happening, but there's so much more to do (especially things like zincati -> bootc etc).

And a big goal should be "sealed FCOS" w/UKI.

@travier

travier commented Mar 17, 2026

Copy link
Copy Markdown
Member

Chatting about confidential computing and stuff so this doesn't get lost: I think we are also going to need to support setting up dm-integrity

I think that should be set up by the Ignition config?

@Johan-Liebert1 Johan-Liebert1 force-pushed the bootc-composefs branch 2 times, most recently from 4b2daa1 to 7748249 Compare March 24, 2026 12:37
Description=CoreOS Root Setup
Documentation=man:bootc(1)
DefaultDependencies=no
ConditionKernelCommandLine=|composefs

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ideally...we don't hardcode this because I'd like the ability to change it in the future. That already came up because e.g. not having a . makes the Linux kernel emit a warning i.e. I'd like to switch to composefs.digest or so.

But also, maybe we actually switch to key based mounting per composefs/composefs-rs#226

So...how about ConditionPathExists=|/sysroot/composefs ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

So...how about ConditionPathExists=|/sysroot/composefs ?

This sounds good to me, but I don't know if systemd will OR this with the kernel cmdline condition. I'll need to check

@@ -0,0 +1,32 @@
#!/bin/bash

XBOOTLDR_UUID="BC13C2FF-59E6-4262-A352-B275FD6F7172"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hmm it'd be nice to not write new load-bearing bash code run as root. In this case...can't the GPT auto generator mount this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

can't the GPT auto generator mount this?

Yes, it could, and would mount /boot if the partuuid follows DPS, which it does after my other PR. This was mainly supposed to be a sync target for a lot of other services that depend on a boot partition being present.

fi

echo "Enabling fs-verity again..."
find /sysroot/composefs/objects -type f -exec fsverity enable {} --hash-alg $hash_alg \;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Eeek. This is another thing exactly like ostreedev/ostree#3094

I think at a minimum we could put this in rust in the bootc initramfs setup like bootc-initramfs-setup post-copy /sysroot/composefs ?

Also note that once we have composefs/composefs-rs#268 then the tooling itself will immediately know the expected digest size just looking at the repo.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think at a minimum we could put this in rust in the bootc initramfs setup like bootc-initramfs-setup post-copy /sysroot/composefs ?

agreed. That would be much cleaner

And yes, repo metdata would help here

@@ -0,0 +1,21 @@
[Unit]
Description=CoreOS Root Setup

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hmm this is effectively a generic synchronization point between "ostree or composefs" right? I think we could just add this to bootc upstream as say bootc-root-setup.target - which then we ensure via a generator depends on the right service.

The bash code executed here is just reimplementing the upstream services which I think we don't want.

Description=Ignition OSTree: Grow Root Filesystem
DefaultDependencies=false
ConditionKernelCommandLine=ostree
ConditionKernelCommandLine=|ostree

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I said something like this before in a different PR on this repo but I think this would be a good time to change our logic so that we don't depend on the specific kernel command line at all.

One way we could handle this is in the initramfs we introduce /run/bootc-requested which we synthesize from a generator (like /run/ostree-booted). I think this should only go into the initramfs (unlike the ostree one) because right now we have another way to detect composefs (look at the mount source for /) and anyways the post-boot code should largely be talking to bootc anyways.

This /run/bootc-requested is something we could again do in bootc upstream right now.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Discussed this in a 1-1 call. This is a good to have, but not a blocker for now

@Johan-Liebert1 Johan-Liebert1 marked this pull request as ready for review March 25, 2026 11:07
@Johan-Liebert1 Johan-Liebert1 force-pushed the bootc-composefs branch 2 times, most recently from 234f8be to ef74394 Compare March 26, 2026 06:01
@cgwalters

Copy link
Copy Markdown
Member

Also xref systemd/systemd#29731 - i'd like to opitmize the LUKS-without-filesyostem change case.

Replace direct boot device dependencies (dev-disk-by-label-boot.device)
with a new boot partition discovery mechanism across multiple services:

- Add boot-part-discovery.service and boot-part-discovered.target to
dynamically detect XBOOTLDR partition availability
- Update ignition-ostree services to use conditional boot partition
dependencies instead of hard requirements
- Add composefs condition support to ignition-ostree services
- Update coreos-boot-mount-generator to respect boot partition status

This change is needed for booting composefs systems with ignition as
not all composefs systems will have a boot parition

Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Add override for systemd-fsck@dev-disk-by\x2dlabel-boot so that it'll
only run after boot-part-discovered.target and the file
/run/coreos/boot-partition-status is not empty, i.e. only run the
service if boot partition exists

Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
systemd will still wait for /dev/disk/by-label/boot if we have it in the
Mount section even if we don't have a boot partition

Refactor boot-part-discovery.sh to have a `boot_part_exists` function so
that we can source the script and use it in a bunch of other places

Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
We need a single service that would handle the /sysroot mount for
ostree backend and for composefs backend. This service does that.
Depending upon the kernel cmdline, it would either proxy to ostree or
bootc

Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
Run transposefs services for composefs systems as well by adding
"composefs" as a commandline condition

In "restore" option make sure to re-enable fsverity on the composefs
objects if the kernel commandlne enforces fsverity, i.e. doesn't have
"?" before the fsverity digest

Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
We now will have quite a few combinations that need to be taken care of
after ignition's first boot. Update the ignition-firstboot-complete
script to handle these cases, viz systemd-boot BLS, systemd-boot UKI,
grub UKI and grub BLS.

The UKI cases are pretty simple and consist of only removing one single
UKI addon.

The grub BLS case does not change and we still just remove
/boot/ignition.firstboot

For systemd-boot BLS, we manually remove `ignition.firstboot` from BLS
config file

Signed-off-by: Pragyan Poudyal <pragyanpoudyal41999@gmail.com>
@@ -306,9 +306,32 @@ case "${1:-}" in
if [ -d "${saved_root}" ]; then
echo "Restoring rootfs from RAM..."
mount_and_restore_filesystem_by_label root /sysroot "${saved_root}"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Discussing this live:

For the sealed UKI case let's say we want to do the DPS. Then probably we should detect whether the disk has the DPS root UUID and if the bootloader set the BLI variable.

I think we could make this a clean distinct prep commit right? Basically "support DPS booting".

Questions:

  • Will we need to suppress the generator and redo what it's doing for the Ignition transposefs case? Though this relates to a systemd PR around optimizing the cryptsetup case when we don't need to reinitialize the partition table for the root at all.

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

Labels

WIP PR still being worked on

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants