Chapter 4. Creating bootc-compatible base disk images by using bootc-image-builder


Create disk images from bootc images by using the bootc-image-builder tool. Generating these artifacts enables you to provision your containerized operating system across diverse infrastructure, including physical hardware, virtual machines, edge and cloud environments.

By using the bootc-image-builder tool, you can convert bootc images into disk images for a variety of different platforms and formats. Converting bootc images into disk images is equivalent to installing a bootc image. After you deploy these disk images to the target environment, you can update them directly from the container registry.

You can build your base images by using one of the following methods:

  • Use a local RHEL system, install the Podman tool, and build your image locally. Then, you can push the images to your private registry.
  • Use a CI/CD pipeline: Create a CI/CD pipeline that uses a RHEL-based system to build images and push them to your private registry.

The bootc-image-builder tool supports generating the following image types:

  • Disk image formats, such as ISO, that are suitable for disconnected installations.
  • Virtual disk image formats, such as:

    • QEMU copy-on-write (QCOW2)
    • Amazon Machine Image (AMI)
    • Unformatted raw disk (Raw)
    • Virtual Machine Image (VMI)

bootc-image-builder uses the local container storage by default. The tool cannot pull container images from remote registries itself. To build disk images, you must make the base bootc container image available in the system’s local container registry to mount the system’s container storage into the bootc-image-builder container so it can use containers from the system storage.

Deploying from a container image is beneficial when you run VMs or servers because you can achieve the same installation result. That consistency extends across multiple different image types and platforms when you build them from the same container image. Consequently, you can minimize the effort in maintaining operating system images across platforms. You can also update systems that you deploy from these disk images by using the bootc tool, instead of re-creating and uploading new disk images with bootc-image-builder.

Although you can deploy a rhel-9-bootc image directly, you can also create your own customized images that are derived from this bootc image. The bootc-image-builder tool takes the rhel-9-bootc OCI container image as an input.

Note

Generic base container images do not include any default passwords or SSH keys. Also, the disk images that you create by using the bootc-image-builder tool do not contain the tools that are available in common disk images, such as cloud-init. These disk images are transformed container images only.

4.2. Installing bootc-image-builder

To install the bootc-image-builder, use the Red Hat Container Registry. The bootc-image-builder is intended to be used as a container and it is not available as an RPM package in RHEL.

Prerequisites

  • The container-tools meta-package is installed. The meta-package contains all container tools, such as Podman, Buildah, and Skopeo.
  • You are authenticated to registry.redhat.io. For details, see Red Hat Container Registry Authentication.

Procedure

  1. Login to authenticate to registry.redhat.io:

    $ sudo podman login registry.redhat.io
  2. Install the bootc-image-builder tool:

    $ sudo podman pull registry.redhat.io/rhel10/bootc-image-builder

Verification

  • List all images pulled to your local system:

    $ sudo podman images
    REPOSITORY                                    TAG         IMAGE ID      CREATED       SIZE
    registry.redhat.io/rhel10/bootc-image-builder  latest      b361f3e845ea  24 hours ago  676 MB

You can use a build configuration file in the TOML or JSON format to add customizations for your resulting disk image. The container directory maps the config file to /config.toml. The customizations object defines the image modifications.

Additionally, you can embed a build configuration file, either as config.json or config.toml in the /usr/lib/bootc-image-builder directory. The system uses these default customizations unless explicitly overridden. For the JSON format, you can also pass the configuration by using stdin when you use the --config argument.

User customization

Add a user to your disk image, and optionally set an SSH key. All fields for this section are optional except for the name.

Expand
TOMLJSON
[[customizations.user]]
name = "user"
password = "password"
key = "ssh-rsa AAA ... user@email.com"
groups = ["wheel"]
{
  "customizations": {
    "user": [
      {
        "name": "user",
        "password": "password",
        "key": "ssh-rsa AAA ... user@email.com",
        "groups": [
          "wheel",
          "admins"
        ]
      }
    ]
  }
}
Kernel configuration

You can customize the kernel boot parameters in the configuration file.

Expand
TOMLJSON
[customizations.kernel]
name = "kernel-debug"
append = "nosmt=force"
{
  "customizations": {
    "kernel": {
      "append": "mitigations=auto,nosmt"
    }
  }
}
File systems configuration

You can use the file system section of the customizations to set the minimum size of the base partitions, such as / and /boot, and to create extra partitions with mount points under /var.

Expand
TOMLJSON
[[customizations.filesystem]]
mountpoint = "/"
minsize = "10 GiB"

