💽 Build Bespoke OS Images
btrfs subvolume delete
first before falling back to recursively deleting the directory.root
when running sync
scripts. This fixes an issue where we would fail when a package
manager tree or skeleton tree contained a /usr
directory as we would
not have permissions to run mount in the sandbox.QemuFirmware=uefi
now boots without
SecureBoot support, and QemuFirmware=uefi-secure-boot
was introduced
to boot with SecureBoot support. By default we will still boot with
SecureBoot support if QemuFirmware=auto
.QemuFirmwareVariables=custom
and
QemuFirmwareVariables=microsoft
to use OVMF/EDK2 variables with
either the user's custom keys enrolled or with the Microsoft keys
enrolled.UnifiedKernelImages=
to control whether we generate unified
kernel images or not.Bootloader=grub
will now generate a grub EFI image and install it.
If SecureBoot=
is enabled and ShimBootloader=
is not set to
signed
, the grub EFI image will be signed for SecureBoot.ShimBootloader=signed
will now also instruct mkosi to look for and
install already signed grub, systemd-boot, kernel and UKI binaries.$MKOSI_CONFIG
environment variable.$PROFILE
is now set for all mkosi scripts containing the value of
Profile=
if it is set.mkosi-initrd
, mkosi-tools
) can now be included
using Include=
(e.g. Include=mkosi-initrd
)mkosi-initrd
config
so there's no need anymore to copy the full mkosi-initrd
config into
/usr/lib/mkosi-initrd
.journalctl
and
coredumpctl
verbs.mkosi ssh
works again when used with ToolsTree=default
.zst
instead of .zstd
for compressed split artifacts
produced by systemd-repart
.systemd-repart
uses a persistent temporary directory again for
assembling images instead of a tmpfs.MicrocodeHost=
setting to only include the CPU specific
microcode for the current host system.PackageCacheDirectory=
to set the directory for package
manager caches. This setting defaults to a suitable location in the
system or user directory depending on how mkosi is invoked.
CacheDirectory=
is only used for incremental cached images now./var
so
that incremental images and extension images can reuse the same
snapshot. When building an image intended to be used with
BaseTrees=
, disable CleanPackageMetadata=
to make sure the
repository metadata in /var
is not cleaned up, otherwise any
extension images using this image as their base tree will not be able
to install additional packages.CacheOnly=metadata
. Note that in the JSON output, the
value of CacheOnly=
will now be a string instead of a boolean.CompressLevel=
to set the compression level to use.TriggerMatch=
to specify multiple match sections of which only
one should be satisfied.jq
, attr
, acl
, git
, sed
, grep
and findutils
to
the default tools tree.mkosi-install
, mkosi-upgrade
, mkosi-remove
and
mkosi-reinstall
scripts which allow writing scripts that are
independent of the package manager being used to build the image.Match
section values/etc/fstab
and /etc/crypttab
for the image if any
partition definitions contain the corresponding settings
(MountPoint=
and EncryptedVolume=
).bash
is now started in the debug shell instead of sh
.noble
.mkosi vmspawn
which boots the image with systemd-vmspawn
.
Note that systemd-vmspawn
is experimental and its interface may
still change. As such mkosi vmspawn
is also considered experimental.
Note that systemd-vmspawn
version 256
or newer is required.SyncScripts=
which can be used to update various build sources
before starting the image build.DISTRIBUTION=
and RELEASE=
environment variables are now set
when running scripts.ToolsTreeRepositories=
and ToolsTreePackageManagerTrees=
.RuntimeNetwork=
to configure the networking used when booting
the image.SecureBootKeySource=
and VerityKeySource=
to support signing
images with OpenSSL engines. Note that these settings require various
systemd tools to be version 256
or newer.CleanPackageManagerMetadata=yes
when building
directory
and tar
images.PackageDirectories=
to allow providing extra packages to be
made available during the build.KernelModulesIncludeHost
was including unnecessary
modules--mirror
specification for CentOS (and variants) and Fedora.
Previously a subdirectory within the mirror had to be specified which
prevented using CentOS and EPEL repositories from the same mirror. Now
only the URL has be specified./etc/mtab
compatibility symlink in mkosi's
sandbox.systemd-firstboot
./srv
and /mnt
are not mounted read-only anymore during builds.RepositoryKeyCheck=
for apt-based distributions.BuildSources=
are now mounted when we install packages so local
packages can be made available in the sandbox.Overlay=
is enabled as this
combination isn't supported.qemu-system-xxx
binaries are now preferred over the generic qemu
and qemu-kvm
binaries.gpg
is allowed to access /run/pscsd/pscsd.comm
on the host if it
exists to allow interaction with smartcards./work/src
anymore. Instead, the default value for BuildSources=
now mounts the current working directory to /work/src
. This means
that the current working directory is no longer implicitly included
when BuildSources=
is explicitly configured.ToolsTree=default
can be used to make sure a
recent version of systemd is used to do the image build.EnvironmentFiles=
to read environment variables from
environment files./usr
, a few directories in /etc
, /tmp
,
/var/tmp
and various directories configured in mkosi settings, all
host directories are hidden from scripts, package managers and other
tools executed by mkosi.RuntimeScratch=
to automatically mount a directory with extra
scratch space into mkosi-spawned containers and virtual machines./etc
or /usr
.SELinuxRelabel=
to specify whether to relabel selinux files
or not.mkosi qemu
can now direct kernel boot s390x
and powerpc
images.HostArchitecture=
match to match against the host
architecture.mkosi ssh
but instead use a separate key pair which can be
generated by mkosi genkey
. Users using mkosi ssh
will have to run
mkosi genkey
once to generate the necessary files to keep
mkosi ssh
working.--offline=no
anymore when we detect the
Subvolumes=
setting is used in a systemd-repart
partition
definition file. Instead, use the new RepartOffline=
option to
explicitly disable running systemd-repart
in offline mode./boot
instead of /efi
. While this will generally not be noticeable, users
with custom systemd-repart ESP partition definitions will need to add
CopyFiles=/boot:/
along with the usual CopyFiles=/efi:/
to their
ESP partition definitions. By installing UKIs/kernels/initrds to
/boot
, it becomes possible to use /boot
to populate an XBOOTLDR
partition which wasn't possible before. Note that this is also safe to
do before v20
so CopyFiles=/boot:/
can unconditionally be added to
any ESP partition definition files.QemuFirmwareVariables=
to allow specifying a custom OVMF
variables file to use.MinimumVersion=
to allow specifying the minimum required mkosi
version to build an image.ShimBootloader=
to support installing shim to the ESP.QemuVsockConnectionId=
to configure how to allocate the vsock
connection ID when QemUVsock=
is enabled.WithDocs=
for apt
.Locale=
.rpm
plugins are now disabled when building images.KernelModulesIncludeHost=
and
KernelModulesInitrdIncludeHost=
to only include modules loaded on
the host system in the image/initrd respectively.RemovePackages=
for Arch Linux.useradd
and groupadd
scripts to configure these binaries to
operate on the image during builds instead on the host.hashed:
Autologin=
feature was extended with support for arm64
,
s390x
and powerpc
architectures.SecureBootAutoEnroll=
to control automatic enrollment of secureboot
keys separately from signing systemd-boot
and generated UKIs.ImageVersion=
is no longer automatically appended to the output files,
instead this is automatically appended to Output=
if not specified and
results in the %o
specifier being equivalent to %i
or %i_%v
depending
on if ImageVersion=
is specified.journalctl
and coredumpctl
verbs for running the respective tools on built directory or disk images.burn
verb to write the output image to a block device.esp
output format, which is large similar to the existing uki
output format but wraps it in a disk image with only an ESP.Presets
were renamed to Images
. mkosi.images/
is now used instead of mkosi.presets/
, the Presets=
setting was renamed to Images=
and the Presets
section was merged into the Config
section. The old names can still be used for backwards compatibility.mkosi.profiles/
and one can be selected using the new Profile=
setting.mkosi.local.conf
before any other config files if that exists.--json
option to get the output of mkosi summary
as JSON.-a
for --autologin
..chroot
extension are now executed in the image automatically.rpm
helper script to have rpm
automatically operate on the image when running scripts.mkosi-as-caller
helper script that can be used in scripts to run commands as the user invoking mkosi.mkosi-chroot
will now start a shell if no arguments are specified.WithRecommends=
to configure whether to install recommended packages by default or not where this is supported. It is disabled by default.ToolsTreeMirror=
setting for configuring the mirror to use for the default tools tree.WithDocs=
is now enabled by default.BuildSourcesEphemeral=
to make source directories ephemeral when running scripts. This means any changes made to source directories while running scripts will be undone after the scripts have finished executing.QemuDrives=
to have mkosi create extra qemu drives and pass them to qemu when using the qemu
verb.BuildSources=
match to match against configured build source targets.PackageManagerTrees=
was moved to the Distribution
section.-kernel
or QemuKernel=
.updates-testing
repositories for Fedora.git
can be executed from mkosi scripts without running into permission errors.XDG_CACHE_HOME
, $HOME/.cache
or /var/tmp
depending on the situation.MKOSI_DNF
to override which dnf to use for building images (dnf
or dnf5
).docs/building-rpms-from-source.md
)./etc/resolv.conf
will now only be mounted for scripts when they are run with network access.$SCRIPT
was renamed to $CHROOT_SCRIPT
. $SCRIPT
can still be used
but is considered deprecated.RuntimeTrees=
setting to mount directories when booting images
via mkosi boot
, mkosi shell
or mkosi qemu
. The directories are
mounted with a uid map that maps the user invoking mkosi to the root
user so that all files in the directory appear as if owned by the root
user in the container or virtual machine and any new files created in
the directories are owned by the user invoking mkosi. To make this
work in VMs, we use VirtioFS
via virtiofsd
. Note that this
requires systemd v254 or newer to be installed in the image.mkosi qemu
via
VirtioFS
. When CONFIG_VIRTIOFS
and CONFIG_VIRTIO_PCI
are builtin
modules, no initramfs is required to make this work.Include=
or --include
to include extra configuration files
or directories.mkosi
will now exit with an error when no configuration was
provided.custom
distribution. When using custom
as the distribution, the rootfs must
be provided via base trees, skeleton trees or prepare scripts.distribution-gpg-keys
package is installed on the host.RuntimeSize=
to grow the image to a specific size before
booting it when using mkosi boot
or mkosi qemu
.MKOSI_UID
and MKOSI_GID
when running scripts which are
set to the uid and gid of the user invoking mkosi respectively. These
can be used to run commands as the user that invoked mkosi.Architecture=
matchInitrds=
are now used for grub menuentries as
well.ImageId=
and ImageVersion=
are now written to os-release as
IMAGE_ID
and IMAGE_VERSION
if provided.build
verb to the build
script again.--autologin
was broken when used in combination with
a tools tree when using a packaged version of mkosi.ToolsTreePackages=
to add extra packages to the default tools
tree.SystemdVersion=
match to match on the host's systemd versionFormat=
match to match on the configured output formatPresets=
can now be configured in global configuration files to select
which presets to build--help
to show all options againmkosi.version
is now picked up from preset and dropin directories as
well following the usual config precedence logic!
operator for lists. Instead, assign the empty string
to the list to remove all previous values.@
.QemuCdrom=
to attach the image to the virtual machine as a
CD-ROM instead of a block device.SectorSize=
to set the sector size of the disk images built by
systemd-repart.Bootloader=
option to configure which EFI bootloader to
install. Added uki
option to install just the UKI without
systemd-boot and grub
to generate grub configuration to chainload
into the built UKIs.BiosBootloader=
to configure whether grub for BIOS gets
installed or not.QemuFirmware=
to select which qemu firmware to use (OVMF,
Seabios or direct kernel boot).QemuKernel=
to specify the kernel that should be used with
direct kernel boot./var/lib/dbus/machine-id
is now removed if it was added by a package
manager postinstall script.ManifestFormat=json
to make sure the manifest is generated.SourceDateEpoch=
to enable more reproducible image builds.Seed=
to set the seed passed to systemd-repart.ToolsTree=
is set to default
, mkosi will now build a default
tools tree containing all the necessary tools to build images. The
distribution and release to use can be configured with
ToolsTreeDistribution=
and ToolsTreeRelease=
or are determined
automatically based on the image being built.uki
output format. This is similar to cpio
, except the cpio
is packaged up as a UKI with a kernel image and stub picked up from
the rootfs.