composefs_boot/design.rs
1//! # Booting from a composefs image
2//!
3//! This document describes how composefs-rs sets up the root filesystem during
4//! early boot. It covers the kernel command-line interface, the expected on-disk
5//! layout, kernel requirements, and the step-by-step mount sequence performed by
6//! `composefs-setup-root`.
7//!
8//! The target audience is system integrators and OS developers who are packaging a
9//! bootable system using composefs. Familiarity with Linux mount namespaces,
10//! overlayfs, and fs-verity is assumed.
11//!
12//! ## Kernel command-line
13//!
14//! The initramfs code in composefs supports multiple kernel arguments; it
15//! is possible to pre-compute the digest of an image using both e.g. SHA-256 and
16//! SHA-512. On an installed system, the repository only supports one digest
17//! by default today, and the first found will be selected.
18//!
19//! Additionally, it is opt-in to enable v1 EROFS, and again the first compatible
20//! version will be found.
21//!
22//! ```text
23//! composefs.digest=v1-sha256-12:<digest> # V1 EROFS image (preferred; RHEL9-era kernels)
24//! composefs.digest=v1-sha512-12:<digest> # V1 EROFS image (SHA-512 variant)
25//! composefs.digest=v2-sha512-12:<digest> # V2 EROFS image (explicit form)
26//! composefs=<digest> # V2 EROFS image (legacy shorthand)
27//! ```
28//!
29//! The value format is `<version>-<hash>-<lg_blocksize>:<hex_digest>`, where
30//! `<version>` is `v1` or `v2`, `<hash>` is `sha256` or `sha512`, and
31//! `<lg_blocksize>` is the log2 block size (currently always `12`, i.e. 4096
32//! bytes). This mirrors how `meta.json` encodes the algorithm as
33//! `fsverity-sha256-12`.
34//!
35//! `composefs.digest=` is checked first. Multiple entries may appear on the cmdline
36//! (one per format/algorithm combination); the initramfs tries each in order and
37//! mounts the first image that actually exists in the repository.
38//!
39//! `composefs=<digest>` is a legacy shorthand equivalent to
40//! `composefs.digest=v2-<hash>-12:<digest>` -- the algorithm is inferred from the
41//! digest length (64 hex chars -> SHA-256, 128 -> SHA-512). It is checked only when
42//! no `composefs.digest=` token matches.
43//!
44//! **Insecure mode.** Placing `?` immediately after `=` (e.g.
45//! `composefs.digest=?v1-sha256-12:<digest>` or `composefs=?<digest>`) makes
46//! fs-verity verification optional. The system will boot even when the underlying
47//! filesystem does not support fs-verity or the image has no verity metadata
48//! attached. This mode exists for development and testing only; it must not be used
49//! in production.
50//!
51//! ## On-disk layout
52//!
53//! The composefs repository must be present at `/sysroot/composefs` with the
54//! standard layout described in the `composefs::repository_format` module.
55//!
56//! The digest must correspond to a symlink under `images/`.
57//!
58//! Persistent per-deployment state lives at `/sysroot/state/deploy/<digest>/`,
59//! where `<digest>` matches the boot karg digest exactly. The `etc/` and `var/`
60//! subdirectories within that directory serve as the upper layers for the
61//! corresponding overlayfs mounts.
62//!
63//! ## Kernel requirements
64//!
65//! The following kernel features must be available:
66//!
67//! - **EROFS** filesystem driver (`CONFIG_EROFS_FS`)
68//! - **overlayfs** with `metacopy=on` and `redirect_dir=on`
69//! (`CONFIG_OVERLAY_FS`, `CONFIG_OVERLAY_FS_METACOPY`, `CONFIG_OVERLAY_FS_REDIRECT_DIR`)
70//! - **fs-verity** unless insecure mode is used (`CONFIG_FS_VERITY`)
71//! - The modern Linux mount API (`fsopen` / `fsconfig` / `fsmount` / `move_mount`),
72//! available since kernel 5.2. Kernel >= 6.15 is required for the atomic root
73//! replacement path (the default build). On kernels without `fsconfig_set_fd`
74//! support (e.g. RHEL 9 / kernel < 5.15), a loopback device is created
75//! automatically by `composefs::mountcompat`.
76//!
77//! ## Kernel argument
78//!
79//! The boot karg (`composefs.digest=` or `composefs=`) is the authoritative selector for which image is booted.
80//! Without the `?` insecure prefix, every file access through the overlayfs is
81//! verified against the object's stored digest by the kernel, combining fs-verity
82//! on the data objects with overlayfs `verity=require`.
83//!
84//! ## Other notes
85//!
86//! As a workaround for a GPT auto-root issue in systemd
87//! ([systemd#35017](https://github.com/systemd/systemd/issues/35017)),
88//! `composefs-setup-root` attempts to create `/run/systemd/volatile-root` as a
89//! symlink pointing to the real block device before performing any mounts. Failure
90//! to do so is non-fatal and does not abort the boot sequence.