[[customizations.filesystem]]
mountpoint = "/var/data"
minsize = "20 GiB"
{
  "customizations": {
    "filesystem": [
      {
        "mountpoint": "/",
        "minsize": "10 GiB"
      },
      {
        "mountpoint": "/var/data",
        "minsize": "20 GiB"
      }
    ]
  }
}
File system type interaction with rootfs

The root file system type (--rootfs) argument overrides the default value from the source container. It also sets the file system types for all additional mount points for the ext4, xfs, and btrfs types.

For supported mount points and sizes, the following restrictions and rules apply, unless the rootfs is btrfs:

  • You can specify / to set the minimum size of the root file system. The final size of the file system, mounted at /sysroot on a booted system, equals the value you specify in this configuration or 2x the size of the base container, whichever is larger.
  • You can specify /boot to set the minimum size of the boot partition. You can also specify subdirectories of /var, but you cannot specify symlinks in /var. For example, /var/home and /var/run are symlinks and cannot be file systems on their own.
  • /var itself cannot be a mount point. The rootfs option defines the file system type for the root file system.
  • Currently, there is no support for creating btrfs subvolumes during build time. Therefore, if the rootfs is btrfs, no custom mount points are supported under /var. You can only configure / and /boot.
Anaconda ISO (installer) configuration options

Create a Kickstart file that contains the installation commands of your choice. Then, add a Kickstart file to your ISO build to create a fully customized and automated installation medium.

Note

The following combined customizations are not supported: [customizations.user] and [customizations.installer.kickstart]. When you add a Kickstart, use a configuration file in the TOML format, because multi-line strings are prone to error.

Expand
TOMLJSON
[customizations.installer.kickstart]
contents = """
text --non-interactive
zerombr
clearpart --all --initlabel --disklabel=gpt
autopart --noswap --type=lvm
network --bootproto=dhcp --device=link --activate --onboot=on
"""
{
  "customizations": {
    "installer": {
      "kickstart": {
        "contents": "text --non-interactive\nzerombr\nclearpart --all --initlabel --disklabel=gpt\nautopart --noswap --type=lvm\nnetwork --bootproto=dhcp --device=link --activate --onboot=on"
      }
    }
  }
}
Warning

The bootc-image-builder does not add additional Kickstart commands besides the container image, which the system adds automatically to the container image. See Creating Kickstart files for more information.

Build a RHEL bootc image into a QEMU (QCOW2) image for the architecture. The RHEL base image does not include a default user. You can optionally inject a user configuration by using the --config option to run the bootc-image-builder container. Alternatively, you can configure the base image with cloud-init to inject users and SSH keys on first boot. See Users and groups configuration - Injecting users and SSH keys by using cloud-init.

Prerequisites

  • You have Podman installed on your host machine.
  • You have root access to run the bootc-image-builder tool, and run the containers in --privileged mode, to build the images.
  • You have the base bootc container image available in the systems root container registry.

Procedure

  1. Optional: Create a config.toml to configure user access, for example:

    [[customizations.user]]
    name = "user"
    password = "pass"
    key = "ssh-rsa AAA ... user@email.com"
    groups = ["wheel"]
  2. Before running the container, initialize the output folder. Use the -p argument to ensure that the command does not fail if the directory already exists:

    $ mkdir -p ./output
  3. Run bootc-image-builder. Optionally, if you want to use user access configuration, pass the config.toml as an argument.

    1. The following example creates a public QEMU disk image (QCOW2). To build a public image, you must have a container image that is available in a remote, publicly accessible registry, for example, registry.redhat.io/rhel10/bootc-image-builder:latest. The image is available to download and use without special credentials.

      $ podman run \
          --rm \
          --privileged \
          --pull=newer \
          --security-opt label=type:unconfined_t \
          -v ./config.toml:/config.toml:ro \
          -v ./output:/output \
          registry.redhat.io/rhel10/bootc-image-builder:latest \
          --type qcow2 \
          --config /config.toml \
        quay.io/<namespace>/<image>:<tag>
    2. This example creates a private QEMU disk image (QCOW2) from a local container. To build a private image, you must have a container image on your local machine, which is not available on a public registry. The local image could be an image you built yourself using a Containerfile, an image you pulled from a private, access-controlled registry that required a login, or an image you loaded from a tar file. The bootc-image-builder finds and uses the source image from your local Podman /var/lib/containers/storage storage, which is mounted into the builder container.

      $ sudo podman run \
          --rm \
          -it \
          --privileged \
          --pull=newer \
          --security-opt label=type:unconfined_t \
          -v ./config.toml:/config.toml:ro \
          -v ./output:/output \
          -v /var/lib/containers/storage:/var/lib/containers/storage \
          registry.redhat.io/rhel10/bootc-image-builder:latest \
          --type qcow2 \
          --config /config.toml \
          quay.io/<namespace>/<image>:<tag>

      You can find the .qcow2 image in the output folder.

