From 3c75c5a1aba93027f106fdf24a089bf5acbffd1d Mon Sep 17 00:00:00 2001 From: Pragyan Poudyal Date: Thu, 14 May 2026 12:25:09 +0530 Subject: [PATCH 1/6] ukify: Allow passing custom kernel, initramfs While building a sealed UKI image we'd want to remove the original kernel + initramfs from the final image and have only the final UKI present. This was not possible before as `bootc container ukify` expected kernel + initramfs to be present in `usr/lib/modules` of container root Fixes: #2185 Signed-off-by: Pragyan Poudyal Mark `bootc container ukify` without `--kernel` and `--initramfs` as deprecated --- crates/lib/src/cli.rs | 38 +++++++++++++++++ crates/lib/src/ukify.rs | 54 ++++++++++++++++--------- docs/src/man/bootc-container-ukify.8.md | 12 ++++++ 3 files changed, 86 insertions(+), 18 deletions(-) diff --git a/crates/lib/src/cli.rs b/crates/lib/src/cli.rs index dd80fd6ad..9275db060 100644 --- a/crates/lib/src/cli.rs +++ b/crates/lib/src/cli.rs @@ -442,6 +442,19 @@ pub(crate) enum ContainerOpts { #[clap(long)] write_dumpfile_to: Option, + /// The kernel version. + /// Required if kernel is passed + #[clap(long, requires = "kernel")] + kver: Option, + + /// Path to the kernel + #[clap(long, requires = "initramfs", requires = "kver")] + kernel: Option, + + /// Path to the initramfs + #[clap(long, requires = "kernel")] + initramfs: Option, + /// Additional arguments to pass to ukify (after `--`). #[clap(last = true)] args: Vec, @@ -1902,12 +1915,37 @@ async fn run_from_opt(opt: Opt) -> Result<()> { kargs, allow_missing_verity, write_dumpfile_to, + kernel, + kver, + initramfs, args, } => { + let kernel = match (kernel, initramfs) { + (Some(path), Some(initramfs)) => Some(crate::kernel::KernelInternal { + kernel: crate::kernel::Kernel { + unified: false, + version: kver + .ok_or_else(|| anyhow::anyhow!("Expected kver to be present"))?, + }, + k_type: crate::kernel::KernelType::Vmlinuz { path, initramfs }, + }), + + (None, None) => { + eprintln!( + "Warning: `bootc container ukify` without --kernel and --initramfs parameters is deprecated and will be removed in a future version" + ); + None + } + + // Shouldn't happen due to clap constraints but for sanity + _ => anyhow::bail!("--kernel and --initramfs must be provided together"), + }; + crate::ukify::build_ukify( &rootfs, &kargs, &args, + kernel, allow_missing_verity, write_dumpfile_to.as_deref(), ) diff --git a/crates/lib/src/ukify.rs b/crates/lib/src/ukify.rs index c36cdb360..06008e7ef 100644 --- a/crates/lib/src/ukify.rs +++ b/crates/lib/src/ukify.rs @@ -15,6 +15,7 @@ use fn_error_context::context; use crate::bootc_composefs::digest::compute_composefs_digest; use crate::bootc_composefs::status::ComposefsCmdline; +use crate::kernel::KernelInternal; /// Build a UKI from the given rootfs. /// @@ -30,6 +31,7 @@ pub(crate) async fn build_ukify( rootfs: &Utf8Path, extra_kargs: &[String], args: &[OsString], + kernel: Option, allow_missing_fsverity: bool, write_dumpfile_to: Option<&Utf8Path>, ) -> Result<()> { @@ -52,12 +54,14 @@ pub(crate) async fn build_ukify( let root = Dir::open_ambient_dir(rootfs, cap_std_ext::cap_std::ambient_authority()) .with_context(|| format!("Opening rootfs {rootfs}"))?; - // Find the kernel - let kernel = crate::kernel::find_kernel(&root)? - .ok_or_else(|| anyhow::anyhow!("No kernel found in {rootfs}"))?; + let kernel_final = match kernel { + Some(ref kernel) => kernel, + None => &crate::kernel::find_kernel(&root)? + .ok_or_else(|| anyhow::anyhow!("No kernel found in {rootfs}"))?, + }; // Extract vmlinuz and initramfs paths, or bail if this is already a UKI - let (vmlinuz_path, initramfs_path) = match kernel.k_type { + let (vmlinuz_path, initramfs_path) = match &kernel_final.k_type { crate::kernel::KernelType::Vmlinuz { path, initramfs } => (path, initramfs), crate::kernel::KernelType::Uki { path, .. } => { anyhow::bail!("Cannot build UKI: rootfs already contains a UKI at {path}"); @@ -65,17 +69,31 @@ pub(crate) async fn build_ukify( }; // Verify kernel and initramfs exist - if !root - .try_exists(&vmlinuz_path) - .context("Checking for vmlinuz")? - { - anyhow::bail!("Kernel not found at {vmlinuz_path}"); - } - if !root - .try_exists(&initramfs_path) - .context("Checking for initramfs")? - { - anyhow::bail!("Initramfs not found at {initramfs_path}"); + // + // NOTE: Not using cap_std here as the vmlinuz/initramfs path from + // args can be outside of "rootfs" + if kernel.is_some() { + if !vmlinuz_path.exists() { + anyhow::bail!("Kernel not found at {vmlinuz_path}"); + } + + if !initramfs_path.exists() { + anyhow::bail!("Initramfs not found at {initramfs_path}"); + } + } else { + if !root + .try_exists(&vmlinuz_path) + .context("Checking for vmlinuz")? + { + anyhow::bail!("Kernel not found at {vmlinuz_path}"); + } + + if !root + .try_exists(&initramfs_path) + .context("Checking for initramfs")? + { + anyhow::bail!("Initramfs not found at {initramfs_path}"); + } } // Compute the composefs digest @@ -105,7 +123,7 @@ pub(crate) async fn build_ukify( .arg("--initrd") .arg(&initramfs_path) .arg("--uname") - .arg(&kernel.kernel.version) + .arg(&kernel_final.kernel.version) .arg("--cmdline") .arg(&cmdline_str) .arg("--os-release") @@ -132,7 +150,7 @@ mod tests { let tempdir = tempfile::tempdir().unwrap(); let path = Utf8Path::from_path(tempdir.path()).unwrap(); - let result = build_ukify(path, &[], &[], false, None).await; + let result = build_ukify(path, &[], &[], None, false, None).await; assert!(result.is_err()); let err = format!("{:#}", result.unwrap_err()); assert!( @@ -150,7 +168,7 @@ mod tests { fs::create_dir_all(tempdir.path().join("boot/EFI/Linux")).unwrap(); fs::write(tempdir.path().join("boot/EFI/Linux/test.efi"), b"fake uki").unwrap(); - let result = build_ukify(path, &[], &[], false, None).await; + let result = build_ukify(path, &[], &[], None, false, None).await; assert!(result.is_err()); let err = format!("{:#}", result.unwrap_err()); assert!( diff --git a/docs/src/man/bootc-container-ukify.8.md b/docs/src/man/bootc-container-ukify.8.md index bad9e10cc..b77f37b0f 100644 --- a/docs/src/man/bootc-container-ukify.8.md +++ b/docs/src/man/bootc-container-ukify.8.md @@ -35,6 +35,18 @@ Any additional arguments after `--` are passed through to ukify unchanged. Write a dumpfile to this path +**--kver**=*KVER* + + The kernel version. Required if kernel is passed + +**--kernel**=*KERNEL* + + Path to the kernel + +**--initramfs**=*INITRAMFS* + + Path to the initramfs + # EXAMPLES From 0c291cdcc1a340b97b5cca26752121c8ee7ecf6c Mon Sep 17 00:00:00 2001 From: Pragyan Poudyal Date: Thu, 14 May 2026 21:13:52 +0530 Subject: [PATCH 2/6] dockerfile/uki: Rework to remove kernel + initrd Now that we can pass kernel and initrd paths to `bootc ukify`, rework our UKI Dockerfile to remove kernel + initrd from the final layer and only keep the UKI This still will not *remove* the kernel + initrd from the tarball but have whiteout instead See https://github.com/bootc-dev/bootc/issues/2027#issuecomment-4244181869 Signed-off-by: Pragyan Poudyal --- Dockerfile | 46 +++++++-- contrib/packaging/finalize-uki | 15 +-- contrib/packaging/seal-uki | 98 ++++++++++++++----- crates/tests-integration/src/container.rs | 2 + tmt/tests/Dockerfile.upgrade | 34 ++++++- tmt/tests/booted/tap.nu | 28 +++++- .../test-install-to-filesystem-var-mount.sh | 55 ++++++++--- 7 files changed, 206 insertions(+), 72 deletions(-) diff --git a/Dockerfile b/Dockerfile index 31f515800..58e32e49d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -83,7 +83,7 @@ RUN --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \ # Install systemd-ukify and systemd-boot for UKIs # This also installs systemd-boot for the grub UKI case which is not ideal... if [[ "${boot_type}" == "uki" ]]; then - pkgs_to_install+=(systemd-ukify) + pkgs_to_install+=(systemd-ukify binutils) fi if [[ ${#pkgs_to_install[@]} -gt 0 ]]; then @@ -135,7 +135,10 @@ ARG pkgversion ARG SOURCE_DATE_EPOCH ENV SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} # Build RPM directly from source, using cached target directory -RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp --mount=type=cache,target=/src/target --mount=type=cache,target=/var/roothome RPM_VERSION="${pkgversion}" /src/contrib/packaging/build-rpm +RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \ + --mount=type=cache,target=/src/target \ + --mount=type=cache,target=/var/roothome \ + RPM_VERSION="${pkgversion}" /src/contrib/packaging/build-rpm # Build a systemd-sysext containing just the bootc binary. # Skips RPM machinery entirely for fast incremental rebuilds. @@ -218,7 +221,7 @@ COPY --from=update-generated-from-code /src/docs/src/*.schema.json /docs/src/ # ---- # Perform all filesystem transformations except generating the sealed UKI (if configured) -FROM base as base-penultimate +FROM base as base-penultimate-source ARG variant ARG bootloader ARG boot_type @@ -247,6 +250,10 @@ rm -rf /var/cache rm -rf /run/rhsm EORUN + +FROM base-penultimate-source as base-penultimate +ARG boot_type + # Configure the rootfs ARG rootfs="" RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \ @@ -265,9 +272,19 @@ RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp COPY --from=packaging /usr-extras/ /usr/ # Clean up package manager caches RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \ - --mount=type=bind,from=packaging,src=/,target=/run/packaging \ + --mount=type=bind,from=base-penultimate-source,src=/,target=/run/base-penultimate-src \ + --mount=type=bind,from=packaging,src=/,target=/run/packaging <&2 - exit 1 -fi +kver=$1 +shift # Create the EFI directory structure mkdir -p /boot/EFI/Linux @@ -36,12 +31,6 @@ mkdir -p /boot/EFI/Linux target=/boot/EFI/Linux/${kver}.efi cp "${uki_src}/${kver}.efi" "${target}" -# Remove the raw kernel and initramfs since we're using a UKI now. -# NOTE: We intentionally keep these for now until bcvk is updated to extract -# kernel/initramfs from UKIs in subdirectories. Once bcvk PR #144 is fixed -# to look for .efi files in /usr/lib/modules//, we can uncomment this. -# rm -v "/usr/lib/modules/${kver}/vmlinuz" "/usr/lib/modules/${kver}/initramfs.img" - # NOTE: We used to create a symlink from /usr/lib/modules/${kver}/${kver}.efi to the UKI # for tooling compatibility. However, composefs-boot's find_uki_components() doesn't # handle symlinks correctly and fails with "is not a regular file". The UKI is already diff --git a/contrib/packaging/seal-uki b/contrib/packaging/seal-uki index 66de92ffd..c493aeeb4 100755 --- a/contrib/packaging/seal-uki +++ b/contrib/packaging/seal-uki @@ -2,32 +2,82 @@ # Generate a sealed UKI with embedded composefs digest set -xeuo pipefail -# Path to the desired root filesystem -target=$1 -shift -# Write to this directory -output=$1 -shift -# Path to secrets directory -secrets=$1 -shift -allow_missing_verity=$1 -shift -seal_state=$1 -shift - -if [[ $seal_state == "sealed" && $allow_missing_verity == "true" ]]; then +missing_verity=() + +while [ ! -z "${1:-}" ]; do + case "$1" in + # Path to the desired root filesystem + "--target") + target="$2" + shift + shift + ;; + + # Write to this directory + "--output") + output="$2" + shift + shift + ;; + + # Path to secrets directory + "--secrets") + secrets="$2" + shift + shift + ;; + + "--allow-missing-verity") + missing_verity=(--allow-missing-verity) + shift + ;; + + "--seal-state") + seal_state="$2" + shift + shift + ;; + + # The kernel version + "--kver") + kver="$2" + shift + shift + ;; + + # Path to the kernel + "--kernel") + kernel="$2" + shift + shift + ;; + + # Path to the initrd + "--initramfs") + initramfs="$2" + shift + shift + ;; + + * ) + echo "Argument $1 not understood" + exit 1 + ;; + esac +done + +if [[ $seal_state == "sealed" && ${#missing_verity[@]} -gt 0 ]]; then echo "Cannot have missing verity with sealed UKI" >&2 exit 1 fi -# Find the kernel version (needed for output filename) -kver=$(bootc container inspect --rootfs "${target}" --json | jq -r '.kernel.version') -if [ -z "$kver" ] || [ "$kver" = "null" ]; then - echo "Error: No kernel found" >&2 - exit 1 +if [[ -z $kernel || -z $initramfs || -z $kver ]]; then + echo "kernel, initramfs and kver are required" >&2 + exit 1 fi +kernel_params=(--kernel "$kernel" --initramfs "$initramfs" --kver "$kver") + mkdir -p "${output}" # Baseline ukify options @@ -45,12 +95,6 @@ fi # Baseline container ukify options containerukifyargs=(--rootfs "${target}") -missing_verity=() - -if [[ $allow_missing_verity == "true" ]]; then - missing_verity+=(--allow-missing-verity) -fi - # Build the UKI using bootc container ukify # This computes the composefs digest, reads kargs from kargs.d, and invokes ukify -bootc container ukify "${containerukifyargs[@]}" "${missing_verity[@]}" -- "${ukifyargs[@]}" +bootc container ukify "${containerukifyargs[@]}" "${kernel_params[@]}" "${missing_verity[@]}" -- "${ukifyargs[@]}" diff --git a/crates/tests-integration/src/container.rs b/crates/tests-integration/src/container.rs index a7d8e89d6..b03a69f58 100644 --- a/crates/tests-integration/src/container.rs +++ b/crates/tests-integration/src/container.rs @@ -51,6 +51,8 @@ pub(crate) fn test_bootc_container_inspect() -> Result<()> { .as_bool() .expect("kernel.unified should be a boolean"); + println!("kernel: {kernel:#?}"); + let is_uki = std::env::var("BOOTC_boot_type").is_ok_and(|var| var == "uki"); if let Some(variant) = std::env::var("BOOTC_variant").ok() { diff --git a/tmt/tests/Dockerfile.upgrade b/tmt/tests/Dockerfile.upgrade index 561e2e0a7..02e50e3ac 100644 --- a/tmt/tests/Dockerfile.upgrade +++ b/tmt/tests/Dockerfile.upgrade @@ -13,6 +13,16 @@ ARG filesystem=ext4 FROM scratch AS packaging COPY contrib/packaging / +# Get kernel + initrd from the UKI +FROM localhost/bootc as kernel +ARG boot_type +RUN <<-EOF + if test "${boot_type}" = "uki"; then + objcopy -O binary --only-section=.initrd /boot/EFI/Linux/*.efi /boot/initramfs.img + objcopy -O binary --only-section=.linux /boot/EFI/Linux/*.efi /boot/vmlinuz + fi +EOF + # Create the upgrade content (a simple marker file). # For UKI builds, we also remove the existing UKI so that seal-uki can # regenerate it with the correct composefs digest for this derived image. @@ -36,16 +46,28 @@ RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp --mount=type=secret,id=secureboot_key \ --mount=type=secret,id=secureboot_cert \ --mount=type=bind,from=packaging,src=/,target=/run/packaging \ + --mount=type=bind,from=kernel,src=/,target=/run/kernel \ --mount=type=bind,from=upgrade-base,src=/,target=/run/target <> /tmp/Containerfile.drop-lbis <<-EOF - FROM base as base-final - RUN rm -rf /boot/EFI/Linux/*.efi + allow_missing_verity=() - FROM base as sealed-uki - RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \ - --mount=type=bind,from=base-final,src=/,target=/run/target \ - /usr/bin/seal-uki /run/target /out /run/secrets $allow_missing_verity $seal_state + if [[ "$(bootc status --json | jq -r '.status.booted.composefs.missingVerityAllowed')" == "true" ]]; then + allow_missing_verity=("--allow-missing-verity") + fi - FROM base-final + seal_state="unsealed" - # Copy the sealed UKI and finalize the image remove raw kernel, create symlinks - RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \ - --mount=type=bind,from=sealed-uki,src=/,target=/run/sealed-uki \ - /usr/bin/finalize-uki /run/sealed-uki/out + cat >> /tmp/Containerfile.drop-lbis <<-EOF +FROM base as kernel +RUN <<-RUNEOF + objcopy -O binary --only-section=.initrd /boot/EFI/Linux/*.efi /boot/initramfs.img + objcopy -O binary --only-section=.linux /boot/EFI/Linux/*.efi /boot/vmlinuz +RUNEOF + +FROM base as base-final +RUN rm -rf /boot/EFI/Linux/*.efi + +FROM base as sealed-uki +RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \ + --mount=type=bind,from=kernel,src=/,target=/run/kernel \ + --mount=type=bind,from=base-final,src=/,target=/run/target < Date: Fri, 15 May 2026 12:51:30 +0530 Subject: [PATCH 3/6] test/integration: Test vmlinuz non-existence with UKI vmlinuz and intrd should not be present in UKI images; add test for the same Signed-off-by: Pragyan Poudyal --- crates/tests-integration/src/container.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/crates/tests-integration/src/container.rs b/crates/tests-integration/src/container.rs index b03a69f58..57dc3af1d 100644 --- a/crates/tests-integration/src/container.rs +++ b/crates/tests-integration/src/container.rs @@ -1,8 +1,8 @@ use indoc::indoc; use scopeguard::defer; use serde::Deserialize; -use std::fs; use std::process::Command; +use std::{fs, path::Path}; use anyhow::{Context, Result}; use camino::Utf8Path; @@ -51,8 +51,6 @@ pub(crate) fn test_bootc_container_inspect() -> Result<()> { .as_bool() .expect("kernel.unified should be a boolean"); - println!("kernel: {kernel:#?}"); - let is_uki = std::env::var("BOOTC_boot_type").is_ok_and(|var| var == "uki"); if let Some(variant) = std::env::var("BOOTC_variant").ok() { @@ -74,6 +72,18 @@ pub(crate) fn test_bootc_container_inspect() -> Result<()> { ); // Version should be non-empty after stripping extension assert!(!version.is_empty(), "version should not be empty for UKI"); + + // For UKI make sure vmlinuz + initrd don't exist + let usr_lib_mod = Path::new("/usr/lib/modules").join(version); + assert!(usr_lib_mod.exists(), "'{usr_lib_mod:?}' does not exist"); + assert!( + !usr_lib_mod.join("vmlinuz").exists(), + "vmlinuz should not exist for UKI" + ); + assert!( + !usr_lib_mod.join("initramfs.img").exists(), + "initramfs should not exist for UKI" + ); } o => eprintln!("notice: Unhandled variant for kernel check: {o:?}"), } From f4fb7b991f73b7b55c1876980e2d544c58d860bc Mon Sep 17 00:00:00 2001 From: Pragyan Poudyal Date: Mon, 18 May 2026 12:57:33 +0530 Subject: [PATCH 4/6] test/tmt: Don't run bootloader-none test for composefs Bootloader set to none is not supported with the composefs backend so we skip tests with this option for composefs backend Signed-off-by: Pragyan Poudyal --- tmt/plans/integration.fmf | 2 ++ tmt/tests/booted/test-install-bootloader-none.nu | 5 ++++- tmt/tests/booted/test-install-no-boot-dir.nu | 9 +++++++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/tmt/plans/integration.fmf b/tmt/plans/integration.fmf index b3366648b..9830acd87 100644 --- a/tmt/plans/integration.fmf +++ b/tmt/plans/integration.fmf @@ -217,6 +217,7 @@ execute: how: fmf test: - /tmt/tests/tests/test-37-install-no-boot-dir + extra-fixme_skip_if_composefs: true /plan-37-upgrade-check-status: summary: Verify upgrade --check populates cached update in status @@ -232,6 +233,7 @@ execute: how: fmf test: - /tmt/tests/tests/test-38-install-bootloader-none + extra-fixme_skip_if_composefs: true /plan-39-upgrade-tag: summary: Test bootc upgrade --tag functionality with containers-storage diff --git a/tmt/tests/booted/test-install-bootloader-none.nu b/tmt/tests/booted/test-install-bootloader-none.nu index ef89deae7..ab36260e6 100644 --- a/tmt/tests/booted/test-install-bootloader-none.nu +++ b/tmt/tests/booted/test-install-bootloader-none.nu @@ -2,7 +2,10 @@ # tmt: # summary: Test bootc install with --bootloader=none # duration: 30m -# +# extra: +# # bootloader=none is not supported for composefs +# fixme_skip_if_composefs: true + use std assert use tap.nu diff --git a/tmt/tests/booted/test-install-no-boot-dir.nu b/tmt/tests/booted/test-install-no-boot-dir.nu index bc012fd66..82494abb5 100644 --- a/tmt/tests/booted/test-install-no-boot-dir.nu +++ b/tmt/tests/booted/test-install-no-boot-dir.nu @@ -2,7 +2,12 @@ # tmt: # summary: Test bootc install to-filesystem without /boot directory # duration: 30m -# +# extra: +# # bootloader=none is not supported for composefs and this test fails +# # when trying to install bootloader for composefs. For ostree, the +# # bootloader installation is simply skipped +# fixme_skip_if_composefs: true + use std assert use tap.nu @@ -19,7 +24,7 @@ def main [] { mount -o loop disk.img /var/mnt setenforce 0 - + tap run_install $"bootc install to-filesystem --disable-selinux --bootloader=none --source-imgref ($target_image) /var/mnt" umount /var/mnt From fa0221b0ba6a44ab36db9a0376b754a8989cb25f Mon Sep 17 00:00:00 2001 From: Pragyan Poudyal Date: Tue, 19 May 2026 14:45:09 +0530 Subject: [PATCH 5/6] image-proxy: Use privileged user when pull from containers storage We were defaulting to unprivileged user "nobody" when pulling an image, but pulling from containers-storage was failing as it requires extra privileges. Default to the current user, usually root, when pulling from containers-storage Signed-off-by: Pragyan Poudyal --- crates/lib/src/bootc_composefs/status.rs | 13 ++++++++----- crates/lib/src/bootc_composefs/update.rs | 2 +- crates/lib/src/install.rs | 3 +-- crates/ostree-ext/src/container/mod.rs | 14 ++++++++++++++ crates/ostree-ext/src/container/store.rs | 8 +------- 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/crates/lib/src/bootc_composefs/status.rs b/crates/lib/src/bootc_composefs/status.rs index ac1b261dd..49a6349c8 100644 --- a/crates/lib/src/bootc_composefs/status.rs +++ b/crates/lib/src/bootc_composefs/status.rs @@ -36,7 +36,8 @@ use bootc_utils::try_deserialize_timestamp; use cap_std_ext::{cap_std::fs::Dir, dirext::CapStdExtDirExt}; use ostree_container::OstreeImageReference; use ostree_ext::container::{self as ostree_container}; -use ostree_ext::containers_image_proxy; +use ostree_ext::containers_image_proxy::{ImageProxy, ImageReference}; + use ostree_ext::oci_spec; use ostree_ext::{container::deploy::ORIGIN_CONTAINER, oci_spec::image::ImageConfiguration}; @@ -379,14 +380,16 @@ pub(crate) fn list_bootloader_entries(storage: &Storage) -> Result Result { let mut config = crate::deploy::new_proxy_config(); - ostree_ext::container::merge_default_container_proxy_opts(&mut config)?; - let proxy = containers_image_proxy::ImageProxy::new_with_config(config).await?; + + ostree_ext::container::apply_container_proxy_opts_for_transport(&mut config, imgref.transport)?; + + let proxy = ImageProxy::new_with_config(config).await?; let img = proxy - .open_image(&imgref) + .open_image_ref(&imgref) .await .with_context(|| format!("Opening image {imgref}"))?; diff --git a/crates/lib/src/bootc_composefs/update.rs b/crates/lib/src/bootc_composefs/update.rs index a1fb2722f..79c823159 100644 --- a/crates/lib/src/bootc_composefs/update.rs +++ b/crates/lib/src/bootc_composefs/update.rs @@ -58,7 +58,7 @@ pub(crate) async fn is_image_pulled( imgref: &ImageReference, ) -> Result<(Option, ImgConfigManifest)> { let imgref_repr = imgref.to_image_proxy_ref()?; - let img_config_manifest = get_container_manifest_and_config(&imgref_repr.to_string()).await?; + let img_config_manifest = get_container_manifest_and_config(&imgref_repr).await?; let img_digest = img_config_manifest.manifest.config().digest().digest(); diff --git a/crates/lib/src/install.rs b/crates/lib/src/install.rs index c9fcaf88c..d49c6a350 100644 --- a/crates/lib/src/install.rs +++ b/crates/lib/src/install.rs @@ -2017,8 +2017,7 @@ async fn install_to_filesystem_impl( // Pre-flight disk space check for native composefs install path. { let imgref = &state.source.imageref; - let imgref_repr = imgref.to_string(); - let img_manifest_config = get_container_manifest_and_config(&imgref_repr).await?; + let img_manifest_config = get_container_manifest_and_config(&imgref).await?; crate::store::ensure_composefs_dir(&rootfs.physical_root)?; // Use init_path since the repo may not exist yet during install let (cfs_repo, _created) = crate::store::ComposefsRepository::init_path( diff --git a/crates/ostree-ext/src/container/mod.rs b/crates/ostree-ext/src/container/mod.rs index 3419bdf82..e73361852 100644 --- a/crates/ostree-ext/src/container/mod.rs +++ b/crates/ostree-ext/src/container/mod.rs @@ -496,6 +496,20 @@ pub fn version_for_config(config: &oci_spec::image::ImageConfiguration) -> Optio None } +/// Apply appropriate container proxy options based on transport type +pub fn apply_container_proxy_opts_for_transport( + config: &mut containers_image_proxy::ImageProxyConfig, + transport: Transport, +) -> Result<()> { + if transport == Transport::ContainerStorage { + // Fetching from containers-storage, may require privileges to read files + merge_default_container_proxy_opts_with_isolation(config, None) + } else { + // Apply our defaults to the proxy config + merge_default_container_proxy_opts(config) + } +} + pub mod deploy; mod encapsulate; pub use encapsulate::*; diff --git a/crates/ostree-ext/src/container/store.rs b/crates/ostree-ext/src/container/store.rs index 8acf5831e..f810bb7ca 100644 --- a/crates/ostree-ext/src/container/store.rs +++ b/crates/ostree-ext/src/container/store.rs @@ -635,13 +635,7 @@ impl ImageImporter { imgref: &OstreeImageReference, mut config: ImageProxyConfig, ) -> Result { - if imgref.imgref.transport == Transport::ContainerStorage { - // Fetching from containers-storage, may require privileges to read files - merge_default_container_proxy_opts_with_isolation(&mut config, None)?; - } else { - // Apply our defaults to the proxy config - merge_default_container_proxy_opts(&mut config)?; - } + apply_container_proxy_opts_for_transport(&mut config, imgref.imgref.transport)?; let proxy = ImageProxy::new_with_config(config).await?; system_repo_journal_print( From 20e2fede405dfc8511ed067a291118d9446e3200 Mon Sep 17 00:00:00 2001 From: Pragyan Poudyal Date: Thu, 28 May 2026 15:40:39 +0530 Subject: [PATCH 6/6] dockerfile: Separate layer for removing kernel + initrd Baseconfigs tests were failing in CI because the initrd which had the expected baseconfigs was being deleted in the same layer it was being created in. Move the deletion to a completely separate layer Signed-off-by: Pragyan Poudyal --- Dockerfile | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 58e32e49d..00a05d7cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -221,11 +221,10 @@ COPY --from=update-generated-from-code /src/docs/src/*.schema.json /docs/src/ # ---- # Perform all filesystem transformations except generating the sealed UKI (if configured) -FROM base as base-penultimate-source +FROM base as base-source ARG variant ARG bootloader ARG boot_type -ARG baseconfigs="" # Switch to a signed systemd-boot, if configured RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \ @@ -251,8 +250,10 @@ rm -rf /run/rhsm EORUN -FROM base-penultimate-source as base-penultimate +FROM base-source as base-penultimate-source ARG boot_type +ARG variant +ARG baseconfigs="" # Configure the rootfs ARG rootfs="" @@ -272,9 +273,14 @@ RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp COPY --from=packaging /usr-extras/ /usr/ # Clean up package manager caches RUN --network=none --mount=type=tmpfs,target=/run --mount=type=tmpfs,target=/tmp \ - --mount=type=bind,from=base-penultimate-source,src=/,target=/run/base-penultimate-src \ --mount=type=bind,from=packaging,src=/,target=/run/packaging <