diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4d8b5e6ea..298b76cf4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -144,8 +144,8 @@ etc. ### Building and testing with the composefs backend -bootc has two storage backends: `ostree` (default, production) and `composefs` -(experimental). The composefs backend has several axes of configuration: +bootc has two storage backends: `ostree` and `composefs`. +The composefs backend has several axes of configuration: | Variable | Values | Notes | |---|---|---| @@ -206,7 +206,7 @@ just validate-composefs-digest The `build-sealed` target generates test Secure Boot keys in `target/test-secureboot/` and builds a complete sealed image with all the sealed composefs settings. See -[experimental-composefs.md](docs/src/bootc-experimental-composefs.7.md) for +[sealed images](docs/src/building/bootc-sealed-images.7.md) for more information on sealed images. diff --git a/crates/lib/src/cli.rs b/crates/lib/src/cli.rs index 578a74adb..0a7c0e598 100644 --- a/crates/lib/src/cli.rs +++ b/crates/lib/src/cli.rs @@ -430,7 +430,10 @@ pub(crate) enum ContainerOpts { no_truncate: bool, }, /// Output the bootable composefs digest for a directory. - #[clap(hide = true)] + /// + /// This is the digest that `bootc container ukify` embeds in the kernel + /// command line of a UKI. It is useful for scripting and debugging outside + /// of that flow. ComputeComposefsDigest { /// Path to the filesystem root #[clap(default_value = "/target")] @@ -473,7 +476,7 @@ pub(crate) enum ContainerOpts { /// and RHEL derivatives ship. /// /// Example: - /// bootc container split-kernel-rootfs --rootfs /target-rootfs --output /out + /// bootc container split-kernel-and-rootfs --rootfs /target-rootfs --output /out SplitKernelAndRootfs { /// Operate on the provided rootfs #[clap(long, default_value = "/")] @@ -1088,6 +1091,7 @@ pub(crate) enum Opt { #[clap(subcommand)] #[clap(hide = true)] Internals(InternalsOpts), + #[clap(hide = true)] ComposefsFinalizeStaged(ComposefsFinalizeStagedOpts), /// Diff current /etc configuration versus default #[clap(hide = true)] @@ -1102,9 +1106,7 @@ pub(crate) enum Opt { shell: clap_complete::aot::Shell, }, #[clap(hide = true)] - DeleteDeployment { - depl_id: String, - }, + DeleteDeployment { depl_id: String }, } /// Ensure we've entered a mount namespace, so that we can remount diff --git a/crates/lib/src/lib.rs b/crates/lib/src/lib.rs index 09a646c75..edd50e347 100644 --- a/crates/lib/src/lib.rs +++ b/crates/lib/src/lib.rs @@ -39,7 +39,7 @@ //! //! ## Storage Backends //! -//! - [`bootc_composefs`] - Composefs backend implementation (experimental) +//! - [`bootc_composefs`] - Composefs backend implementation //! - The OSTree backend is implemented via `ostree-ext` and the [`store`] module //! //! ## Filesystem and Boot diff --git a/crates/lib/src/spec.rs b/crates/lib/src/spec.rs index 15ad1014f..b58ed0ef1 100644 --- a/crates/lib/src/spec.rs +++ b/crates/lib/src/spec.rs @@ -237,7 +237,7 @@ pub enum Bootloader { /// Use Grub as the bootloader #[default] Grub, - /// Use Grub for confidential clusters as the bootloader + /// Use Grub for confidential clusters as the bootloader (experimental) #[serde(rename = "grub-cc")] GrubCC, /// Use SystemdBoot as the bootloader diff --git a/docs/book.toml b/docs/book.toml index 17ad2db3f..5de3a0ab6 100644 --- a/docs/book.toml +++ b/docs/book.toml @@ -20,6 +20,7 @@ additional-js = ["mermaid.min.js", "mermaid-init.js"] # Preserve published URLs when canonical chapters adopt manual filenames. [output.html.redirect] "boot-failure-detection.html" = "bootc-boot-failure-detection.7.html" +"bootc-experimental-composefs.7.html" = "bootc-composefs.7.html" "bootc-images.html" = "bootc-compatible-images.7.html" "bootc-in-container.html" = "bootc-in-container.7.html" "bootc-install.html" = "bootc-installation.7.html" @@ -34,7 +35,17 @@ additional-js = ["mermaid.min.js", "mermaid-init.js"] "building/secrets.html" = "bootc-secrets.7.html" "building/users-and-groups.html" = "bootc-users-and-groups.7.html" "experimental-bootc-image.html" = "bootc-experimental-image.7.html" -"experimental-composefs.html" = "bootc-experimental-composefs.7.html" +"experimental-composefs.html" = "bootc-composefs.7.html" +"experimental-composefs.html#storage-and-repository-structure" = "bootc-sysroot.7.html#composefs-backend-storage" +"experimental-composefs.html#how-sealed-images-work" = "building/bootc-sealed-images.7.html#how-sealed-images-work" +"experimental-composefs.html#building-sealed-images" = "building/bootc-sealed-images.7.html#building-sealed-images" +"experimental-composefs.html#prerequisites" = "building/bootc-sealed-images.7.html#prerequisites" +"experimental-composefs.html#using-without-secure-boot" = "building/bootc-sealed-images.7.html#using-without-secure-boot" +"experimental-composefs.html#the-bootc-container-ukify-command" = "building/bootc-sealed-images.7.html#the-bootc-container-ukify-command" +"experimental-composefs.html#the-bootc-container-compute-composefs-digest-command" = "building/bootc-sealed-images.7.html#the-bootc-container-compute-composefs-digest-command" +"experimental-composefs.html#external-signing-workflow" = "building/bootc-sealed-images.7.html#external-signing-workflow" +"experimental-composefs.html#bootloader-support" = "bootc-bootloaders.7.html#composefs-backend" +"experimental-composefs.html#installation" = "bootc-installation.7.html#composefs-backend" "experimental-container-export.html" = "bootc-experimental-container-export.7.html" "experimental-fsck.html" = "bootc-experimental-fsck.7.html" "experimental-install-reset.html" = "bootc-experimental-install-reset.7.html" diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index e6cda5f25..fe4d0ebfa 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -14,6 +14,7 @@ - [Users, groups, SSH keys](building/bootc-users-and-groups.7.md) - [`man bootc-sysusers-shadow-sync.service`](man/bootc-sysusers-shadow-sync.service.5.md) - [Kernel arguments](building/bootc-kernel-arguments.7.md) +- [Sealed images](building/bootc-sealed-images.7.md) - [Secrets](building/bootc-secrets.7.md) - [Management Services](building/bootc-management-services.7.md) @@ -61,6 +62,7 @@ - [`man bootc-container-inspect`](man/bootc-container-inspect.8.md) - [`man bootc-container-split-kernel-and-rootfs`](man/bootc-container-split-kernel-and-rootfs.8.md) - [`man bootc-container-ukify`](man/bootc-container-ukify.8.md) +- [`man bootc-container-compute-composefs-digest`](man/bootc-container-compute-composefs-digest.8.md) - [`man bootc-container-lint`](man/bootc-container-lint.8.md) # Architecture @@ -69,6 +71,10 @@ - [Filesystem](bootc-filesystem.7.md) - [Filesystem: sysroot](bootc-sysroot.7.md) - [Container storage](bootc-container-storage.7.md) +- [composefs backend](bootc-composefs.7.md) +- [`man bootc-root-setup.service`](man/bootc-root-setup.service.5.md) +- [`man bootc-setup-root-conf.toml`](man/bootc-setup-root-conf.5.md) +- [`man bootc-composefs-finalize-staged`](man/bootc-composefs-finalize-staged.8.md) - [Bootloader](bootc-bootloaders.7.md) - [`man bootc-loader-entries`](man/bootc-loader-entries.8.md) - [`man bootc-loader-entries-set-options-for-source`](man/bootc-loader-entries-set-options-for-source.8.md) @@ -81,11 +87,7 @@ # Experimental features - [bootc image](bootc-experimental-image.7.md) -- [composefs backend](bootc-experimental-composefs.7.md) -- [`man bootc-composefs-finalize-staged`](man/bootc-composefs-finalize-staged.8.md) - [unified storage](bootc-experimental-unified-storage.7.md) -- [`man bootc-root-setup.service`](man/bootc-root-setup.service.5.md) -- [`man bootc-setup-root-conf.toml`](man/bootc-setup-root-conf.5.md) - [fsck](bootc-experimental-fsck.7.md) - [install reset](bootc-experimental-install-reset.7.md) - [--progress-fd](bootc-experimental-progress-fd.7.md) diff --git a/docs/src/bootc-bootloaders.7.md b/docs/src/bootc-bootloaders.7.md index 6cd22cb17..6f88aec2f 100644 --- a/docs/src/bootc-bootloaders.7.md +++ b/docs/src/bootc-bootloaders.7.md @@ -29,3 +29,9 @@ It is possible to skip bootloader installation entirely by using `--bootloader=n With this option, users can have explicit control over how the boot loading is handled, without bootc or bootupd intervention. NOTE: none is only supported for the Ostree backend and not for Composefs. It is also not supported for the s390x architecture. If used with `--generic-image`, it will lead to a generic image that does not have support for any bootloader. + +## composefs backend + +Whenever the container image has a UKI, bootc automatically selects the composefs backend during installation. The [prerequisites for sealed images](building/bootc-sealed-images.7.md#prerequisites) describe the currently-supported UKI + systemd-boot configuration. Note that having a UKI does not by itself make an install sealed — that also depends on whether [fs-verity enforcement](bootc-composefs.7.md#overview) is on. + +Composefs installs using a traditional `vmlinuz`/`initramfs.img` layout instead of a UKI can enforce fs-verity, but are never sealed, since nothing authenticates the root digest. They can use either `bootupd` (GRUB) or systemd-boot. Under the hood, bootc writes standard BLS boot entries for both UKI and traditional kernels; see the [composefs boot module documentation](https://github.com/bootc-dev/bootc/blob/main/crates/lib/src/bootc_composefs/boot.rs) for details on how entry filenames and sort-keys are chosen to sort correctly on both GRUB and systemd-boot. diff --git a/docs/src/bootc-compatible-images.7.md b/docs/src/bootc-compatible-images.7.md index 64ebf0416..cd197d713 100644 --- a/docs/src/bootc-compatible-images.7.md +++ b/docs/src/bootc-compatible-images.7.md @@ -23,7 +23,7 @@ The Linux kernel (and optionally initramfs) is embedded in the container image; ### Kernel (sealed UKI) -For the composefs backend, the UKI must be located at `/boot/EFI/Linux/$kver.efi`. +For the composefs backend, the UKI must be located at `/boot/EFI/Linux/$kver.efi`. See [sealed images](building/bootc-sealed-images.7.md). ### /ostree symlink and `bootc container lint` diff --git a/docs/src/bootc-composefs.7.md b/docs/src/bootc-composefs.7.md new file mode 100644 index 000000000..d670580ae --- /dev/null +++ b/docs/src/bootc-composefs.7.md @@ -0,0 +1,170 @@ +# composefs backend + +bootc has two storage backends. The default is [ostree](https://github.com/ostreedev/ostree), +and the composefs backend uses [composefs-rs](https://github.com/composefs/composefs-rs) +instead of ostree to store and manage deployments. Both are supported and +covered by the project's [stability guarantees](https://github.com/bootc-dev/bootc/blob/main/RELEASES.md#stability-guarantees). +In particular, the project is committed to upgrading every composefs system +installed since bootc 1.16.0 in place. + +The composefs backend is required for [sealed images](building/bootc-sealed-images.7.md), +and the image determines which backend `bootc install` uses; see +[Understanding `bootc install`](bootc-installation.7.md#composefs-backend). Its +on-disk layout is described in [Filesystem: sysroot](bootc-sysroot.7.md#composefs-backend-storage). + +## Overview + +The composefs backend has two independent integrity controls: + +- **fs-verity enforcement.** By default every object in the composefs + repository must have fs-verity enabled, and the root filesystem is only + mounted if its digest matches the one on the kernel command line. Building a + UKI with `--allow-missing-verity` adds a `?` marker to that argument, which + makes fs-verity optional (for filesystems such as XFS that lack it). Both UKI + and traditional kernel/initramfs installs can enforce fs-verity. +- **Boot authentication.** In a *sealed* deployment fs-verity is enforced and + the expected root digest is embedded in a UKI signed for Secure Boot, so + firmware authenticates the digest and the digest authenticates the root + filesystem. A BLS entry or an + unsigned UKI still has fs-verity checked at mount time, but nothing + authenticates the digest itself. + +## EROFS formats + +composefs-rs can encode the EROFS image for a root filesystem in two formats, +which produce different digests for the same content: + +- **V1** is compatible with the C composefs tools and is the default for new + repositories. +- **V2** is the older composefs-rs format, kept as a fallback. + +The `composefs.digest=` kernel argument names the format along with the +digest, for example `composefs.digest=v1-sha512-12:`, so it is +unambiguous. The older bare `composefs=` argument is not: released +UKIs carry either a V1 or a V2 digest there (see below), so bootc tries both. + +By default `bootc container ukify` computes both digests and writes the V1 +`composefs.digest=` argument followed by a bare `composefs=` argument with the +V2 digest, for older clients. `--erofs-version=v2` writes only the bare V2 +argument. + +Each argument names one exact image. Staging fails unless every digest in the +UKI matches an image bootc generated for that container image. At boot, +bootc's initramfs tries the arguments in order and moves on to the next one if +an image is missing, but an image that fails fs-verity checks stops the boot. +bootc never substitutes a different digest. + +Existing repositories keep the format configuration recorded in their +metadata; opening one with a newer bootc doesn't convert it. + +### The bare `composefs=` argument + +Released UKIs have used the bare `composefs=` argument for different +formats: + +- bootc 1.16.0 through 1.16.2 predate format versioning and use the original + composefs-rs encoding that V2 descends from. +- bootc 1.16.3 writes a V2 digest. +- bootc 1.16.4 through 1.16.13 write a **V1** digest: the switch to the V1 + format shipped before the `composefs.digest=` argument did. +- Releases after 1.16.13 write V2 there again, after an explicit V1 argument. + +So bootc accepts a bare `composefs=` digest that matches either a V1 or a V2 +image, and only enforces the format for `composefs.digest=`. + +### Upgrading from bootc 1.16 + +When you update bootc in an image, **regenerate the initramfs before +generating the UKI**. The initramfs contains bootc's own mount logic, and +keeping an old initramfs with a newer bootc is not supported. + +For a sealed deployment, sign the new UKI with a key the existing machine +trusts. If the deployment was built with `--allow-missing-verity`, keep that +flag. Then publish the image and run `bootc upgrade` as usual. + +What happens next depends on the bootc version doing the staging. A client +that only understands `composefs=`, such as 1.16.0, stages the V2 fallback; +the new initramfs boots it, and the next upgrade (now staged by the new bootc) +moves the system to V1. bootc 1.16.4 and later already understand +`composefs.digest=` and stage V1 directly. + +The 1.16.0 path is covered by the `test-49-composefs-1-16-bridge` TMT test for +both sealed and `--allow-missing-verity` UKIs, including rollback and garbage +collection. Upgrades of UKI installs from other releases are not yet tested. + +## Supported configurations + +The following are supported with the composefs backend: + +- `bootc install`, `upgrade`, `switch`, `rollback`, `status`, `usr-overlay` + and soft reboots. +- [`bootc install mount`](man/bootc-install-mount.8.md), for changing an + installed deployment before its first boot. +- Traditional kernel and initramfs installs booted through BLS entries, with + either GRUB (via `bootupd`) or systemd-boot, and UKIs booted with + systemd-boot, including sealed UKIs signed for Secure Boot. See + [Bootloaders](bootc-bootloaders.7.md#composefs-backend). +- Root filesystems with fs-verity support, and filesystems without it (such + as XFS) with fs-verity made optional. Sealed images require fs-verity. + CI covers ext4 and XFS; btrfs is expected to work but is not tested. +- The [EROFS formats](#erofs-formats) and kernel arguments described above. +- The image build commands `bootc container ukify`, + `bootc container split-kernel-and-rootfs` and + `bootc container compute-composefs-digest`, and the initramfs setup + configured by [`setup-root-conf.toml`](man/bootc-setup-root-conf.5.md). + +On CentOS Stream 9, only sealed UKIs are tested; traditional kernel installs +require newer dracut and systemd features. Its dracut also doesn't install +`setup-root-conf.toml` into the initramfs automatically. + +## Experimental parts + +These remain [experimental](https://github.com/bootc-dev/bootc/blob/main/RELEASES.md#stability-guarantees) +and may change or be removed: + +- The `grub-cc` bootloader (`--bootloader=grub-cc`). +- UKI addons (`--uki-addon`). Addons are only installed by `bootc install`: + they aren't updated on upgrade, garbage collected, or reverted on + rollback. +- [Unified storage](bootc-experimental-unified-storage.7.md). + +## Limitations + +- `bootc edit` and [`bootc install reset`](bootc-experimental-install-reset.7.md) + are not yet implemented for the composefs backend. +- There is no `bootc-boot-complete.service` and no boot counting; see + [boot failure detection](bootc-boot-failure-detection.7.md#composefs-backend-boot-failure-detection). +- There is no in-place transition from an ostree system to the composefs + backend yet, so for now a system has to be reinstalled. We fully intend to + support moving to composefs without a reinstall; see + [Future work](#future-work). +- `--bootloader=none` is not supported. +- `--soft-reboot=auto` doesn't fall back to a regular reboot when the new + deployment can't be soft rebooted into; see + [Soft reboots](bootc-upgrades.7.md#soft-reboots). +- Only a single ESP is used (the first one found), and a separate + XBOOTLDR partition is not supported. +- Rollback with GRUB and UKIs assumes exactly two deployments. +- `bootc internals fsck` doesn't yet comprehensively cover the composefs + backend; see [#2497](https://github.com/bootc-dev/bootc/pull/2497). + +For building and testing bootc itself with the composefs backend, see +[CONTRIBUTING.md](https://github.com/bootc-dev/bootc/blob/main/CONTRIBUTING.md). + +## Future work + +- [Unified storage](https://github.com/bootc-dev/bootc/issues/20) +- [Sealed image build UX](https://github.com/bootc-dev/bootc/issues/1498): Streamlined tooling for building sealed images +- In place transitions: + - First: support [factory reset](https://github.com/bootc-dev/bootc/issues/404) from ostree to composefs + - Next: Support copying /etc and /var + +## Additional Resources + +- See [filesystem.md](bootc-filesystem.7.md) for information about composefs in the standard ostree backend +- See [bootloaders.md](bootc-bootloaders.7.md) for bootloader configuration details +- See [sealed images](building/bootc-sealed-images.7.md) for building UKIs and sealed images +- [composefs-rs](https://github.com/composefs/composefs-rs) - The underlying composefs implementation +- [composefs-rs repository format](https://github.com/composefs/composefs-rs/blob/main/crates/composefs/src/repository_format.rs) - Detailed on-disk layout of the `/composefs` repository +- [Unified Kernel Images specification](https://uapi-group.org/specifications/specs/unified_kernel_image/) +- [ukify documentation](https://www.freedesktop.org/software/systemd/man/latest/ukify.html) - Tool for building UKIs diff --git a/docs/src/bootc-experimental-composefs.7.md b/docs/src/bootc-experimental-composefs.7.md deleted file mode 100644 index d99217cb0..000000000 --- a/docs/src/bootc-experimental-composefs.7.md +++ /dev/null @@ -1,316 +0,0 @@ -# composefs backend - -Experimental features are subject to change or removal. Please -do provide feedback on them. - -## Overview - -The composefs backend is an experimental alternative storage backend that uses [composefs-rs](https://github.com/composefs/composefs-rs) instead of ostree for storing and managing bootc system deployments. - -The composefs backend has two independent integrity controls: - -- **fs-verity enforcement.** By default every object in the composefs - repository must have fs-verity enabled, and the root filesystem is only - mounted if its digest matches the one on the kernel command line. Building a - UKI with `--allow-missing-verity` adds a `?` marker to that argument, which - makes fs-verity optional (for filesystems such as XFS that lack it). Both UKI - and traditional kernel/initramfs installs can enforce fs-verity. -- **Boot authentication.** In a *sealed* deployment fs-verity is enforced and - the expected root digest is embedded in a UKI signed for Secure Boot, so - firmware authenticates the digest and the digest authenticates the root - filesystem. A BLS entry or an - unsigned UKI still has fs-verity checked at mount time, but nothing - authenticates the digest itself. - -## EROFS formats - -composefs-rs can encode the EROFS image for a root filesystem in two formats, -which produce different digests for the same content: - -- **V1** is compatible with the C composefs tools and is the default for new - repositories. Its kernel argument is - `composefs.digest=v1-sha512-12:`. -- **V2** is the older composefs-rs format, kept as a fallback. bootc writes - its kernel argument as the bare `composefs=`. - -By default `bootc container ukify` computes both digests and writes the V1 -argument followed by the V2 one. `--erofs-version=v2` writes only the V2 -argument. - -Each argument names one exact image. Staging fails unless every digest in the -UKI matches an image bootc generated for that container image. At boot, -bootc's initramfs tries the arguments in order and moves on to the next one if -an image is missing, but an image that fails fs-verity checks stops the boot. -bootc never substitutes a different digest. - -Existing repositories keep the format configuration recorded in their -metadata; opening one with a newer bootc doesn't convert it. - -### The bare `composefs=` argument - -Released UKIs have used the bare `composefs=` argument for different -formats: - -- bootc 1.16.0 through 1.16.2 predate format versioning and use the original - composefs-rs encoding that V2 descends from. -- bootc 1.16.3 writes a V2 digest. -- bootc 1.16.4 through 1.16.13 write a **V1** digest, because composefs-rs - switched its default while `ukify` kept emitting only the bare argument. -- Releases after 1.16.13 write V2 there again, after an explicit V1 argument. - -So bootc accepts a bare `composefs=` digest that matches either a V1 or a V2 -image, and only enforces the format for the explicit -`composefs.digest=v1-…`/`composefs.digest=v2-…` form. - -### Upgrading from bootc 1.16 - -When you update bootc in an image, **regenerate the initramfs before -generating the UKI**. The initramfs contains bootc's own mount logic, and -keeping an old initramfs with a newer bootc is not supported. - -For a sealed deployment, sign the new UKI with a key the existing machine -trusts. If the deployment was built with `--allow-missing-verity`, keep that -flag. Then publish the image and run `bootc upgrade` as usual. - -What happens next depends on the bootc version doing the staging. A client -that only understands `composefs=`, such as 1.16.0, stages the V2 fallback; -the new initramfs boots it, and the next upgrade (now staged by the new bootc) -moves the system to V1. bootc 1.16.4 and later already understand -`composefs.digest=` and stage V1 directly. - -The 1.16.0 path is covered by the `test-49-composefs-1-16-bridge` TMT test for -both sealed and `--allow-missing-verity` UKIs, including rollback and garbage -collection. Upgrades from other releases, and from BLS (non-UKI) composefs -installs, are not yet tested. - -## Storage and repository structure - -Unlike the ostree backend, which keeps its repository at `/ostree/repo`, the composefs backend splits its on-disk state across two top-level directories in the physical sysroot: - -- `/composefs`: The [composefs-rs repository](https://github.com/composefs/composefs-rs/blob/main/crates/composefs/src/repository_format.rs) (mode `0700`), containing: - - `objects/`: content-addressed file storage, keyed by SHA-512 fs-verity digest and shared via reflink (`FICLONE`) where the filesystem supports it - - `images/`: EROFS images describing each deployment's root filesystem metadata, possibly in both [formats](#erofs-formats) - - `streams/`: OCI manifest, config, and layer splitstreams captured during image pulls - - `bootc/storage/`: the `containers-storage:` instance backing logically bound images, reflink-shared with the composefs object store -- `/state/deploy//`: Persistent per-deployment state, one directory per deployment (see below for how it is named): - - `etc/`: a writable copy of the deployment's `/etc`, bind-mounted onto the booted root's `/etc` - - `var`: a symlink to the shared `/state/os/default/var`, bind-mounted onto the booted root's `/var` - - `.origin`: an INI file recording the image reference, boot type (BLS or UKI) and digest, and the OCI manifest digest (the latter is what keeps a deployment's objects alive across garbage collection) - -Although composefs-rs supports other fs-verity hash algorithms, bootc currently hardcodes `SHA-512` for the repository. This is why EROFS image IDs and object identifiers are 128-character hex strings. - -Three kinds of digest show up here and are easy to confuse. The OCI manifest -digest names the pulled container image (see the origin file above). An EROFS -digest names one bootable image under `images/` and is what the kernel command -line refers to; a deployment may have one of each format. The deployment ID names the -state directory; it is the digest of the boot image selected when the -deployment was staged. - -There is no `/ostree/repo`; the composefs backend doesn't use the ostree repository at all. A minimal `/ostree` directory is still created, but only to hold a compatibility symlink (`ostree/bootc -> ../composefs/bootc`) so that existing tooling expecting `/usr/lib/bootc/storage` to resolve through `ostree/bootc` keeps working. - -Transient, not-yet-finalized deployment state (used while staging an update before reboot) lives under `/run/composefs/staged-deployment` and is never persisted to disk. - -## How Sealed Images Work - -A sealed image is a cryptographically signed and verified bootc image that provides end-to-end integrity protection. This is achieved through: - -- **Unified Kernel Images (UKIs)**: Combining kernel, initramfs, and boot parameters into a single signed binary -- **Composefs integration**: Using composefs with fs-verity for content-addressed filesystem verification -- **Secure Boot**: Cryptographic signatures on both the UKI and systemd-boot loader - -A sealed image includes: - -1. **composefs digest**: A SHA-512 hash of the entire root filesystem, computed at build time -2. **Unified Kernel Image (UKI)**: A single EFI binary containing the kernel, initramfs, and kernel command line with the composefs digest embedded -3. **Secure Boot signature**: The UKI is signed with your private key - -At boot time, the composefs digest in the kernel command line (e.g. `composefs.digest=v1-sha512-12:`) is verified against the mounted root filesystem. This creates a chain of trust from firmware to userspace, ensuring the system will only boot if the root filesystem matches exactly what was signed. - -## Building Sealed Images - -### Prerequisites - -For sealed images, the container must: - -- Include a kernel and initramfs in `/usr/lib/modules//` -- Have systemd-boot available (and NOT have `bootupd`) -- Not include a pre-built UKI (the build process generates one) - -Sealed images also require: - -- Secure Boot support in the target system firmware -- A filesystem with fs-verity support (e.g., ext4, btrfs) for the root partition - -#### Using without Secure Boot - -You can use a sealed UKI without Secure Boot enabled. The composefs and mounting -code is fully orthogonal to Secure Boot - the fs-verity digest of the root filesystem -and all of its contents will still be validated at runtime, which does provide -an increased level of integrity. - -However: nothing validates that root digest itself, meaning any locally running -code can replace the UKI (e.g. after a container breakout) and fully control -the next boot. - -It is intentional to support booting with Secure Boot disabled, because a -valid use case is to temporarily disable it in order to test a change locally -on e.g. one machine, then re-enable it later. However at the current time it -is not yet streamlined to regenerate the UKI locally. - -This is independent of `--allow-missing-verity` (see [Overview](#overview)), -which instead makes fs-verity on the root filesystem optional. - -### Build Pattern: Split the Kernel, Then Generate the UKI in a Separate Stage - -Building a sealed image involves three stages: build the rootfs, split the kernel and initramfs out of it, and generate the signed UKI from the split rootfs in a tools stage: - -```dockerfile -# Build your rootfs with all packages and configuration -FROM as rootfs -RUN apt|dnf|zypper install ... && bootc container lint --fatal-warnings - -# Split the kernel and initramfs out of the rootfs. This moves -# /usr/lib/modules//{vmlinuz,initramfs.img} into /kernel//, -# since for a sealed image they end up embedded in the UKI instead. -FROM rootfs as split -RUN mkdir /kernel && bootc container split-kernel-and-rootfs --rootfs / --output /kernel - -# Generate the sealed UKI in a tools stage -FROM as sealed-uki -RUN --mount=type=bind,from=split,target=/target \ - --mount=type=bind,from=split,source=/kernel,target=/kernel \ - --mount=type=secret,id=secureboot_key \ - --mount=type=secret,id=secureboot_cert < [OPTIONS] -- [UKIFY_ARGS...] -``` - -This is the recommended way to build a UKI for a bootc image. It computes the composefs digest of `--rootfs` (using the lower-level `compute-composefs-digest` primitive described below), reads extra kernel arguments from `/usr/lib/bootc/kargs.d`, and invokes the system `ukify` binary with the resulting cmdline. Anything after `--` is forwarded to `ukify` unchanged (e.g. `--output`, `--signtool`, signing key/cert options). - -**Options:** - -- `--rootfs `: Root filesystem to operate on (default: `/`) -- `--kernel-dir `: Directory containing `vmlinuz`/`initramfs.img`, named `/parent/`. Needed when the kernel has already been split out of `--rootfs`, e.g. via `split-kernel-and-rootfs` -- `--allow-missing-verity`: Make fs-verity validation optional, for filesystems that don't support it (e.g. XFS) -- `--erofs-version `: `v1` (the default) writes a V1 argument followed - by a V2 fallback; `v2` writes only V2. See [EROFS formats](#erofs-formats). -- `--write-dumpfile-to `: Write a composefs dumpfile for debugging - -### The `bootc container compute-composefs-digest` Command - -```bash -bootc container compute-composefs-digest [PATH] -``` - -A lower-level primitive, used internally by `ukify` above, that computes just the composefs digest for a filesystem without building a UKI. The digest is a 128-character SHA-512 hex string that uniquely identifies the filesystem contents. Useful for scripting or debugging outside of the UKI build flow. - -**Options:** - -- `PATH`: Path to the filesystem root (default: `/target`) -- `--erofs-version `: EROFS format for the computed digest (default: `v1`) -- `--write-dumpfile-to `: Generate a dumpfile for debugging - -> **Note**: This command is currently hidden from `--help` output as it's part of the experimental composefs feature set. - -### Final Image Structure - -The sealed image should have: - -- The signed UKI at `/boot/EFI/Linux/.efi` -- A signed systemd-boot at `/boot/EFI/BOOT/BOOTX64.EFI` and `/boot/EFI/systemd/systemd-bootx64.efi` -- The raw `vmlinuz` and `initramfs.img` removed from `/usr/lib/modules//` (they're now embedded in the UKI) - -### External Signing Workflow - -For production environments with dedicated signing infrastructure: - -1. **Build unsigned UKI**: Compute digest and create an unsigned UKI (omit `--signtool` from ukify) -2. **Sign externally**: Take the unsigned UKI to your signing infrastructure -3. **Complete the seal**: Inject the signed UKI into the final image - -This workflow is planned for streamlining in future releases (see [#1498](https://github.com/bootc-dev/bootc/issues/1498)). - -## Developing and Testing bootc with composefs - -See [CONTRIBUTING.md](https://github.com/bootc-dev/bootc/blob/main/CONTRIBUTING.md) for information on building and testing bootc itself with composefs support. - -## Bootloader Support - -Whenever the container image has a UKI, bootc automatically selects the composefs backend during installation (see [Prerequisites](#prerequisites) above for the currently-supported UKI + systemd-boot configuration for building sealed images). Note that having a UKI does not by itself make an install sealed — that also depends on whether fs-verity enforcement is on, per [Overview](#overview) above. - -Composefs installs using a traditional `vmlinuz`/`initramfs.img` layout instead of a UKI can enforce fs-verity, but are never sealed, since nothing authenticates the root digest. They can use either `bootupd` (GRUB) or systemd-boot, the same as the ostree backend. See [bootloaders.md](bootc-bootloaders.7.md) for the general bootloader selection rules. Under the hood, bootc writes standard BLS boot entries for both UKI and traditional kernels; see the [composefs boot module documentation](https://github.com/bootc-dev/bootc/blob/main/crates/lib/src/bootc_composefs/boot.rs) for details on how entry filenames and sort-keys are chosen to sort correctly on both GRUB and systemd-boot. - -## Installation - -There is a `--composefs-backend` option for `bootc install` to explicitly select a composefs backend apart from sealed images; this is not as heavily tested yet. - -An image built only for the composefs backend selects it by itself: if it ships -`/usr/lib/composefs/setup-root-conf.toml` (see [bootc-setup-root-conf.toml(5)](man/bootc-setup-root-conf.5.md); -it may be empty) and no ostree `prepare-root.conf` (in `/usr/lib/ostree` or `/etc/ostree`), -`bootc install` uses composefs without the flag. Like the install configuration, these files are -read from the root bootc runs in, also with `--source-imgref`, so this applies to tools like -bootc-image-builder that run bootc from the image they install. An image that ships both is installed with ostree. - -## Known issues - -The composefs backend is experimental; on-disk formats are subject to change. - -- Upgrades are tested only from bootc 1.16.0 UKI installs (see - [Upgrading from bootc 1.16](#upgrading-from-bootc-116)), and that test - doesn't yet run in CI. -- Recovery from missing or corrupt images and deployment state is not yet - tested, nor is garbage collection when deployments are referenced by both V1 - and V2 boot entries (for example, that GC keeps a V2 fallback image a - rollback deployment still boots from). -- How container signature enforcement carries over from installation into the - installed system is not settled yet. -- Extended install APIs: Ability to cleanly implement anaconda %post and osbuild post mutations and general post-install pre-reboot; right now some tools just mount the deployment directory (note this one also relates to [APIs in general](https://github.com/bootc-dev/bootc/issues/522)) - -## Related issues - -- [Unified storage](https://github.com/bootc-dev/bootc/issues/20): Not strictly a blocker but a really nice to have -- [Sealed image build UX](https://github.com/bootc-dev/bootc/issues/1498): Streamlined tooling for building sealed images -- In place transitions: - - First: support [factory reset](https://github.com/bootc-dev/bootc/issues/404) from ostree to composefs - - Next: Support copying /etc and /var - -## Additional Resources - -- See [filesystem.md](bootc-filesystem.7.md) for information about composefs in the standard ostree backend -- See [bootloaders.md](bootc-bootloaders.7.md) for bootloader configuration details -- [composefs-rs](https://github.com/composefs/composefs-rs) - The underlying composefs implementation -- [composefs-rs repository format](https://github.com/composefs/composefs-rs/blob/main/crates/composefs/src/repository_format.rs) - Detailed on-disk layout of the `/composefs` repository -- [Unified Kernel Images specification](https://uapi-group.org/specifications/specs/unified_kernel_image/) -- [ukify documentation](https://www.freedesktop.org/software/systemd/man/latest/ukify.html) - Tool for building UKIs diff --git a/docs/src/bootc-experimental-unified-storage.7.md b/docs/src/bootc-experimental-unified-storage.7.md index c9f060845..4f0e95588 100644 --- a/docs/src/bootc-experimental-unified-storage.7.md +++ b/docs/src/bootc-experimental-unified-storage.7.md @@ -133,7 +133,7 @@ podman --storage-opt=additionalimagestore=/usr/lib/bootc/storage run localhost/b ## Relationship to composefs backend -Unified storage is complementary to the [composefs backend](bootc-experimental-composefs.7.md). +Unified storage is complementary to the [composefs backend](bootc-composefs.7.md). While unified storage changes *how images are pulled* (using containers/storage), the composefs backend changes *how the filesystem is stored and verified*. diff --git a/docs/src/bootc-installation.7.md b/docs/src/bootc-installation.7.md index dbd576da3..22f086add 100644 --- a/docs/src/bootc-installation.7.md +++ b/docs/src/bootc-installation.7.md @@ -121,7 +121,7 @@ merge precedence, and the available configuration fields. ### The storage backend The storage backend is determined by the image. It is installed with the -[experimental composefs backend](bootc-experimental-composefs.7.md) when it +[composefs backend](bootc-composefs.7.md) when it ships a UKI, or when it matches both of these rules: - it ships `/usr/lib/composefs/setup-root-conf.toml` (which may be empty; see @@ -143,6 +143,22 @@ unconfigured image does not have a default password or SSH key, etc. For more information, see [Image building and configuration guidance](building/bootc-building-images.7.md). +## composefs backend + +The [storage backend](#the-storage-backend) is selected by the image; see +[composefs backend](bootc-composefs.7.md) and [sealed images](building/bootc-sealed-images.7.md). + +With a traditional kernel and initramfs, the initramfs of a composefs image +must also include bootc's dracut module (`51bootc`), which mounts the composefs +root. That module is not enabled by default: the reference +[baseimage](https://github.com/bootc-dev/bootc/tree/main/baseimage) configuration +enables it, and other base images need to as well; see +[bootc-root-setup.service(5)](man/bootc-root-setup.service.5.md). + +On a root filesystem without fs-verity support (such as XFS), fs-verity is +made optional automatically for a traditional kernel install; +`--allow-missing-verity` does this explicitly. + ## More advanced installation with `to-filesystem` The basic `bootc install to-disk` logic is really a pretty small (but opinionated) wrapper diff --git a/docs/src/bootc-internals.7.md b/docs/src/bootc-internals.7.md index f3ed61e46..524134295 100644 --- a/docs/src/bootc-internals.7.md +++ b/docs/src/bootc-internals.7.md @@ -42,7 +42,7 @@ Key paths: - `/sysroot/ostree/repo/` - OSTree repository - `/sysroot/ostree/deploy//` - Deployment directories -### Composefs Backend (experimental) +### Composefs Backend Uses [composefs-rs](https://github.com/containers/composefs-rs) directly, enabling native UKI support and sealed images with fsverity integrity. diff --git a/docs/src/bootc-overview.7.md b/docs/src/bootc-overview.7.md index bdbd2df53..9f6435eeb 100644 --- a/docs/src/bootc-overview.7.md +++ b/docs/src/bootc-overview.7.md @@ -19,7 +19,8 @@ systemd is in use, systemd acts as pid1 as usual - there's no "outer" process. The CLI and API for bootc are now considered stable. Every existing system can be upgraded in place seamlessly across any future changes. -However, the core underlying code uses the [ostree](https://github.com/ostreedev/ostree) +However, the default storage backend uses the [ostree](https://github.com/ostreedev/ostree) project which has been powering stable operating system updates for many years. The stability here generally refers to the surface -APIs, not the underlying logic. +APIs, not the underlying logic. There is also a [composefs backend](bootc-composefs.7.md), +which is required for sealed images. diff --git a/docs/src/bootc-sysroot.7.md b/docs/src/bootc-sysroot.7.md index 75acc754f..9e3310c11 100644 --- a/docs/src/bootc-sysroot.7.md +++ b/docs/src/bootc-sysroot.7.md @@ -1,7 +1,8 @@ # Filesystem: Physical /sysroot -The bootc project uses [ostree](https://github.com/ostreedev/ostree/) as a backend, +By default, bootc uses [ostree](https://github.com/ostreedev/ostree/) as a backend, and maps fetched container images to a [deployment](https://ostreedev.github.io/ostree/deployment/). +The layout of the composefs backend is described [below](#composefs-backend-storage). ## stateroot @@ -76,3 +77,30 @@ is recommended, along with an `ExecStartPre=mount -o remount,rw /sysroot`. ### Detecting bootc/ostree systems See the [package managers](bootc-package-managers.7.md) section on "Detecting image based systems". + +## composefs backend storage + +Unlike the ostree backend, which keeps its repository at `/ostree/repo`, the composefs backend splits its on-disk state across two top-level directories in the physical sysroot: + +- `/composefs`: The [composefs-rs repository](https://github.com/composefs/composefs-rs/blob/main/crates/composefs/src/repository_format.rs) (mode `0700`), containing: + - `objects/`: content-addressed file storage, keyed by SHA-512 fs-verity digest and shared via reflink (`FICLONE`) where the filesystem supports it + - `images/`: EROFS images describing each deployment's root filesystem metadata, possibly in both [formats](bootc-composefs.7.md#erofs-formats) + - `streams/`: OCI manifest, config, and layer splitstreams captured during image pulls + - `bootc/storage/`: the `containers-storage:` instance backing logically bound images, reflink-shared with the composefs object store +- `/state/deploy//`: Persistent per-deployment state, one directory per deployment (see below for how it is named): + - `etc/`: a writable copy of the deployment's `/etc`, bind-mounted onto the booted root's `/etc` + - `var`: a symlink to the shared `/state/os/default/var`, bind-mounted onto the booted root's `/var` + - `.origin`: an INI file recording the image reference, boot type (BLS or UKI) and digest, and the OCI manifest digest (the latter is what keeps a deployment's objects alive across garbage collection) + +Although composefs-rs supports other fs-verity hash algorithms, bootc currently hardcodes `SHA-512` for the repository. This is why EROFS image IDs and object identifiers are 128-character hex strings. + +Three kinds of digest show up here and are easy to confuse. The OCI manifest +digest names the pulled container image (see the origin file above). An EROFS +digest names one bootable image under `images/` and is what the kernel command +line refers to; a deployment may have one of each format. The deployment ID names the +state directory; it is the digest of the boot image selected when the +deployment was staged. + +There is no `/ostree/repo`; the composefs backend doesn't use the ostree repository at all. A minimal `/ostree` directory is still created, but only to hold a compatibility symlink (`ostree/bootc -> ../composefs/bootc`) so that existing tooling expecting `/usr/lib/bootc/storage` to resolve through `ostree/bootc` keeps working. + +Transient, not-yet-finalized deployment state (used while staging an update before reboot) lives under `/run/composefs/staged-deployment` and is never persisted to disk. diff --git a/docs/src/bootc-upgrades.7.md b/docs/src/bootc-upgrades.7.md index 48eabce0d..de6f8f18f 100644 --- a/docs/src/bootc-upgrades.7.md +++ b/docs/src/bootc-upgrades.7.md @@ -163,7 +163,7 @@ Without `--apply`, `--soft-reboot` prepares the deployment but does not restart the system immediately. Without `--soft-reboot`, `--apply` requests a regular reboot. -The [experimental composefs backend](bootc-experimental-composefs.7.md) currently +The [composefs backend](bootc-composefs.7.md) currently differs: both modes fail if systemd lacks soft-reboot support. If the target deployment is not soft-reboot capable, `auto` leaves it staged without restarting, even with `--apply`; it does not automatically fall back to a diff --git a/docs/src/building/bootc-sealed-images.7.md b/docs/src/building/bootc-sealed-images.7.md new file mode 100644 index 000000000..202357974 --- /dev/null +++ b/docs/src/building/bootc-sealed-images.7.md @@ -0,0 +1,153 @@ +# Sealed images + +## How Sealed Images Work + +A sealed image is a cryptographically signed and verified bootc image that provides end-to-end integrity protection. This is achieved through: + +- **Unified Kernel Images (UKIs)**: Combining kernel, initramfs, and boot parameters into a single signed binary +- **Composefs integration**: Using composefs with fs-verity for content-addressed filesystem verification +- **Secure Boot**: Cryptographic signatures on both the UKI and systemd-boot loader + +A sealed image includes: + +1. **composefs digest**: A SHA-512 hash of the entire root filesystem, computed at build time +2. **Unified Kernel Image (UKI)**: A single EFI binary containing the kernel, initramfs, and kernel command line with the composefs digest embedded +3. **Secure Boot signature**: The UKI is signed with your private key + +At boot time, the composefs digest in the kernel command line (e.g. `composefs.digest=v1-sha512-12:`) is verified against the mounted root filesystem. This creates a chain of trust from firmware to userspace, ensuring the system will only boot if the root filesystem matches exactly what was signed. + +## Building Sealed Images + +### Prerequisites + +For sealed images, the container must: + +- Include a kernel and initramfs in `/usr/lib/modules//` +- Have systemd-boot available (and NOT have `bootupd`) +- Not include a pre-built UKI (the build process generates one) + +Sealed images also require: + +- Secure Boot support in the target system firmware +- A filesystem with fs-verity support (e.g., ext4, btrfs) for the root partition + +#### Using without Secure Boot + +You can use a sealed UKI without Secure Boot enabled. The composefs and mounting +code is fully orthogonal to Secure Boot - the fs-verity digest of the root filesystem +and all of its contents will still be validated at runtime, which does provide +an increased level of integrity. + +However: nothing validates that root digest itself, meaning any locally running +code can replace the UKI (e.g. after a container breakout) and fully control +the next boot. + +It is intentional to support booting with Secure Boot disabled, because a +valid use case is to temporarily disable it in order to test a change locally +on e.g. one machine, then re-enable it later. However at the current time it +is not yet streamlined to regenerate the UKI locally. + +This is independent of [`--allow-missing-verity`](../bootc-composefs.7.md#overview), +which instead makes fs-verity on the root filesystem optional. + +### Build Pattern: Split the Kernel, Then Generate the UKI in a Separate Stage + +Building a sealed image involves three stages: build the rootfs, split the kernel and initramfs out of it, and generate the signed UKI from the split rootfs in a tools stage: + +```dockerfile +# Build your rootfs with all packages and configuration +FROM as rootfs +RUN apt|dnf|zypper install ... && bootc container lint --fatal-warnings + +# Split the kernel and initramfs out of the rootfs. This moves +# /usr/lib/modules//{vmlinuz,initramfs.img} into /kernel//, +# since for a sealed image they end up embedded in the UKI instead. +FROM rootfs as split +RUN mkdir /kernel && bootc container split-kernel-and-rootfs --rootfs / --output /kernel + +# Generate the sealed UKI in a tools stage +FROM as sealed-uki +RUN --mount=type=bind,from=split,target=/target \ + --mount=type=bind,from=split,source=/kernel,target=/kernel \ + --mount=type=secret,id=secureboot_key \ + --mount=type=secret,id=secureboot_cert < [OPTIONS] -- [UKIFY_ARGS...] +``` + +This is the recommended way to build a UKI for a bootc image. It computes the composefs digest of `--rootfs` (using the lower-level `compute-composefs-digest` primitive described below), reads extra kernel arguments from `/usr/lib/bootc/kargs.d`, and invokes the system `ukify` binary with the resulting cmdline. Anything after `--` is forwarded to `ukify` unchanged (e.g. `--output`, `--signtool`, signing key/cert options). + +**Options:** + +- `--rootfs `: Root filesystem to operate on (default: `/`) +- `--kernel-dir `: Directory containing `vmlinuz`/`initramfs.img`, named `/parent/`. Needed when the kernel has already been split out of `--rootfs`, e.g. via `split-kernel-and-rootfs` +- `--allow-missing-verity`: Make fs-verity validation optional, for filesystems that don't support it (e.g. XFS) +- `--erofs-version `: `v1` (the default) writes a V1 argument followed + by a V2 fallback; `v2` writes only V2. See [EROFS formats](../bootc-composefs.7.md#erofs-formats). +- `--write-dumpfile-to `: Write a composefs dumpfile for debugging + +### The `bootc container compute-composefs-digest` Command + +```bash +bootc container compute-composefs-digest [PATH] +``` + +A lower-level primitive, used internally by `ukify` above, that computes just the composefs digest for a filesystem without building a UKI. The digest is a 128-character SHA-512 hex string that uniquely identifies the filesystem contents. Useful for scripting or debugging outside of the UKI build flow. + +**Options:** + +- `PATH`: Path to the filesystem root (default: `/target`) +- `--erofs-version `: EROFS format for the computed digest (default: `v1`) +- `--write-dumpfile-to `: Generate a dumpfile for debugging + +See also [bootc-container-compute-composefs-digest(8)](../man/bootc-container-compute-composefs-digest.8.md). + +### Final Image Structure + +The sealed image should have: + +- The signed UKI at `/boot/EFI/Linux/.efi` +- A signed systemd-boot at `/boot/EFI/BOOT/BOOTX64.EFI` and `/boot/EFI/systemd/systemd-bootx64.efi` +- The raw `vmlinuz` and `initramfs.img` removed from `/usr/lib/modules//` (they're now embedded in the UKI) + +### External Signing Workflow + +For production environments with dedicated signing infrastructure: + +1. **Build unsigned UKI**: Compute digest and create an unsigned UKI (omit `--signtool` from ukify) +2. **Sign externally**: Take the unsigned UKI to your signing infrastructure +3. **Complete the seal**: Inject the signed UKI into the final image + +This workflow is planned for streamlining in future releases (see [#1498](https://github.com/bootc-dev/bootc/issues/1498)). diff --git a/docs/src/host-v1.schema.json b/docs/src/host-v1.schema.json index 686b71e04..8e0fa84dd 100644 --- a/docs/src/host-v1.schema.json +++ b/docs/src/host-v1.schema.json @@ -216,7 +216,7 @@ "const": "grub" }, { - "description": "Use Grub for confidential clusters as the bootloader", + "description": "Use Grub for confidential clusters as the bootloader (experimental)", "type": "string", "const": "grub-cc" }, diff --git a/docs/src/man/bootc-composefs-finalize-staged.8.md b/docs/src/man/bootc-composefs-finalize-staged.8.md index a8b054ab3..1736e673f 100644 --- a/docs/src/man/bootc-composefs-finalize-staged.8.md +++ b/docs/src/man/bootc-composefs-finalize-staged.8.md @@ -30,13 +30,10 @@ runs. # OPTIONS - **--hold** Hold /boot open until terminated, instead of finalizing - - # EXAMPLES Check whether a staged deployment is waiting to be finalized at the diff --git a/docs/src/man/bootc-container-compute-composefs-digest.8.md b/docs/src/man/bootc-container-compute-composefs-digest.8.md new file mode 100644 index 000000000..3f5237a5b --- /dev/null +++ b/docs/src/man/bootc-container-compute-composefs-digest.8.md @@ -0,0 +1,62 @@ +# NAME + +bootc-container-compute-composefs-digest - Output the bootable composefs +digest for a directory + +# SYNOPSIS + +bootc container compute-composefs-digest [OPTIONS] [PATH] + +# DESCRIPTION + +Output the bootable composefs digest for a directory + +This is the digest that `bootc container ukify` embeds in the kernel +command line of a UKI. It is a 128-character SHA-512 hex string that +identifies the filesystem contents. Most image builds should use +**bootc-container-ukify**(8), which computes it internally; this command is +useful for scripting and debugging outside of that flow. + +The digest depends on the EROFS format; see `--erofs-version`. It must be +run against a separate mount of the root filesystem, not the running root. + +# OPTIONS + + +**PATH** + + Path to the filesystem root + +**--write-dumpfile-to**=*WRITE_DUMPFILE_TO* + + Additionally generate a dumpfile for the preferred digest, written to the target path + +**--erofs-version**=*EROFS_VERSION* + + EROFS format version to use when computing the composefs digest + + Possible values: + - v1 + - v2 + + Default: v1 + + + +# EXAMPLES + +Compute the digest of a root filesystem mounted at `/target`: + + bootc container compute-composefs-digest /target + +Also write a composefs dumpfile, to compare against another build: + + bootc container compute-composefs-digest --write-dumpfile-to /tmp/rootfs.dump /target + +# SEE ALSO + +**bootc**(8), **bootc-container-ukify**(8) + +# VERSION + + diff --git a/docs/src/man/bootc-container.8.md b/docs/src/man/bootc-container.8.md index 1b1fce62f..8f54ccc5b 100644 --- a/docs/src/man/bootc-container.8.md +++ b/docs/src/man/bootc-container.8.md @@ -21,6 +21,7 @@ Operations which can be executed as part of a container build |---------|-------------| | **bootc container inspect** | Output information about the container image | | **bootc container lint** | Perform relatively inexpensive static analysis checks as part of a container build | +| **bootc container compute-composefs-digest** | Output the bootable composefs digest for a directory | | **bootc container split-kernel-and-rootfs** | Split kernel and rootfs from a container image | | **bootc container ukify** | Build a Unified Kernel Image (UKI) using ukify | diff --git a/docs/src/man/bootc-setup-root-conf.5.md b/docs/src/man/bootc-setup-root-conf.5.md index d4c3350c8..908373c73 100644 --- a/docs/src/man/bootc-setup-root-conf.5.md +++ b/docs/src/man/bootc-setup-root-conf.5.md @@ -28,9 +28,6 @@ when it is present on the host image. Image authors can therefore ship the file at this path in their container image and rebuild the initramfs with a plain `dracut --force`; no `--include` flags are needed. -**NOTE**: The composefs backend and this configuration file are experimental -and subject to change without notice. - # SECTIONS ## `[root]` diff --git a/docs/src/man/bootc.8.md b/docs/src/man/bootc.8.md index e564852fb..c741f8f75 100644 --- a/docs/src/man/bootc.8.md +++ b/docs/src/man/bootc.8.md @@ -37,7 +37,6 @@ For guides to building, installing, and managing bootable images, see | **bootc install** | Install the running container to a target | | **bootc container** | Operations which can be executed as part of a container build | | **bootc loader-entries** | Operations on Boot Loader Specification (BLS) entries | -| **bootc composefs-finalize-staged** | Finalize a staged composefs deployment |