Beanie Builder is a tool for building custom OS images using OSBuild. It provides a streamlined workflow for creating customized Fedora/RHEL-based images with packages, systemd services, kickstart configurations, and more.
- Prerequisites
- Installation
- Getting Started
- Creating a Blueprint
- Blueprint Structure
- Building Images
- Workflow Commands
- Documentation References
- Host must be running on a Fedora or other RHEL-based Linux distribution OS, or Debian-based Linux distribution OS such as Ubuntu, Debian, etc.
- sudo/root access for installing dependencies
justcommand runner (installed during setup)
-
Clone this repository:
git clone <repository-url> cd beanie-builder
-
Install dependencies:
./setup-local.sh
This will install:
image-builder(OSBuild tool)qemu-kvmand virtualization toolsyq,jq,tomlq(for configuration processing)just(command runner)mise(environment manager)pykickstart(kickstart validation)
The basic workflow for building a custom OS image:
- Create a blueprint - Define your custom image configuration
- Configure build settings - Set distribution, architecture, and image type
- Build the image - Compile your blueprint into an OS image
# Create a new blueprint
just create-blueprint my-custom-image
# Build the image
just build my-custom-imageA blueprint defines what packages, customizations, and configurations should be included in your OS image.
just create-blueprint my-workstationThis creates the following structure:
blueprints/
└── my-workstation.toml
blueprint-config/
└── my-workstation.yaml
blueprint-kickstarts/
└── my-workstation/
└── kickstart.ks
blueprint-services/
└── my-workstation/
Edit blueprint-config/my-workstation.yaml:
distro: fedora-43
image-type: minimal-installer
arch: x86_64Configuration keys:
-
distro- Specifies the target distribution and version to build. Common values includefedora-43,fedora-42,rhel-9,rhel-10, etc. The distribution must be supported by OSBuild. Check available distributions in the OSBuild documentation. -
image-type- Defines the type of output image to generate. The available image types depend on the selected distribution. Common types include installer images (ISO files), disk images (raw, qcow2), and cloud images (ami, vhd, etc.). -
arch- Specifies the target architecture for the image. Common values arex86_64(64-bit Intel/AMD),aarch64(ARM 64-bit),ppc64le(PowerPC 64-bit little-endian), ands390x(IBM Z). The architecture must be supported by both the distribution and OSBuild.
Available image types for fedora-43 distro (for instance):
minimal-installer- Installation ISO with minimal packages that does not include a desktop environment.minimal-raw-zst- Minimal raw disk image in .zst compressed that's similar to "minimal-installer" image-type but without the installer.workstation-live-installer- Installation ISO that includes the GNOME desktop environment, taliored for workstations.- And more (see OSBuild documentation)
Edit blueprints/my-workstation.toml:
# Define packages to install
[[packages]]
name = "kernel"
version = "6.17*"
[[packages]]
name = "firefox"
version = "*"
[[packages]]
name = "vim"
version = "*"
# System customizations
[customizations.timezone]
timezone = "America/New_York"
[customizations.locale]
languages = ["en_US.UTF-8"]
keyboard = "us"
# User creation
[[customizations.user]]
name = "admin"
password = "$6$encrypted_password_hash"
groups = ["wheel"]Create service files in blueprint-services/my-workstation/:
Example: blueprint-services/my-workstation/my-service/my-service.service
[Unit]
Description=My Custom Service
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/my-script.sh
Restart=on-failure
[Install]
WantedBy=multi-user.targetExample: blueprint-services/my-workstation/my-service/my-script.sh
#!/bin/bash
echo "Hello from custom service!"The prepare script will automatically:
- Copy service files to
/etc/systemd/system/ - Copy scripts to
/usr/local/sbin/or/usr/local/bin/ - Enable the services
If your image type includes installer, you can customize the installation process.
Edit blueprint-kickstarts/my-workstation/kickstart.ks:
# Kickstart file for my-workstation blueprint
# Unattended installation settings
#graphical
#lang en_US.UTF-8
#keyboard us
#timezone America/New_York
#network --bootproto=dhcp --device=link --activate
#firewall --enabled
#selinux --enforcing
# Post-installation script
%post --nochroot --log=/mnt/sysimage/root/ks-post.log
# Customize MOTD
echo "Welcome to My Custom Workstation!" | tee -a /mnt/sysroot/etc/motd
# Install additional software
# dnf install -y --installroot=/mnt/sysroot my-custom-package
%endNote: Global kickstart files in blueprint-kickstarts/all/global.ks are automatically prepended to blueprint-specific kickstart files.
[[packages]]
name = "package-name"
version = "*" # or specific version like "1.2.3" or "1.2*"# Timezone
[customizations.timezone]
timezone = "America/New_York"
# Locale
[customizations.locale]
languages = ["en_US.UTF-8"]
keyboard = "us"
# Users
[[customizations.user]]
name = "username"
password = "$6$encrypted_hash"
groups = ["wheel"]
ssh_key = "ssh-rsa AAAAB3NzaC1yc2E..."Files can be added directly in the blueprint:
[[customizations.files]]
path = "/etc/motd"
mode = "0644"
data = "Welcome message"# This runs all preparation steps and builds the image
just build my-workstationThe build process:
- Validates blueprint configuration
- Validates kickstart files (if applicable)
- Prepares the blueprint (combines services, kickstart, etc.)
- Prepares blueprint config (creates mise.toml)
- Builds the image using OSBuild
# Validate configuration
just validate-blueprint-config my-workstation
# Validate kickstart files
just validate-kickstarts my-workstation
# Prepare blueprint (combine services, kickstart, etc.)
just prepare-blueprint my-workstation
# Prepare blueprint config
just prepare-blueprint-config my-workstation
# Build the image
just build-image my-workstationBuilt images are located in:
build/my-workstation/
├── my-workstation.toml # Prepared blueprint
├── my-workstation.iso # (for installer images)
└── mise.toml # Environment configuration
For installer images:
just run-image my-workstationThis will launch QEMU with the installer ISO or other image build.
| Command | Description |
|---|---|
just create-blueprint <name> |
Create a new blueprint structure |
just validate-blueprint-config <name> |
Validate blueprint configuration |
just validate-kickstarts <name> |
Validate kickstart files |
just prepare-blueprint <name> |
Prepare blueprint (combine assets) |
just prepare-blueprint-config <name> |
Prepare blueprint config |
just pre-build <name> |
Run all validation and preparation steps |
just build-image <name> |
Build the OS image |
just build <name> |
Full workflow: pre-build + build-image |
just clean <name> |
Clean build artifacts |
just run-image <name> |
Run the image in QEMU |
For complete blueprint syntax and available customizations, refer to the official OSBuild documentation:
- OSBuild Homepage: https://www.osbuild.org/
- User Guide: https://osbuild.org/docs/user-guide/introduction/
- Image Descriptions: https://osbuild.org/docs/user-guide/image-descriptions/
- Blueprint Schema Reference: https://osbuild.org/docs/user-guide/blueprint-reference/
- Customizations Reference: https://osbuild.org/docs/user-guide/blueprint-reference/#customizations
For kickstart file syntax and options:
- Fedora Kickstart Documentation: https://docs.fedoraproject.org/en-US/fedora/f36/install-guide/appendixes/Kickstart_Syntax_Reference/
- Kickstart Options Reference (pykickstart): https://pykickstart.readthedocs.io/en/latest/kickstart-docs.html
Here's a complete example blueprint for a development workstation with KDE Plasma Desktop Environment added:
blueprints/dev-workstation.toml
# Base packages
[[packages]]
name = "kernel"
version = "6.17.*"
[[packages]]
name = "systemd"
version = "*"
# Development tools
[[packages]]
name = "git"
version = "*"
[[packages]]
name = "vim"
version = "*"
[[packages]]
name = "gcc"
version = "*"
[[packages]]
name = "make"
version = "*"
# KDE Plasma 6 desktop environment
[[packages]]
name = "@kde-desktop-environment"
[[packages]]
name = "plasma-oxygen"
version = "*"
[[packages]]
name = "plasma-milou"
version = "*"
# Packages needed for support Power Management Service (required in Desktop/Laptop machines)
[[packages]]
name = "power-profiles-daemon"
version = "*"
[[packages]]
name = "upower"
version = "*"
# Essential system tools
[[packages]]
name = "firewalld"
version = "*"
# System configuration
[customizations.timezone]
timezone = "UTC"
[customizations.locale]
languages = ["en_US.UTF-8"]
keyboard = "us"
blueprint-config/dev-workstation.yaml
distro: fedora-43
image-type: minimal-installer
arch: x86_64Build it:
just build dev-workstation- Check that all required packages exist in the repository
- Verify that the base image is available to use with
just validate-blueprint-config <name>. Unsupported versions of the OSs will no longer be available to use, thus thedistrokey in your blueprint config will need to be updated to the next supported OS distro. - Check kickstart syntax with
just validate-kickstarts <name> - If you are building a raw or other disk images instead of an installer, make sure to add the following in your blueprint set disk size. (By default, the disk image size is 4GB and build will fail if the image size exceeds it.):
[customizations.disk] minsize = "12 GiB"
- Ensure service files are in
blueprint-services/<blueprint-name>/<service-name>/ - Verify service file syntax
- Check that scripts have execute permissions (0755)
- Ensure image type includes
installerin the config YAML - Verify kickstart syntax is valid
- Check that kickstart file is in
blueprint-kickstarts/<blueprint-name>/kickstart.ks
See LICENSE file for details.