Last updated:
genpack is a suite of tools for declaratively building, distributing, and booting purpose-built immutable system images based on Gentoo Linux. Rather than the traditional approach of installing an OS and then customizing it, genpack follows an image factory model where an entire OS image is built from a blueprint (JSON5).
What Docker achieved for application containers, genpack aims to achieve at the entire OS level — and across bare metal, virtual machines, and embedded devices.
| Component | Language | Role | Repository |
|---|---|---|---|
| genpack | Python + C++ | Generates SquashFS images from JSON5 configuration | wbrxcorp/genpack |
| genpack-overlay | Gentoo ebuild/profile | Package definitions, profile hierarchy, and initialization scripts | wbrxcorp/genpack-overlay |
| genpack-init | C++ + Python (pybind11) | Configures the system at every boot based on system.ini | wbrxcorp/genpack-init |
| genpack-install | C++ | Deploys images to disk/ISO/ZIP, handles self-updates | wbrxcorp/genpack-install |
| vm | C++ | Runs and manages genpack images as QEMU/KVM virtual machines | shimarin/vm |
| genpack-artifacts | JSON5 + shell scripts | A collection of concrete image definitions | genpack-artifacts (GitHub Organization) |
genpack is the core build engine of the toolchain. It takes a declarative configuration file called genpack.json5 as input and produces an optimized SquashFS image using Gentoo Linux's stage3 and Portage.
genpack uses a two-layer (lower/upper) build structure.
systemd-nspawn containerThis design ensures that compilers, header files, and other build-only artifacts remain in the lower layer and never make it into the final image. A minimal runtime image is the natural result.
{
name: "nextcloud",
profile: "paravirt",
packages: [
"www-apps/nextcloud",
"dev-db/mysql",
"dev-lang/php",
"net-misc/redis"
],
services: ["apache2", "mysqld", "redis"],
users: [{ name: "nextcloud", uid: 1000 }],
use: {
"dev-lang/php": "+mysql +curl +gd +xml +zip"
},
compression: "xz"
}
Everything — package lists, enabled services, user definitions, USE flags, and kernel configuration — is consolidated in this single file. This eliminates manual system construction and delivers fully reproducible builds.
| Command | Function |
|---|---|
genpack build | Full build (lower -> upper -> pack) |
genpack lower | Build/rebuild the lower layer |
genpack upper | Build/rebuild the upper layer |
genpack pack | Generate the SquashFS image |
genpack bash [command...] | Interactive shell / command execution inside the lower layer |
genpack archive | Create a tar.gz archive of the configuration |
x86_64, aarch64 (ARM64), i686, and riscv64 are supported. Architecture-specific settings can be managed in the arch section of genpack.json5.
GitHub: wbrxcorp/genpack-overlay
genpack-overlay is a Gentoo overlay that extends the Portage package management system. It provides metapackages that serve as building blocks for genpack images, along with a profile hierarchy that abstracts away differences between deployment targets.
Image definitions simply specify profile: "paravirt" or profile: "gnome/baremetal", and the appropriate base environment is automatically selected.
Each package can install initialization scripts under /usr/lib/genpack/package-scripts/. This is where package-specific setup tasks are defined — things like MySQL data directory initialization, Docker storage configuration, and SSH host key generation.
genpack-init is a hybrid C++ and Python (pybind11) initialization system. It starts as PID 1 and, at every boot, reads system.ini from the boot partition and executes a series of Python scripts to configure the system.
/run/initramfs/boot/system.ini (located on a FAT partition)configure(ini) function in each module under /usr/lib/genpack-init/*.py/sbin/init = systemd) via execThrough pybind11, genpack-init exposes the following low-level operations to Python scripts:
The most important design feature of genpack-init is that the entire system behavior can be customized through a single system.ini file on a FAT partition.
The genpack image's initramfs detects at boot time whether a data partition exists on the boot storage (or, in the case of QEMU, a dedicated data virtual disk) and dynamically determines the upper layer of the overlayfs root filesystem:
This mechanism allows a single image to exhibit different behaviors depending on the deployment configuration. A setup without a data partition enables "reset every time" operation suitable for kiosk terminals or demo environments, while a setup with a data partition supports persistent operation suitable for servers. In either case, genpack-init reads system.ini at every boot to configure the system, so changes to system.ini always take effect at the next boot.
GitHub: wbrxcorp/genpack-install
genpack-install writes generated system images to physical storage and makes them bootable.
| Mode | Purpose |
|---|---|
--disk=<device> | Install to a physical disk (partitioning + bootloader setup) |
| Self-update | Atomically replace the image on a running system |
--cdrom=<file> | Create a bootable ISO 9660 image |
--zip=<file> | Create a ZIP archive |
Generates and installs GRUB bootloaders for BIOS / UEFI (x86_64, i386, ARM64, RISC-V) / Raspberry Pi boot methods. El Torito CD/ISO booting is also supported.
Image updates on a running system are performed through atomic rename operations:
vm is a command-line tool for running and managing genpack system images as virtual machines on QEMU/KVM.
| Command | Function |
|---|---|
vm run <image> | Boot a VM from a system image |
vm service | Run VMs as services based on vm.ini |
vm console <name> | Connect to a VM's serial console |
vm stop <name> | Graceful shutdown via the QMP protocol |
vm list | List running VMs |
vm ssh user@vm | SSH into a VM over vsock |
vm usb | Enumerate USB devices (with XPath query support) |
GitHub Organization: genpack-artifacts
genpack-artifacts is a collection of concrete system image definitions built using the genpack toolchain. Each artifact is managed as a separate repository.
Every artifact follows a uniform directory layout:
| Category | Artifact | Purpose |
|---|---|---|
| Desktop | gnome, streamer | GNOME desktop, OBS streaming workstation |
| ML/AI | torch | PyTorch + ROCm/CUDA machine learning environment |
| Cloud | nextcloud, owncloud | Self-hosted cloud storage |
| Project Management | redmine | Redmine project management |
| Networking | vpnhub, walbrix | VPN gateway, network appliance |
| Security | suricata, borg | IDS, backup server |
| Embedded | camera | Motion-detection camera system |
| Utility | rescue, stub | System recovery, minimal build environment |
From a minimal configuration (rescue: a dozen or so packages) to a full desktop (gnome: hundreds of packages), everything is defined using the same genpack.json5 + files/ pattern.
Every image is declaratively defined in genpack.json5. Packages, USE flags, users, services, and kernel configuration are all consolidated in a single file, eliminating manual steps and delivering reproducible builds.
The final artifact is a read-only SquashFS image. System updates are performed not by modifying the existing environment, but by building a new image and atomically swapping it in. The runtime root filesystem is composed using overlayfs, and whether the upper layer is backed by persistent storage or tmpfs is automatically determined by the presence or absence of a data partition. Without a data partition, the system boots clean every time, making configuration drift impossible by design. With a data partition, persistent operation suitable for server workloads is supported.
The OS image (SquashFS) is immutable; user configuration (system.ini) is a text file on a FAT partition. Because the two are completely separate, OS updates never overwrite configuration, and changing settings requires no Linux expertise.
genpack-init reads system.ini and configures the system not just on the first boot, but at every boot. This means changes to system.ini always take effect at the next startup. Furthermore, in transient mode (no data partition), the overlayfs upper layer is tmpfs, so runtime changes are automatically discarded on reboot — the system always starts from a clean state plus whatever system.ini specifies.
By separating the lower layer (build environment) from the upper layer (runtime), compilers and headers that are unnecessary at runtime are naturally excluded.
Choosing Gentoo as the base provides:
The toolchain provides cross-cutting support for x86_64 / aarch64 / i686 / riscv64 architectures and BIOS / UEFI / Raspberry Pi boot methods.
Many tools with similar goals exist — NixOS, Yocto, Buildroot, mkosi, OSTree, among others — but genpack occupies a unique position aimed at "distributing highly optimized Linux images as appliances that non-technical users can operate."
At its core is a combination of ideas: an intentionally primitive configuration interface (INI files on FAT32), configuration applied at every boot with automatic persistence mode selection based on hardware detection, repurposing Gentoo — the quintessential mutable distribution — as raw material for immutable images, and a plugin-based init system via pybind11.
For a detailed comparison with existing tools, see A Conversation about genpack's Unique Value Proposition.
This document was written based on the following repository snapshots: