You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add comprehensive documentation for building sealed bootc images,
focusing on the core concepts and the key command:
`bootc container compute-composefs-digest`.
Key additions:
- Document how sealed images work (UKI + composefs digest + Secure Boot)
- Explain the build workflow abstractly without distribution-specific details
- Document the compute-composefs-digest command and its options
- Add section on generating/signing UKIs with ukify
- Document developer testing commands (just variant=composefs-sealeduki-sdboot)
- Add validation tooling documentation
This provides the foundation for distribution-specific documentation
to build upon with concrete Containerfile examples.
Assisted-by: OpenCode (Claude Sonnet 4)
Signed-off-by: Colin Walters <walters@verbum.org>
@@ -16,40 +16,150 @@ This is based on [Unified Kernel Images](https://uapi-group.org/specifications/s
16
16
that embed a digest of the target container root filesystem, typically alongside a bootloader (such
17
17
as systemd-boot) also signed with your key.
18
18
19
-
### UKIs in bootc containers
19
+
##How Sealed Images Work
20
20
21
-
There must be exactly one UKI placed in `/boot/EFI/Linux/<name>.efi`.
21
+
A sealed image is a cryptographically signed and verified bootc image that provides end-to-end integrity protection. This is achieved through:
22
22
23
-
### Bootloader support
23
+
-**Unified Kernel Images (UKIs)**: Combining kernel, initramfs, and boot parameters into a single signed binary
24
+
-**Composefs integration**: Using composefs with fsverity for content-addressed filesystem verification
25
+
-**Secure Boot**: Cryptographic signatures on both the UKI and systemd-boot loader
24
26
25
-
To use sealed images, ensure that the target container image has systemd-boot,
26
-
and does not have `bootupd`.
27
+
A sealed image includes:
27
28
28
-
### Installation
29
+
1.**composefs digest**: A SHA-512 hash of the entire root filesystem, computed at build time
30
+
2.**Unified Kernel Image (UKI)**: A single EFI binary containing the kernel, initramfs, and kernel command line with the composefs digest embedded
31
+
3.**Secure Boot signature**: The UKI is signed with your private key
29
32
30
-
There is a `--composefs-backend` option for `bootc install`; however, if
31
-
a UKI and systemd-boot are detected, it will automatically be used.
33
+
At boot time, the composefs digest in the kernel command line (e.g., `composefs=<sha512-hash>`) 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.
32
34
33
-
### Developing and testing bootc with sealed composefs
35
+
##Building Sealed Images
34
36
35
-
Use `just variant=composefs-sealeduki-sdboot build` to build a local sealed
36
-
UKI, using Secure Boot keys generated in `target/test-secureboot`. This is
37
-
not a production path.
37
+
### Prerequisites
38
+
39
+
For sealed images, the container must:
40
+
41
+
- Include a kernel and initramfs in `/usr/lib/modules/<kver>/`
42
+
- Have systemd-boot available (and NOT have `bootupd`)
43
+
- Not include a pre-built UKI (the build process generates one)
44
+
45
+
Sealed images also require:
46
+
47
+
- Secure Boot support in the target system firmware
48
+
- A filesystem with fsverity support (e.g., ext4, btrfs) for the root partition
49
+
50
+
### Build Pattern: Compute Digest and Generate UKI in One Stage
51
+
52
+
The key to building sealed images is using a multi-stage Dockerfile where a separate stage mounts the target rootfs, computes its composefs digest, and generates the signed UKI in one step:
53
+
54
+
```dockerfile
55
+
# Build your rootfs with all packages and configuration
56
+
FROM <base-image> as rootfs
57
+
RUN apt|dnf|zypper install ... && bootc container lint --fatal-warnings
58
+
59
+
# Generate the sealed UKI in a tools stage
60
+
FROM <tools-image> as sealed-uki
61
+
RUN --mount=type=bind,from=rootfs,target=/target \
62
+
--mount=type=secret,id=secureboot_key \
63
+
--mount=type=secret,id=secureboot_cert <<EORUN
64
+
set -euo pipefail
65
+
66
+
# Compute the composefs digest from the mounted rootfs
# Remove raw kernel/initramfs (now embedded in UKI)
88
+
RUN rm -f /usr/lib/modules/*/vmlinuz /usr/lib/modules/*/initramfs.img
89
+
```
90
+
91
+
This pattern works because:
92
+
93
+
1. The `--mount=type=bind,from=rootfs` provides read-only access to the target filesystem
94
+
2.`bootc container compute-composefs-digest` computes the SHA-512 hash of the rootfs
95
+
3.`ukify` creates the UKI with that digest in the kernel command line (`composefs=<digest>`)
96
+
4. The final stage copies the signed UKI into the rootfs without modifying any files used in the digest calculation
97
+
98
+
### The `bootc container compute-composefs-digest` Command
99
+
100
+
```bash
101
+
bootc container compute-composefs-digest [PATH]
102
+
```
103
+
104
+
Computes the composefs digest for a filesystem. The digest is a 128-character SHA-512 hex string that uniquely identifies the filesystem contents.
105
+
106
+
**Options:**
107
+
108
+
-`PATH`: Path to the filesystem root (default: `/target`)
109
+
-`--write-dumpfile-to <PATH>`: Generate a dumpfile for debugging
110
+
111
+
> **Note**: This command is currently hidden from `--help` output as it's part of the experimental composefs feature set.
112
+
113
+
### Final Image Structure
114
+
115
+
The sealed image should have:
116
+
117
+
- The signed UKI at `/boot/EFI/Linux/<kver>.efi`
118
+
- A signed systemd-boot at `/boot/EFI/BOOT/BOOTX64.EFI` and `/boot/EFI/systemd/systemd-bootx64.efi`
119
+
- The raw `vmlinuz` and `initramfs.img` removed from `/usr/lib/modules/<kver>/` (they're now embedded in the UKI)
120
+
121
+
### External Signing Workflow
122
+
123
+
For production environments with dedicated signing infrastructure:
124
+
125
+
1.**Build unsigned UKI**: Compute digest and create an unsigned UKI (omit `--signtool` from ukify)
126
+
2.**Sign externally**: Take the unsigned UKI to your signing infrastructure
127
+
3.**Complete the seal**: Inject the signed UKI into the final image
128
+
129
+
This workflow is planned for streamlining in future releases (see [#1498](https://github.com/bootc-dev/bootc/issues/1498)).
130
+
131
+
## Developing and Testing bootc with composefs
132
+
133
+
See [CONTRIBUTING.md](https://github.com/bootc-dev/bootc/blob/main/CONTRIBUTING.md) for information on building and testing bootc itself with composefs support.
134
+
135
+
## Bootloader Support
136
+
137
+
To use sealed images, the container image must have a UKI and systemd-boot installed (and not have `bootupd`). If these conditions are met, bootc will automatically detect and use the composefs backend during installation.
138
+
139
+
## Installation
140
+
141
+
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.
38
142
39
143
## Current Limitations
40
144
41
-
-**Experimental**: In particular, the on-disk formats are subject to change
145
+
-**Experimental**: The on-disk formats are subject to change
42
146
-**UX refinement**: The user experience for building and managing sealed images is still being improved
147
+
-**SELinux**: Currently uses `enforcing=0` in the kernel command line (see [#1826](https://github.com/bootc-dev/bootc/issues/1826))
148
+
-**kargs.d**: Custom kernel arguments from `/usr/lib/bootc/kargs.d` are not yet automatically included in sealed UKIs
0 commit comments