@@ -26,7 +26,7 @@ This requires running the container via `--privileged`; it uses the running Linu
2626on the host to write the file content from the running container image; not the kernel
2727inside the container.
2828
29- There are two sub-commands: ` bootc install to-disk ` and ` boot install to-filesystem` .
29+ There are two sub-commands: ` bootc install to-disk ` and ` bootc install to-filesystem` .
3030
3131However, nothing * else* (external) is required to perform a basic installation
3232to disk - the container image itself comes with a baseline self-sufficient installer
@@ -217,7 +217,7 @@ podman run --rm --privileged -v /dev:/dev -v /var/lib/containers:/var/lib/contai
217217 bootc install to-existing-root
218218```
219219
220- It is assumed in this command that the target rootfs is pased via ` -v /:/target ` at this time.
220+ It is assumed in this command that the target rootfs is passed via ` -v /:/target ` at this time.
221221
222222As noted above, the data in ` /boot ` will be wiped, but everything else in the existing
223223operating ` / ` is ** NOT** automatically cleaned up. This can
@@ -346,6 +346,84 @@ This argument is mainly useful for 3rd-party tooling for building disk images fr
346346containers (e.g. based on [ osbuild] ( https://github.com/osbuild/osbuild ) ).
347347
348348
349+ ## Discoverable Partitions Specification (DPS)
350+
351+ As of bootc 1.11, the default partitioning layout for ` bootc install to-disk ` uses the
352+ [ Discoverable Partitions Specification (DPS)] ( https://uapi-group.org/specifications/specs/discoverable_partitions_specification/ )
353+ from the UAPI Group. This is an important foundation for modern Linux systems.
354+
355+ ### What is DPS?
356+
357+ The Discoverable Partitions Specification defines well-known partition type GUIDs for
358+ different purposes (root filesystem, ESP, swap, /home, etc.) and for different CPU
359+ architectures. When partitions use these standardized type GUIDs, systemd and other
360+ tools can automatically discover and mount them without explicit configuration.
361+
362+ Each supported CPU architecture has its own root partition type GUID. See the
363+ [ DPS specification] ( https://uapi-group.org/specifications/specs/discoverable_partitions_specification/ )
364+ for the complete list of partition types.
365+
366+ ### How bootc uses DPS
367+
368+ When ` bootc install to-disk ` creates partitions, it sets the appropriate DPS partition
369+ type GUID based on the target architecture. This enables:
370+
371+ 1 . ** Automatic root discovery** : With a DPS-aware bootloader and initramfs, the root
372+ filesystem can be discovered automatically without a ` root= ` kernel argument.
373+ This is handled by [ systemd-gpt-auto-generator] ( https://www.freedesktop.org/software/systemd/man/latest/systemd-gpt-auto-generator.html ) .
374+
375+ 2 . ** Sealed/verified boot paths** : When using composefs with UKIs (Unified Kernel Images),
376+ bootc can omit the ` root= ` kernel argument entirely. The initramfs uses DPS to find
377+ the root partition, and composefs provides integrity verification.
378+
379+ 3 . ** Future systemd-repart integration** : DPS partition types allow systemd-repart to
380+ automatically grow or create partitions based on declarative configuration.
381+
382+ ### When is DPS used vs explicit kernel arguments?
383+
384+ | Installation Mode | Root Discovery Method |
385+ | -------------------| ----------------------|
386+ | ` to-disk ` | Explicit ` root=UUID=... ` karg |
387+ | ` to-filesystem --root-mount-spec="" ` | DPS auto-discovery (no ` root= ` karg) |
388+ | ` to-filesystem ` (default) | Uses filesystem UUID as ` root=UUID=... ` karg |
389+ | ` to-existing-root ` | Inherits from existing system |
390+
391+ For ` to-disk ` , bootc always injects a ` root=UUID=<uuid> ` kernel argument for
392+ compatibility, even though the partition type is set to the DPS GUID. This
393+ ensures the system boots on initramfs implementations that don't support
394+ DPS auto-discovery.
395+
396+ For ` to-filesystem ` , the ` --root-mount-spec="" ` option (empty string) can be
397+ used to omit the ` root= ` kernel argument entirely, enabling DPS auto-discovery.
398+ This is useful when the bootloader and initramfs both support the
399+ [ Boot Loader Interface] ( https://systemd.io/BOOT_LOADER_INTERFACE/ ) .
400+
401+ ### Bootloader requirements for DPS auto-discovery
402+
403+ DPS auto-discovery requires a bootloader that implements the Boot Loader
404+ Interface and sets the ` LoaderDevicePartUUID ` EFI variable. Supported
405+ bootloaders include:
406+
407+ - ** GRUB 2.12+** with the ` bli ` module (included in Fedora 43+, requires EFI boot)
408+ - ** systemd-boot** (always supports the Boot Loader Interface)
409+
410+ Older GRUB versions (without the ` bli ` module) do not set this variable and
411+ DPS auto-discovery will not work.
412+
413+ ### Implications for external installers
414+
415+ If you're building tooling that uses ` bootc install to-filesystem ` , you should:
416+
417+ 1 . ** Set appropriate partition types** : Use the DPS type GUID for the root partition
418+ when creating partitions externally.
419+
420+ 2 . ** Consider auto-discovery** : If your bootloader and initramfs support DPS, you
421+ may be able to omit ` root= ` kernel arguments entirely.
422+
423+ 3 . ** Use ` rootflags ` for mount options** : Prefer the ` rootflags= ` kernel argument
424+ over ` /etc/fstab ` for root mount options, as this works better with composefs
425+ and DPS auto-discovery.
426+
349427## Finding and configuring the physical root filesystem
350428
351429On a bootc system, the "physical root" is different from
@@ -393,3 +471,74 @@ Installation software such as [Anaconda](https://github.com/rhinstaller/anaconda
393471do this today to implement generic ` %post ` scripts and the like.
394472
395473However, it is very likely that a generic bootc API to do this will be added.
474+
475+ ## Provisioning and first boot
476+
477+ After ` bootc install ` completes, the system is ready for first boot. A key
478+ design principle is that ** minimal machine-specific configuration should be
479+ injected at install time** . Instead, most configuration should happen at
480+ runtime—either at first boot or on every boot—using standard Linux mechanisms.
481+
482+ This approach has several benefits:
483+
484+ - ** Simpler installation** : The install process doesn't need to know about
485+ every possible configuration option
486+ - ** Better fits the container model** : Configuration logic lives in the
487+ container image, not in external tooling
488+ - ** Easier updates** : Runtime configuration naturally applies to updated
489+ deployments
490+
491+ ### Install-time configuration
492+
493+ When some machine-specific data must be provided at install time, the preferred
494+ approaches depend on your boot setup:
495+
496+ - ** Type 1 BLS setups** : Use ` bootc install --karg ` to inject kernel arguments.
497+ For example, ` --karg ip=192.168.1.100::192.168.1.1:255.255.255.0:host1::none `
498+ for static IP configuration, or ` --karg console=ttyS0,115200 ` for serial console.
499+
500+ - ** UKI setups** : Use [ UKI addons] ( https://uapi-group.org/specifications/specs/unified_kernel_image/#addon-uki-format )
501+ (additional signed PE binaries containing extra kernel arguments or initrd content)
502+ to provide machine-specific configuration while preserving the signed UKI.
503+
504+ ### Runtime configuration approaches
505+
506+ Since bootc systems are standard Linux systems, any provisioning tool that
507+ works on Linux will work with bootc. Common approaches include:
508+
509+ - ** cloud-init** : If included in your container image, runs at first boot to
510+ configure users, SSH keys, networking, and run custom scripts
511+ - ** Ignition** : Runs in the initramfs before the real root is mounted; used
512+ by Fedora CoreOS-style systems
513+ - ** systemd-firstboot** : Configures locale, timezone, hostname, etc. on first boot
514+ - ** Custom systemd services** : Use ` ConditionFirstBoot=yes ` for one-time setup,
515+ or run on every boot for dynamic configuration
516+
517+ The choice of provisioning tool depends on your base image and deployment
518+ environment—bootc itself is agnostic.
519+
520+ ### SSH key injection
521+
522+ For simple SSH access without a full provisioning system, bootc provides the
523+ ` --root-ssh-authorized-keys ` option:
524+
525+ ``` bash
526+ bootc install to-disk --root-ssh-authorized-keys /path/to/authorized_keys /dev/sda
527+ ```
528+
529+ This writes a systemd-tmpfiles configuration that ensures the SSH keys are
530+ present on every boot, even if ` /root ` is a tmpfs.
531+
532+ ### The ` .bootc-aleph.json ` file
533+
534+ After installation, bootc writes a JSON file at the root of the physical
535+ filesystem (` .bootc-aleph.json ` ) containing installation provenance information:
536+
537+ - The source image reference and digest
538+ - Installation timestamp
539+ - bootc version
540+ - Kernel version
541+ - SELinux state
542+
543+ This file is useful for auditing and understanding how a system was provisioned.
544+ From the booted system, this file is accessible at ` /sysroot/.bootc-aleph.json ` .
0 commit comments