Next steps

Use bootc-image-builder to generate a Virtual Machine Disk (VMDK) from a Red Hat Enterprise Linux bootc image. This artifact enables the deployment of a bootable container image as virtual machines on VMware vSphere.

Prerequisites

  • You have Podman installed on your host machine.
  • You have authenticated to the Red Hat Registry by using the podman login registry.redhat.io.
  • You have pulled the rhel10/bootc-image-builder container image.

Procedure

  1. Create a Containerfile with the following content:

    FROM registry.redhat.io/rhel10/rhel-bootc:latest
    RUN dnf -y install cloud-init open-vm-tools && \
    ln -s ../cloud-init.target /usr/lib/systemd/system/default.target.wants && \
    rm -rf /var/{cache,log} /var/lib/{dnf,rhsm} && \
    systemctl enable vmtoolsd.service
  2. Build the bootc image:

    # podman build . -t localhost/rhel-bootc-vmdk
  3. Before running the container, initialize the output folder. Use the -p argument to ensure that the command does not fail if the directory already exists:

    $ mkdir -p ./output
  4. Create a VMDK file from the previously created bootc image. The image must be accessible from a registry, such as registry.redhat.io/rhel10/bootc-image-builder:latest.

    # podman run \
        --rm \
        --privileged \
        -v /var/lib/containers/storage:/var/lib/containers/storage \
        -v ./output:/output \
        --security-opt label=type:unconfined_t \
        --pull newer \
        registry.redhat.io/rhel10/bootc-image-builder:latest \
        --type vmdk \
        --config /config.toml \
        localhost/rhel-bootc-vmdk:latest

    A VMDK disk file for the bootc image is stored in the output/vmdk directory.

Next steps

  • You can deploy your image.
  • You can make updates to the image and push the changes to a registry. See Managing RHEL bootc images.

Build a RHEL bootc image into a GCE image for the architecture on which you are running the commands.

The RHEL base image does not include a default user. Optionally, you can inject a user configuration by using the --config option to run the bootc-image-builder container. Alternatively, you can configure the base image with cloud-init to inject users and SSH keys on first boot. See Users and groups configuration - Injecting users and SSH keys by using cloud-init.

Prerequisites

  • You have Podman installed on your host machine.
  • You have root access to run the bootc-image-builder tool, and run the containers in --privileged mode, to build the images.

Procedure

  1. Optional: Create a config.toml to configure user access, for example:

    [[customizations.user]]
    name = "user"
    password = "pass"
    key = "ssh-rsa AAA ... user@email.com"
    groups = ["wheel"]
  2. Before running the container, initialize the output folder. Use the -p argument to ensure that the command does not fail if the directory already exists:

    $ mkdir -p ./output
  3. Run bootc-image-builder. Optionally, if you want to use user access configuration, pass the config.toml as an argument. The image must be accessible from a registry, such as registry.redhat.io/rhel10/bootc-image-builder:latest.

    1. The following is an example of creating a gce image:

      $ podman run \
          --rm \
          --privileged \
          --pull=newer \
          --security-opt label=type:unconfined_t \
          -v ./config.toml:/config.toml:ro \
          -v ./output:/output \
          -v /var/lib/containers/storage:/var/lib/containers/storage \
          registry.redhat.io/rhel10/bootc-image-builder:latest \
          --type gce \
          --config /config.toml \
        quay.io/<namespace>/<image>:<tag>

      You can find the gce image in the output folder.

Next steps

Use bootc-image-builder to generate an Amazon Machine Image (AMI) from a Red Hat Enterprise Linux bootc image. This enables the deployment of container-native operating systems as standard EC2 instances within Amazon Web Services (AWS).

Prerequisites

  • You have Podman installed on your host machine.
  • You have an existing AWS S3 bucket within your AWS account.
  • You have root access to run the bootc-image-builder tool, and run the containers in --privileged mode, to build the images.
  • You have the vmimport service role configured on your account to import an AMI into your AWS account.

