Image Builder
Image Builder is a system image building tool provided by Red Hat-based distributions. It creates custom OS images for various platforms, including ISO, qcow2 (KVM/OpenStack), AMI (AWS), VMDK (VMware), and more. This guide covers installing Image Builder, creating blueprints with both the cockpit-composer web interface and the composer-cli command-line tool, building images, and customizing configurations.
Image Builder Overview
Section titled “Image Builder Overview”Image Builder consists of two main components:
- osbuild-composer — The backend build service responsible for the actual image creation
- composer-cli — Command-line tool for managing blueprints and build tasks
- cockpit-composer — A graphical plugin for the Cockpit web interface
Supported Output Formats
Section titled “Supported Output Formats”| Format | Use Case |
|---|---|
qcow2 | KVM / OpenStack / general virtualization |
vmdk | VMware |
vhd | Microsoft Azure / Hyper-V |
ami | Amazon Web Services |
iso | Bootable installation ISO |
tar | Generic tar archive |
gce | Google Cloud Platform |
raw | Raw disk image |
Installing Image Builder
Section titled “Installing Image Builder”sudo dnf install osbuild-composer composer-cli -ysudo dnf install cockpit cockpit-composer -ysudo systemctl enable --now osbuild-composer.socketsudo systemctl enable --now cockpit.socketsudo firewall-cmd --permanent --add-service=cockpitsudo firewall-cmd --reloadAfter installation, access the Cockpit graphical interface via browser at https://<server-IP>:9090.
sudo usermod -aG weldr $(whoami)newgrp weldrcomposer-cli status showBlueprint Management
Section titled “Blueprint Management”A blueprint is a TOML-format configuration file that defines the packages and settings to include in an image.
Creating a Blueprint
Section titled “Creating a Blueprint”cat > /tmp/my-server.toml << 'EOF'name = "my-server"description = "Custom server image for production deployment"version = "1.0.0"distro = ""
# Packages to include[[packages]]name = "vim-enhanced"version = "*"
[[packages]]name = "wget"version = "*"
[[packages]]name = "curl"version = "*"
[[packages]]name = "chrony"version = "*"
[[packages]]name = "bash-completion"version = "*"
[[packages]]name = "net-tools"version = "*"
[[packages]]name = "tmux"version = "*"
[[packages]]name = "htop"version = "*"
# Package groups[[groups]]name = "core"
# Custom kernel parameters (optional)[customizations.kernel]append = "net.ifnames=0"
# Set timezone[customizations.timezone]timezone = "America/New_York"ntpservers = ["time.google.com", "time.cloudflare.com"]
# Set locale[customizations.locale]languages = ["en_US.UTF-8"]keyboard = "us"
# Create user[[customizations.user]]name = "admin"description = "Admin user"password = "$6$rounds=4096$randomsalt$hashedpassword"groups = ["wheel"]
# Firewall settings[customizations.firewall]ports = ["22:tcp", "80:tcp", "443:tcp"]
# Service configuration[customizations.services]enabled = ["chronyd", "sshd", "firewalld"]disabled = ["postfix"]EOFcomposer-cli blueprints push /tmp/my-server.tomlManaging Blueprints
Section titled “Managing Blueprints”composer-cli blueprints listcomposer-cli blueprints show my-servercomposer-cli blueprints depsolve my-servercomposer-cli blueprints save my-servercomposer-cli blueprints delete my-serverModifying Blueprints
Section titled “Modifying Blueprints”The workflow for modifying a blueprint is: export -> edit -> re-push.
composer-cli blueprints save my-servervi my-server.tomlcomposer-cli blueprints push my-server.tomlBuilding Images
Section titled “Building Images”Starting a Build
Section titled “Starting a Build”composer-cli compose start my-server qcow2composer-cli compose start my-server isocomposer-cli compose start my-server amicomposer-cli compose start my-server vmdkcomposer-cli compose start my-server vhdMonitoring Build Progress
Section titled “Monitoring Build Progress”composer-cli compose listcomposer-cli compose statusBuild states progress through: WAITING -> RUNNING -> FINISHED or FAILED.
Downloading Build Results
Section titled “Downloading Build Results”composer-cli compose image <UUID>Replace <UUID> with the actual UUID of the build task (obtained from composer-cli compose list).
composer-cli compose logs <UUID>composer-cli compose metadata <UUID>Cleaning Up Build Records
Section titled “Cleaning Up Build Records”composer-cli compose delete <UUID>Advanced Blueprint Configuration
Section titled “Advanced Blueprint Configuration”Including Custom Files
Section titled “Including Custom Files”You can embed custom configuration files directly in the blueprint:
cat >> /tmp/my-server.toml << 'EOF'
# Custom files[[customizations.files]]path = "/etc/motd"data = "Welcome to My Custom Server\n"
[[customizations.files]]path = "/etc/sysctl.d/99-custom.conf"data = "vm.swappiness=10\nnet.core.somaxconn=65535\n"EOFSetting the Hostname
Section titled “Setting the Hostname”[customizations.hostname]hostname = "prod-server-01"Web Server Blueprint Example
Section titled “Web Server Blueprint Example”cat > /tmp/web-server.toml << 'EOF'name = "web-server"description = "Nginx web server image"version = "1.0.0"
[[packages]]name = "nginx"version = "*"
[[packages]]name = "certbot"version = "*"
[[packages]]name = "python3-certbot-nginx"version = "*"
[[packages]]name = "vim-enhanced"version = "*"
[[packages]]name = "chrony"version = "*"
[customizations.services]enabled = ["nginx", "chronyd", "sshd", "firewalld"]
[customizations.firewall]ports = ["22:tcp", "80:tcp", "443:tcp"]
[customizations.timezone]timezone = "UTC"
[[customizations.user]]name = "deploy"groups = ["wheel"]EOFcomposer-cli blueprints push /tmp/web-server.tomlcomposer-cli compose start web-server qcow2Using Cockpit Composer (Web Interface)
Section titled “Using Cockpit Composer (Web Interface)”If cockpit-composer is installed, you can use the web interface for visual management:
- Open a browser and navigate to
https://<server-IP>:9090 - Log in with your system account
- Select Image Builder from the left menu
- Click Create Blueprint to create a new blueprint
- Use the search box to add required packages
- Configure customization options
- Click Create Image, select the output format, and start the build
- Download the completed image from the Images tab
Using Built Images
Section titled “Using Built Images”Using a qcow2 Image with KVM
Section titled “Using a qcow2 Image with KVM”sudo virt-install \ --name my-server \ --ram 2048 \ --vcpus 2 \ --import \ --disk path=/path/to/<UUID>-disk.qcow2 \ --os-variant almalinux9 \ --nographicsUploading an AMI to AWS
Section titled “Uploading an AMI to AWS”The built AMI image can be uploaded using the AWS CLI:
aws s3 cp <UUID>-image.raw s3://my-bucket/my-server.rawaws ec2 import-image --disk-containers "file://containers.json"Packer as an Alternative
Section titled “Packer as an Alternative”For more complex image building pipelines, consider using HashiCorp Packer. Packer supports more builders and integrates with configuration management tools.
sudo dnf install -y dnf-plugins-coresudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.reposudo dnf install packer -ypacker versionPacker uses HCL or JSON templates to define the image build process, supports QEMU, VMware, AWS, Azure, GCP, and many other builders, and integrates with Ansible, Shell scripts, and other configuration management tools.
Image Builder vs Packer comparison:
| Feature | Image Builder | Packer |
|---|---|---|
| Integration | Natively integrated with EL systems | Third-party tool |
| Learning curve | Low | Medium |
| Flexibility | Medium | High |
| CI/CD integration | Basic | Excellent |
| Multi-platform support | Good | Excellent |
| Config management | Limited | Ansible/Chef/Puppet/Shell |
Best Practices
Section titled “Best Practices”- Version control blueprints — Store TOML blueprint files in a Git repository
- Use meaningful version numbers — Update the version number each time you modify a blueprint
- Validate in test environments first — Deploy and verify built images in test environments before production
- Rebuild regularly — Include the latest security patches
- Minimize the installation — Only include required packages to reduce the attack surface
- Leverage custom files — Embed standard configurations in images to reduce post-deployment work
- Record build information — Save build UUIDs and corresponding blueprint versions