System extension images may – dynamically at runtime — extend the base system with an overlay containing additional files.
To build system extensions with mkosi, we first have to create a base image on top of which we can build our extension.
To keep things manageable, we’ll use mkosi’s support for building multiple images so that we can build our base image and system extension in one go.
Start by creating a temporary directory with a base configuration file
mkosi.conf with some shared settings:
[Output]
OutputDirectory=mkosi.output
CacheDirectory=mkosi.cache
From now on we’ll assume all steps are executed inside the temporary directory.
Now let’s continue with the base image definition by writing the
following to mkosi.images/base/mkosi.conf:
[Output]
Format=directory
[Content]
CleanPackageMetadata=no
Packages=systemd
         udev
We use the directory output format here instead of the disk output
so that we can build our extension without needing root privileges.
Now that we have our base image, we can define a sysext that builds on
top of it by writing the following to mkosi.images/btrfs/mkosi.conf:
[Config]
Dependencies=base
[Output]
Format=sysext
Overlay=yes
[Content]
BaseTrees=%O/base
Packages=btrfs-progs
BaseTrees= points to our base image and Overlay=yes instructs mkosi
to only package the files added on top of the base tree.
We can’t sign the extension image without a key, so let’s generate one
with mkosi genkey (or write your own private key and certificate
yourself to mkosi.key and mkosi.crt respectively). Note that this
key will need to be loaded into your kernel keyring either at build time
or via MOK for systemd to accept the system extension at runtime as
trusted.
Finally, you can build the base image and the extension by running
mkosi -f. You’ll find btrfs.raw in mkosi.output which is the
extension image. You’ll also find the main image image.raw there but
it will be almost empty.
What we can do now is package up the base image as the main image, but
in another format, for example an initrd, we can do that by adding the
following to mkosi.conf:
[Output]
Format=cpio
Output=initrd
[Content]
MakeInitrd=yes
BaseTrees=%O/base
If we now run mkosi -f again, we’ll find initrd.cpio.zst in
mkosi.output with its accompanying extension still in btrfs.raw.
If you don’t have any need for a main image, you can configure
Format=none in the Output section in mkosi.conf to disable it.