Definition
MKOSI is a tool designed to create bootable operating system trees or images. It is tailored for developers who need to build, test, and debug operating system images. Additionally, it supports generating production images with cryptographic protection. A typical use case involves adding a mkosi.default file to an existing project (e.g., written in C or Python) to facilitate creating an operating system image.
MKOSI compiles your code with the necessary development headers and tools to generate a new image. This image contains only your application and a minimal set of required packages. The resulting image can be deployed to any device using tools like casync.
MKOSI is designed to be legacy-free, which means:
- It creates GPT partition tables instead of MBR/DOS tables.
- Bootable images are designed for EFI systems, not BIOS.
- The
/etc/fstabfile is left empty, allowing tools likesystemd-nspawnto handle automatic partitioning and booting.
Image Types
Using MKOSI, the following types of images can be created:
- Raw GPT disk image with ext4 as root.
- Raw GPT disk image with btrfs as root.
- Raw GPT disk image with a read-only squashfs as root.
- A plain directory on disk containing the OS tree directly (useful for container images).
- A btrfs subvolume on disk, similar to the plain directory.
- A tarball of a plain directory.
Additional Features
For GPT-based images, the following features can be configured:
- Add a swap partition.
- Make the system bootable on EFI systems.
- Add separate partitions for
/homeand/srv. - Encrypt partitions like root,
/home, and/srvusing LUKS. - Protect the root partition with
dm-verityto prevent offline attacks. - If the image is bootable, the
dm-verityroot hash is automatically added to the kernel command line. The kernel, initial RAM disk, and kernel command line can also be cryptographically signed for UEFI Secure Boot.
MKOSI is distribution-agnostic and can create images based on various Linux distributions.
How It Works
To run MKOSI with minimal configuration, use:
$ sudo mkosi
This command creates a image.raw GPT disk image in the current directory. Note that the default distribution matches the host machine's operating system.
For more advanced control over image features, specify options via the command line. Testing different configurations in separate directories is recommended.
MKOSI File/Directory Structure
mkosi.default: The main configuration file. Specify image type, distribution, packages, etc.
mkosi.extra: If this directory exists, its contents are copied into the image. Useful for adding static files or overriding distribution defaults.
mkosi.build: A script file executed during the build process. Two images are created:
- A "build" image with compilation tools and headers.
- A final image based on the build output.
The script is executed in the build image, and the build image is discarded afterward.
mkosi.postinst: A script executed within the image (via
systemd-nspawn) at the final stages of image preparation. Ifmkosi.buildis used, this script runs twice: once in the build image and once in the final image.mkosi.nspawn: A configuration file for
systemd-nspawn, included with the final image and its checksum.mkosi.cache/: A directory used as a package cache for builds, speeding up subsequent runs.
mkosi.passphrase: Contains the passphrase for LUKS encryption. Ensure this file is not readable by other users.
mkosi.secure-boot.crt and mkosi.secure-boot.key: X.509 key pair used for signing the kernel and initrd for UEFI Secure Boot.
Usage Examples
Creating a Simple Image
Run the following command to generate a raw GPT disk image:
$ sudo mkosi
This creates an image.raw file in the current directory.
To boot the image:
$ sudo systemd-nspawn -bi image.raw
Creating a Btrfs Image
Generate a bootable GPT+Btrfs image named foobar.raw:
$ sudo mkosi -t raw_btrfs --bootable -o foobar.raw
$ sudo systemd-nspawn -bi foobar.raw
Running the Image in QEMU
Run the foobar.raw image in a QEMU virtual machine:
$ qemu-kvm -m 512 -smp 2 -bios /usr/share/edk2/ovmf/OVMF_CODE.fd -drive format=raw,file=foobar.raw
Creating a Plain Directory Image
Generate and run a plain directory image:
$ mkosi -d fedora -t directory -o quux
$ sudo systemd-nspawn -bD quux
Overwriting Existing Images
By default, MKOSI refuses to overwrite existing images. Use --force or -f to replace an existing image:
$ sudo mkosi --force
Installing Additional Packages
Specify repositories and packages during the build process:
--repositories=<url> --package <package_name>
Example Command
Generate a Debian image with specific options:
$ sudo mkosi -d debian --bootable -o ugur_mkosi --checksum --hostname ugur_mkosi \
--password 1234 --package vim -t raw_gpt --verity
Using MKOSI with Python
Installation
$ python3 -m pip install --user git+https://github.com/systemd/mkosi.git
$ git clone https://github.com/systemd/mkosi/
$ cd mkosi
$ python3 -m pip install --user --no-use-pep517 --editable .
Running MKOSI with Python
$ python3 -m mkosi -i
$ sudo systemd-nspawn -b -i image.raw
Running QEMU
Run the image in QEMU:
$ qemu-system-x86_64 -m 512 -smp 2 -bios /usr/share/ovmf/OVMF.fd -drive format=raw,file=image.raw
For faster performance, use KVM:
$ kvm -m 8192 -smp 8 -bios /usr/share/ovmf/OVMF.fd -drive format=raw,file=image.raw