Procedure

  1. Create a disk image from the bootc image.

    • Configure the user details in the Containerfile. Make sure that you assign it with sudo access.
    • Build a customized operating system image with the configured user from the Containerfile. It creates a default user without password sudo access.
  2. Optional: Configure the machine image with cloud-init. See Users and groups configuration - Injecting users and SSH keys by using cloud-init. The following is an example:

    FROM registry.redhat.io/rhel10/rhel-bootc:latest
    
    RUN dnf -y install cloud-init && \
        ln -s ../cloud-init.target /usr/lib/systemd/system/default.target.wants && \
        rm -rf /var/{cache,log} /var/lib/{dnf,rhsm}
    Note

    You can also use cloud-init to add users and additional configuration by using instance metadata.

  3. Build the bootc image. For example, to deploy the image to an x86_64 AWS machine, use the following commands:

    $ podman build -t quay.io/<namespace>/<image>:<tag> .
    $ podman push quay.io/<namespace>/<image>:<tag> .
  4. Before running the container, initialize the output folder. Use the -p argument to ensure that the command does not fail if the directory already exists:

    $ mkdir -p ./output
  5. Use the bootc-image-builder tool to create a public AMI image from the bootc container image. The image must be accessible from a registry, such as registry.redhat.io/rhel10/bootc-image-builder:latest.

    $ podman run \
      --rm \
      --privileged \
      --pull=newer \
      -v $HOME/.aws:/root/.aws:ro \
      -v /var/lib/containers/storage:/var/lib/containers/storage \
      --env AWS_PROFILE=default \
      registry.redhat.io/rhel10/bootc-image-builder:latest \
      --type ami \
      --config /config.toml \
      --aws-ami-name rhel-bootc-x86 \
      --aws-bucket rhel-bootc-bucket \
      --aws-region us-east-1 \
    quay.io/<namespace>/<image>:<tag>
    Note

    The following flags must be specified all together. If you do not specify any flag, the AMI is exported to your output directory.

    • --aws-ami-name - The name of the AMI image in AWS
    • --aws-bucket - The target S3 bucket name for intermediate storage when you are creating the AMI
    • --aws-region - The target region for AWS uploads

      The bootc-image-builder tool builds an AMI image and uploads it to your AWS S3 bucket by using your AWS credentials to push and register an AMI image after building it.

Next steps

For more details on users, groups, SSH keys, and secrets, see Managing users, groups, SSH keys, and secrets in image mode for RHEL.

You can convert a bootc image to a raw image with an MBR or GPT partition table by using bootc-image-builder.

The RHEL base image does not include a default user, so optionally, you can inject a user configuration by using the --config option to run the bootc-image-builder container. Alternatively, you can configure the base image with cloud-init to inject users and SSH keys on first boot. See Users and groups configuration - Injecting users and SSH keys by using cloud-init.

Prerequisites

  • You have Podman installed on your host machine.
  • You have root access to run the bootc-image-builder tool, and run the containers in --privileged mode, to build the images.
  • You have pulled your target container image in the container storage.

Procedure

  1. Optional: Create a config.toml to configure user access, for example:

    [[customizations.user]]
    name = "user"
    password = "pass"
    key = "ssh-rsa AAA ... user@email.com"
    groups = ["wheel"]
  2. Before running the container, initialize the output folder. Use the -p argument to ensure that the command does not fail if the directory already exists:

    $ mkdir -p ./output
  3. Run bootc-image-builder. If you want to use user access configuration, pass the config.toml as an argument. The image must be accessible from a registry, such as registry.redhat.io/rhel10/bootc-image-builder:latest.

    $ podman run \
        --rm \
        --privileged \
        --pull=newer \
        --security-opt label=type:unconfined_t \
        -v /var/lib/containers/storage:/var/lib/containers/storage \
        -v ./config.toml:/config.toml \
        -v ./output:/output \
        registry.redhat.io/rhel10/bootc-image-builder:latest \
        --type raw \
        --config /config.toml \
      quay.io/<namespace>/<image>:<tag>

    You can find the .raw image in the output folder.

Next steps

Generate a bootable ISO image by using the bootc-image-builder tool to deploy Red Hat Enterprise Linux bootc images on physical hardware or virtual machines. You can use the resulting artifact to provision systems by using standard installation media workflows, such as USB drives or virtual optical discs.

Prerequisites

  • You have Podman installed on your host machine.
  • Your host system is subscribed or you have injected repository configuration by using bind mounts to ensure the image build process can fetch RPMs.
  • You have root access to run the bootc-image-builder tool, and run the containers in --privileged mode, to build the images.

