Katsu
Configuration

Configuration

Katsu images are defined using "Manifests".

A manifest is a modular YAML file that defines the content inside the image, and scripts to run when the image is built.

A manifest is made up of a number of sections, each of which is optional. However, though some sections should only be defined by a manifest that will be used as an entrypoint so the image can be functional.

Sections

builder

The builder section defines the builder module that will be used to build the image. Currently this supports dnf and bootc

The bootc builder is only supported in Katsu 0.10.0 and later. The DNF builder is the default and is used if this section is not defined.

builder: dnf # or bootc

distro

This section defines the product name of the image. It is used for ISO images to name the boot entry.

distro: Fedora 39

scripts

This section defines the scripts that will be run before and after the image is built.

They have two sub-sections, pre and post, which define the scripts to run before and after the image is built. Both of these has the same format described below.

The contents in the subsections are defined as arrays.

scripts:
    pre:
        - inline: |
            #!/bin/bash
            echo "Hello World"
        id: hello-world
        name: Hello World
        - file: ./hello-world.sh
          id: hello-world-file

scripts.*.[].inline

A string containing the script to run, can be replaced with file (optional)

scripts.*.[].file

A path to a file containing the script to run, can be replaced with inline (optional)

scripts.*.[].id

A unique identifier for the script, used for dependency trees, similar to how Ansible works (optional)

scripts.*.[].needs

A list of script IDs that must be run before this script (optional)

scripts.*.[].name

A name for the script, used for logging (optional)

scripts.*.[].chroot

Whether to run the script in a sandboxed chroot environment (optional)

By default, this value will be assumed true. If set to false, the script will be run in the host environment.

The $CHROOT environment variable will be exported for use in the script.


Files should be placed in the same directory as the manifest file that loads it. So if the manifest that loads hello-world-file is in modules/hello.yaml, the file should be in modules/hello-world.sh


The best practice is to create a separate folder for each module, and place the required files in that folder.

bootc

This section configures how Katsu will build the image based on bootc.

bootc:
  image: ghcr.io/you/your-image:latest
  derivation: /path/to/Containerfile
  context: . # OCI build context for copying files from outside the container (optional)
  embed_image: true # This is set to true by default, injects the original image into the final image's Podman storage

bootc (opens in a new tab) is an image-based paradigm for transactional OS updates, based on OCI (opens in a new tab) images. You can build an entire OS image and pack them into a Docker/OCI image, which can then be deployed into a bootable image, and updated the same way you would pull a Docker image. The bootc section is used to configure how Katsu will build the image based on bootc.

bootc.image

The base image tag to use for this build. This image must be a bootc-compatible image.

bootc.derivation

The path to the Containerfile that will be used to build a special derivation made just for this build, Relative to the current working directory.

Katsu calls podman build with the extra build argument DERIVE_FROM with the value of the base image (bootc.image), this can be used to dynamically specify the base image in the Containerfile.

An example Containerfile to be consumed by Katsu bootc mode would look like this:

ARG DERIVE_FROM
FROM $DERIVE_FROM
 
# Touch grass
RUN touch /grass
 
# You can do whatever you want here, as you would a normal Docker layer image
# This will be the final image Katsu will export as the root filesystem
 

This image will be tagged with the name of the base image, with the :katsu_deriv tag instead of whatever tag the base image has. This is done to prevent the image from being overwritten by the base image, and to allow Podman to cache this build for later use.

bootc.context

The OCI build context for copying files from outside the container. This is the same as the --context (or the standard positional) argument to podman build.

This is useful for copying files from the host into the container, such as scripts or files that are needed for the build.

bootc.embed_image

Whether to embed the original image into the final image's Podman storage. This is set to true by default. This is useful for creating self-installing images, as the original image will be embedded into the final image's Podman storage.

The image that will be embedded is the one specified in bootc.image, and will be used as the base image for the final image, not the one specified in bootc.derivation.

bootc Notes

To create self-installer images, you may need to deal with some quirks of the bootc runtime.

  1. You may require fuse-overlayfs (opens in a new tab) to be installed on the final image, as Podman and most other container runtimes cannot nest kernel-based overlayfs mounts, requiring FUSE to be used for nested overlayfs.
  2. You may need to symlink /var/tmp to /tmp in the final image, as bootc uses /var/tmp for its temporary files, This is a bootc implementation detail, and is not a Katsu issue.

dnf

This section configures the DNF package manager.

