sealing blog#40
Conversation
jeckersb
commented
May 1, 2026
- blog: add sealed images security chain overview
- blog: add sealed images key management post
- blog: add sealed images building post
- blog: add sealed images deploying post
First post in a series about bootc sealed images, covering the full trust chain from Secure Boot firmware through per-file fs-verity verification at runtime. Assisted-by: OpenCode (claude-opus-4-6)
Second post in the sealed images series, covering the UEFI Secure Boot key hierarchy, key generation, signing boot artifacts, and key enrollment methods. Assisted-by: OpenCode (claude-opus-4-6)
Third post in the sealed images series, covering the multi-stage container build process for producing a sealed, signed bootc image. References the rhel-bootc-examples repository for the complete working example. Assisted-by: OpenCode (claude-opus-4-6)
Fourth post in the sealed images series, covering deployment via bcvk and verification that the full security chain is active. Assisted-by: OpenCode (claude-opus-4-6)
There was a problem hiding this comment.
Code Review
This pull request introduces a four-part blog series detailing the security chain, key management, build process, and deployment of sealed images for bootc. The review feedback identifies technical inaccuracies regarding bootupd's support for systemd-boot and the range of filesystems supporting fs-verity. Additionally, a correction was provided for a Dockerfile example that was missing the necessary steps to install the generated Unified Kernel Image (UKI) into the boot directory.
| bootc container ukify --rootfs /target \ | ||
| -- \ | ||
| --signtool sbsign \ | ||
| --secureboot-private-key /run/secrets/secureboot_key \ | ||
| --secureboot-certificate /run/secrets/secureboot_cert \ | ||
| --output /out/uki.efi |
There was a problem hiding this comment.
The code block is missing the command to move the generated UKI to the expected path in /boot. The text at line 138 mentions that the stage places the UKI under /boot/EFI/Linux/, but the ukify command outputs to /out/uki.efi. This will cause the subsequent COPY --from=kernel /boot /boot in Stage 4 to miss the new UKI.
| bootc container ukify --rootfs /target \ | |
| -- \ | |
| --signtool sbsign \ | |
| --secureboot-private-key /run/secrets/secureboot_key \ | |
| --secureboot-certificate /run/secrets/secureboot_cert \ | |
| --output /out/uki.efi | |
| bootc container ukify --rootfs /target \ | |
| -- \ | |
| --signtool sbsign \ | |
| --secureboot-private-key /run/secrets/secureboot_key \ | |
| --secureboot-certificate /run/secrets/secureboot_cert \ | |
| --output /tmp/uki.efi | |
| mkdir -p /boot/EFI/Linux/ | |
| install -m 0644 /tmp/uki.efi /boot/EFI/Linux/sealed-uki.efi |
| filesystem. This is required because fs-verity is only supported | ||
| on ext4 and btrfs. |
There was a problem hiding this comment.
The statement that fs-verity is only supported on ext4 and btrfs is outdated. Support for fs-verity on XFS was merged in Linux kernel 6.10. Since the example uses CentOS Stream 10 (which uses kernel 6.11+), XFS is also a valid option.
| filesystem. This is required because fs-verity is only supported | |
| on ext4 and btrfs. | |
| filesystem. This is required because fs-verity is supported | |
| on ext4, btrfs, and XFS (in modern kernels). |
cgwalters
left a comment
There was a problem hiding this comment.
Thanks so much for doing this! Only glancing at the first one so far.
Also once we publish these we should cross-link them from the bootc composefs docs.
|
|
||
| ## The gap | ||
|
|
||
| Many Linux systems in use today don't use |
There was a problem hiding this comment.
This looks similar to some other content I helped edit and would like to change, see https://url.corp.redhat.com/1779017
| bootloader may verify the kernel's signature, but the initramfs and | ||
| command line are typically not covered by any signature. | ||
|
|
||
| A Unified Kernel Image (UKI) changes this by bundling the kernel, the |
There was a problem hiding this comment.
Worth linking to the spec here I think
| line is covered by the same signature that covers the kernel itself. | ||
| As we'll see next, this is where the composefs digest lives. | ||
|
|
||
| ## The composefs digest |
There was a problem hiding this comment.
I would probably refactor this to say:
## composefs: EROFS + overlayfs + fsverity
And frame it that way, e.g. the section here is saying that the digest is of the EROFS...
| carries within it a cryptographic commitment to the exact filesystem | ||
| that should be mounted as the operating system. | ||
|
|
||
| ## fs-verity |
There was a problem hiding this comment.
And this section could explain briefly not just fsverity but also the overlayfs part.
| ### Check the root mount | ||
|
|
||
| ``` | ||
| $ mount | grep " / " |
There was a problem hiding this comment.
AI: Important: This command will not match the output shown. Grepping for " / " (with spaces) will not match a line containing /sysroot. Additionally, standard mount output is <device> on <mountpoint> type <fstype> (options) — the output shown does not match that format.
In a booted bootc system the composefs/overlayfs mount enforcing verity=require will be at the deploy root, not necessarily at /sysroot. A more reliable command would be:
$ findmnt -t overlay /
or
$ mount | grep -E "composefs|overlay"
with output updated to reflect what these actually produce. Readers on Reddit/HN will spot fake terminal output immediately.
| built. Configuration management and runtime security tools protect | ||
| the rest. |
There was a problem hiding this comment.
This starts to get into bigger picture design, but for /etc i think we should actually strongly encourage transient or readonly even.
And for /var, this is where PCR-locked LUKS can come into play (and/or dm-integrity).
How about for now:
By default,
/etcand/varare mutable and persistent. It is possible to make/etctransient today, and this is a good idea if it matches your use case. More suggestions on this will be in the documentation.