Procedure

  1. Optional: Create a config.toml to which overrides the default embedded Kickstart which performs an automatic installation.

    [customizations.installer.kickstart]
    contents = """
    text --non-interactive
    zerombr
    clearpart --all --initlabel --disklabel=gpt
    autopart --noswap --type=lvm
    network --bootproto=dhcp --device=link --activate --onboot=on
    """
  2. Before running the container, initialize the output folder. Use the -p argument to ensure that the command does not fail if the directory already exists:

    $ mkdir -p ./output
  3. Run bootc-image-builder to create a public ISO image. If you do not want to add any configuration, omit the -v ./config.toml:/config.toml argument. The image must be accessible from a registry, such as registry.redhat.io/rhel10/bootc-image-builder:latest.

    $ podman run \
        --rm \
        --privileged \
        --pull=newer \
        --security-opt label=type:unconfined_t \
        -v /var/lib/containers/storage:/var/lib/containers/storage \
        -v ./config.toml:/config.toml:ro \
        -v ./output:/output \
        registry.redhat.io/rhel10/bootc-image-builder:latest \
        --type iso \
        --config /config.toml \
      quay.io/<namespace>/<image>:<tag>

    You can find the .iso image in the output folder.

Next steps

  • You can use the ISO image on unattended installation methods, such as USB sticks or Install-on-boot. The installable boot ISO contains a configured Kickstart file. See Deploying a container image by using Anaconda and Kickstart.

    Warning

    Booting the ISO on a machine with an existing operating system or data can be destructive, because the Kickstart is configured to automatically reformat the first disk on the system.

  • You can make updates to the image and push the changes to a registry. See Managing RHEL bootable images.

You can use a Kickstart file to configure various parts of the RHEL installation process, such as setting up users, customizing partitioning, and adding an SSH key. You can include the Kickstart file in an ISO build to configure any part of the installation process, except the deployment of the base image. For ISOs with bootc container base images, you can use a Kickstart file to configure all installation settings except the ostreecontainer command.

For example, you can use a Kickstart to perform either a partial installation, a full installation, or even omit the user creation. Use bootc-image-builder to build an ISO image that contains the custom Kickstart to configure your installation process.

Prerequisites

  • You have Podman installed on your host machine.
  • You have root access to run the bootc-image-builder tool, and run the containers in --privileged mode, to build the images.

Procedure

  1. Create your Kickstart file. The following Kickstart file is an example of a fully unattended Kickstart file configuration that contains user creation, and partition instructions.

    [customizations.installer.kickstart]
    contents = """
    lang en_GB.UTF-8
    keyboard uk
    timezone CET
    
    user --name <user> --password <password> --plaintext --groups <groups>
    sshkey --username <user> ssh-<type> <public key>
    rootpw --lock
    
    zerombr
    clearpart --all --initlabel
    autopart --type=plain
    reboot --eject
    """
  2. Save the Kickstart configuration in the toml format to inject the Kickstart content. For example, config.toml.
  3. Run bootc-image-builder, and include the Kickstart file configuration that you want to add to the ISO build. The bootc-image-builder automatically adds the ostreecontainer command that installs the container image.

    $ sudo podman run \
        --rm \
        -it \
        --privileged \
        --pull=newer \
        --security-opt label=type:unconfined_t \
        -v /var/lib/containers/storage:/var/lib/containers/storage \
        -v ./config.toml:/config.toml \
        -v ./output:/output \
        registry.redhat.io/rhel10/bootc-image-builder:latest \
        --type iso \
        --config /config.toml \
      quay.io/<namespace>/<image>:<tag>

    You can find the .iso image in the output folder.

Next steps

  • You can use the ISO image on unattended installation methods, such as USB sticks or Install-on-boot. The installable boot ISO contains a configured Kickstart file. See Deploying a container image by using Anaconda and Kickstart.

    Warning

    Booting the ISO on a machine with an existing operating system or data can be destructive, because the Kickstart is configured to automatically reformat the first disk on the system.

  • You can make updates to the image and push the changes to a registry. See Managing RHEL bootable images.

You can create image-mode disk images with advanced partitioning by bootc-image-builder. The image-mode disk images you create for RHEL image mode include custom mount points, custom mount options, LVM-based partitions, and LVM-based swap volumes.

With that, you can, for example, change the size of the /`and the `/boot directories by using a config.toml file. When installing the RHEL image mode on bare metal, you can benefit from all partitioning features available in the Anaconda installer.