dnf:
  releasever: 39
  repodir: /etc/yum.repos.d
  options:
    - --setopt=install_weak_deps=False
    - --nogpgcheck
  exclude:
    - foo
    - bar
  packages:
    - baz
 
  arch_packages:
    x86_64:
      - baz-x86_64
    aarch64:
      - baz-aarch64

dnf.releasever

The release version DNF should pull repos from, replaces DNF's $releasever variable.

dnf.repodir

The directory to load repositories from.

dnf.options

A list of additional arguments to pass to DNF.

dnf.exclude

A list of packages to exclude from the image.

dnf.packages

A list of packages to install in the image. This can also be any DNF spec string that DNF understands, such as @core or foo.x86_64

dnf.arch_packages

A map of packages to install for each architecture. The key is the architecture, and the value is a list of packages to install.

dnf.arch_exclude

A map of packages to exclude from the image per each architecture. The key is the architecture, and the value is a list of packages to exclude from the image.

disk

This section configures the disk layout (GPT only)

disk:
  size: 8GiB
  partitions:
    - label: EFI
      size: 512MiB
      filesystem: efi
      mountpoint: /boot/efi
 
    - label: boot
      size: 1GiB
      filesystem: ext4
      mountpoint: /boot
 
    - label: root
      filesystem: ext4
      mountpoint: /

disk.size

The total size of the disk image, defined by bytesize (opens in a new tab)

disk.partitions

A list of partitions to create on the disk.

disk.partitions.[].label

The label of the partition

disk.partitions.[].size

The size of the partition, defined by bytesize (opens in a new tab)

disk.partitions.[].filesystem

The filesystem to format the partition with mkfs

disk.partitions.[].mountpoint

The mountpoint to mount the partition at relative to the root of the image.


The order of the partitions is important, as they are created in the order they are defined, however, mountpoints will be sorted by nesting level, so / will be mounted first, then /boot, then /boot/efi. This is done using a topological sort algorithm.

If the mountpoint depths are the same, they will be sorted alphabetically.


import.[]

File paths to other manifests to import and merge into the current manifest during runtime. Must be relative to the current manifest.

Not all attributes get merged when importing another manfiest. The following attributes are not merged:

  • bootloader
  • iso
  • disk
  • dnf with the exception of
    • dnf.packages
    • dnf.arch_packages
    • dnf.arch_exclude
    • dnf.options
    • dnf.exclude
    • dnf.repodir
import:
  - ./modules/hello.yaml

users.[]

A list of users to create in the image.

users.[].name

The username of the user

users.[].password

The password of the user, must be hashed using crypt(3)

users.[].uid

The UID of the user

users.[].gid

The GID of the user

users.[].groups.[]

A list of groups to add the user to

users.[].shell

The shell of the user

users.[].ssh_keys.[]

A list of SSH keys to add to the user's authorized_keys file

users.[].create_home

Whether to create the user's home directory

Must be a boolean, defaults to true

Example Manifest

# Example manifest for a Katsu build
builder: dnf
distro: Katsu Ultramarine
 
import:
  - modules/base.yaml
 
scripts:
  post:
    - id: grub-install
      name: Install GRUB
      file: modules/scripts/grub-install.sh
 
disk:
  size: 8GiB
  partitions:
    - label: EFI
      size: 512MiB
      filesystem: efi
      mountpoint: /boot/efi
 
    - label: boot
      size: 1GiB
      filesystem: ext4
      mountpoint: /boot
 
    - label: root
      # size: 2.5MiB
      filesystem: ext4
      mountpoint: /
dnf:
  releasever: 39
  repodir: repodir/
  options:
    - --setopt=cachedir=/var/cache/dnf
    - --nogpgcheck
    - --setopt=keepcache=True
  exclude:
    - fedora-release*
    - generic-release*
  packages:
    - filesystem
    - setup
    - lvm2
    - btrfs-progs
    - kernel
    - glibc
    - glibc-common
    - dnf
    - "@core"
    - NetworkManager
    - fedora-repos
 
  arch_packages:
    aarch64:
      - grub2-efi-aa64
      - grub2-efi-aa64-modules
      - grub2-efi-aa64-cdboot
      - shim-aa64
      - shim-unsigned-aarch64
      - bcm283x-firmware
      - bcm283x-overlays
      - "@arm-tools"
    x86_64:
      - grub2-efi-x64
      - grub2-efi-x64-modules
      - grub2-efi-x64-cdboot
      - grub2-pc
      - grub2-pc-modules
      - shim-x64
      - shim-unsigned-x64