Prerequisites

  • You have Podman installed on your host machine.
  • You have virt-install installed on your host machine.
  • You have root access to run the bootc-image-builder tool, and run the containers in --privileged mode, to build the images.

Procedure

  1. Create a config.toml file to configure custom mount options, for example:

    [[customizations.filesystem]]
    mountpoint = "/"
    minsize = "10 GiB"
    
    [[customizations.filesystem]]
    mountpoint = "/var/data"
    minsize = "20 GiB"
  2. Run bootc-image-builder, passing the config.toml as an argument.

    Note

    If you do not have the container storage mount, your image must be public.

    The following is an example of creating a public image:

    $ sudo podman run \
        --rm \
        -it \
        --privileged \
        --pull=newer \
        --security-opt label=type:unconfined_t \
        -v ./config.toml:/config.toml \
        -v ./output:/output \
        registry.redhat.io/rhel10/bootc-image-builder:latest \
        --type <image_type> \
        --config config.toml \
      quay.io/<namespace>/<image>:<tag>

Next steps

You can build bootc container images without connecting to the internet or the Red Hat content delivery network. Use the local mirror registries and the RPM repositories, then convert the container images into VM formats of your choice, such as raw, AMI, or ISO.

Using a disconnected infrastructure requires configuring your build to source container images and RPM content from local registries, for example:

  • Private container registries and RPM repositories hosted on private web servers or Red Hat Satellite.
  • Pull the base image from a local repository instead of from the internet.
  • Your Containerfile must point to a local mirror registry for the base image and use local HTTP servers for RPM content.

After using the bootc-image-builder command to transform the container into a disk image, you can deploy bootable RHEL-based systems in an air-gapped environment.

Important

Define repository configurations inside the container image you are building. You cannot use the host machine’s repository settings with bootc-image-builder. Instead, you must provide the repository configurations directly within the container image.

Prerequisites

  • A running RHEL system with Red Hat Enterprise Linux 10 deployed on the target hardware.
  • The container-tools meta-package is installed.
  • Access to a registry or a locally stored container.

Procedure

  1. Create a Containerfile. For example:

    # Base image to point to your internal registry
    FROM example.com:1234/rhel10/rhel-bootc:10.2
    
    # Configure the local repo to use the files already present in the image
    # Assuming the repo data is located at /etc/pki/repos or similar inside the image
    RUN echo -e "[local-baseos]\n\
    name=Local RHEL 10 BaseOS\n\
    baseurl=file:///path/to/repo/in/image/BaseOS\n\
    enabled=1\n\
    gpgcheck=0" > /etc/yum.repos.d/local.repo
    
    # Install your required packages using the local file source
    RUN dnf install -y firewalld && \
       dnf clean all
    
    # Ensure the kernel and bootloader are present
    # In air-gapped bootc, BIB often fails because it expects to download these.
    # Pre-installing them ensures they are part of the 'bootc' transition.
    RUN dnf install -y kernel-bootc anaconda-dracut-modules && dnf clean all
  2. Use the bootc-image-builder tool to transform the Containerfile into a bootable format, such as ISO, raw, QCOW2. See Creating bootc-compatible base disk images by using bootc-image-builder.

Troubleshooting

The raw disk images might succeed if the packages are already cached. If you build an ISO, it might trigger the osbuild-depsolve-dnf dependency solving process.

If your .repo files contain a gpgkey URL, bootc-image-builder tool attempts to fetch the gpg key during the manifest generation phase. In an air-gapped environment, check the following information:

  • Ensure the gpgkey parameter points to a reachable local HTTP server or a file path already present in the image, such as /etc/pki/rpm-gpg/.
  • Even if the dnf install command worked during the container build, because the key was already cached or skipped, the ISO creation process can re-validate these keys. An incorrect URL results in errors such as GPGKeyReadError or 404 Not Found.
  • To solve these issues, store GPG Keys locally: Instead of referencing remote URLs for GPG keys, include the keys in your container image and reference them by file:/ in your .repo files.
  • If you encounter a cannot build manifest error, double-check that every repository URL and GPG URL inside the container’s /etc/yum.repos.d/ are reachable from the network on which bootc-image-builder is running.
Red Hat logoGithubredditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat Documentation

We help Red Hat users innovate and achieve their goals with our products and services with content they can trust. Explore our recent updates.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. For more details, see the Red Hat Blog.

About Red Hat

We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

Theme

© 2026 Red Hat
Back to top