# QCrows — Self-Describing VM Container Image Format **Version:** 0.2.0-draft **Status:** Draft **Date:** 2026-07-16 --- ## 1. Overview QCrows (pronounced *cue-crows*) is a self-describing container image format for VM-based container runtimes such as Kata Containers. A `.qcrows` file bundles the guest OS filesystem, kernel, initrd, UI integration metadata, build provenance, and integrity verification into a single distributable artifact. The format is inspired by OCI image manifests — the same principle of self-description applied to VM containers instead of namespace-containers. Where an OCI image has `config.json` + layers + manifest, a QCrows image has `metadata.toml` + rootfs + initrd + kernel + menu entry + build info. ### Design Goals 1. **Self-describing** — A management UI (Cockpit, etc.) can render a QCrows image's name, description, compatibility, and requirements without inspecting the filesystem contents. 2. **Build-system agnostic** — Works equally well with source-based distros (Gentoo, Source Mage, Lunar), embedded build frameworks (Buildroot, LEDE), or any custom pipeline. 3. **Integrity-verifiable** — Every component is checksummed; the entire bundle can be verified before import. 4. **Kernel-rootfs coupled** — The guest kernel and its `.config` travel alongside the rootfs they were built for, eliminating the #1 operational pain point in Kata deployments. The kernel is a **required** component — every QCrows image must include one. 5. **Cockpit-native** — The `menu.toml` entry makes QCrows images first-class citizens in the Cockpit UI, enabling drag-and-drop import with automatic UI integration. ### What QCrows Is Not - Not a container runtime — it's an image format consumed by runtimes like Kata - Not a replacement for OCI — it targets VM containers, not namespace containers - Not a package manager — it's a distribution format for pre-built images --- ## 2. Format Specification ### 2.1 Outer Container A QCrows image is a **tar archive** (uncompressed or gzip-compressed) with the `.qcrows` extension. ``` example.qcrows (uncompressed tar) example.qcrows.gz (gzip-compressed tar) example.qcrows.tar.gz (also valid) ``` The tar archive must use **PAX** (POSIX.1-2001) format for extended attributes. All paths inside the archive are relative. ### 2.2 Directory Layout ``` example.qcrows/ ├── metadata.toml # REQUIRED — image manifest ├── menu.toml # REQUIRED — Cockpit UI menu entry ├── hashes.sha256 # REQUIRED — integrity verification ├── rootfs.tar.gz # REQUIRED — guest OS filesystem ├── initrd.img # ONE OF — initial ramdisk (initrd/initramfs/cramfs) ├── initrd.cpio.gz # alternative initrd format ├── initrd.cramfs # alternative cramfs format ├── kernel/ # REQUIRED — guest kernel binary + config │ ├── vmlinuz # compressed guest kernel (one of vmlinuz/vmlinux required) │ ├── vmlinux # uncompressed guest kernel (for Dragonball, some CLH configs) │ └── config # REQUIRED — kernel .config for reproducibility and validation ├── boot-params.conf # OPTIONAL — kernel command line parameters ├── build.toml # OPTIONAL but recommended — build provenance ├── spec.md # OPTIONAL — build guide / documentation ├── firmware/ # OPTIONAL — additional firmware blobs │ └── ... └── device-tree/ # OPTIONAL — DTB files for ARM/RISC-V └── ... ``` ### 2.3 Component Specifications --- #### `metadata.toml` — Image Manifest (REQUIRED) The central manifest describing the image. This is the first file a consumer reads. ```toml [ qcrows ] format_version = "0.1.0" [ image ] name = "alpine-3.20-kata" version = "3.20.1" description = "Minimal Alpine Linux rootfs with kata-agent for Cloud Hypervisor and QEMU" arch = "x86_64" os = "linux" created_at = "2026-07-16T10:00:00Z" [ image.compatibility ] hypervisors = [ "qemu", "cloud-hypervisor" ] kata_runtime_min = "2.5" kata_runtime_max = "" [ image.resources ] min_vcpus = 1 min_memory_mb = 256 recommended_vcpus = 2 recommended_memory_mb = 1024 [ kernel ] version = "6.6.32" included = true # true if kernel/ directory is present path = "kernel/vmlinuz" # relative path within the archive [ initrd ] included = true type = "cpio-gzip" # cpio-gzip | cpio-lz4 | cpio-xz | cramfs path = "initrd.img" [ rootfs ] type = "tar-gzip" # tar-gzip | tar-xz | tar-zst path = "rootfs.tar.gz" size_mb = 42 [ agent ] name = "kata-agent" version = "2.5.0" protocol = "vsock" ``` **Field Reference:** | Section | Field | Type | Required | Description | |---------|-------|------|----------|-------------| | qcrows | format_version | string | yes | QCrows spec version | | image | name | string | yes | Human-readable image name | | image | version | string | yes | Image version (semver recommended) | | image | description | string | no | One-line description for UI | | image | arch | string | yes | Target architecture (x86_64, aarch64, riscv64, s390x, ppc64le) | | image | os | string | yes | Always "linux" for Kata | | image | created_at | string | no | ISO 8601 timestamp | | image.compatibility | hypervisors | [string] | yes | Supported VMM backends | | image.compatibility | kata_runtime_min | string | no | Minimum kata-runtime version | | image.compatibility | kata_runtime_max | string | no | Maximum kata-runtime version | | image.resources | min_vcpus | int | no | Minimum vCPU count | | image.resources | min_memory_mb | int | no | Minimum memory in MiB | | image.resources | recommended_vcpus | int | no | Recommended vCPU count | | image.resources | recommended_memory_mb | int | no | Recommended memory in MiB | | kernel | version | string | yes | Guest kernel version string | | kernel | included | bool | yes | Whether kernel/ directory is present | | kernel | path | string | conditional | Required if included=true | | initrd | included | bool | yes | Whether initrd is present | | initrd | type | string | conditional | Required if included=true | | initrd | path | string | conditional | Required if included=true | | rootfs | type | string | yes | Compression format of rootfs | | rootfs | path | string | yes | Relative path to rootfs archive | | rootfs | size_mb | int | no | Approximate uncompressed size | | agent | name | string | no | Agent binary name | | agent | version | string | no | Agent version | | agent | protocol | string | no | Communication protocol (always "vsock" for Kata) | --- #### `menu.toml` — Cockpit UI Menu Entry (REQUIRED) Defines how this image appears in the Cockpit Kata module's UI. This is the file that makes QCrows "Cockpit-native." ```toml [ menu ] label = "Alpine 3.20 Kata" category = "minimal" # minimal | server | development | embedded | hardened | custom icon = "box" # lucide-react icon name priority = 10 # lower = higher in list [ menu.details ] distro = "Alpine Linux" distro_version = "3.20" init_system = "OpenRC" # systemd | OpenRC | runit | sinit | busybox | custom package_count = 42 shell = "/bin/ash" [ menu.tags ] [ "suitable-for" ] workloads = [ "microservice", "api-gateway", "sidecar" ] environments = [ "production", "staging" ] [ menu.actions ] # Quick actions shown in the UI import = true deploy = false # Not all images support one-click deploy edit_config = true ``` **Category Values:** | Category | Description | Typical Size | |----------|-------------|-------------| | minimal | Smallest possible rootfs, single-process | < 50 MiB | | server | General-purpose server with common packages | 100–500 MiB | | development | Includes build tools, debug symbols, strace | 500 MiB–2 GiB | | embedded | Built with Buildroot/LEDE for resource-constrained targets | < 30 MiB | | hardened | Security-hardened (PaX, SELinux, musl, stripped) | 50–200 MiB | | custom | User-defined category | varies | --- #### `hashes.sha256` — Integrity Verification (REQUIRED) SHA-256 checksums for every file in the archive (except this file itself). Format follows the `sha256sum` output format. ``` 4a2b3c... metadata.toml 7f8e9d... menu.toml 1a2b3c... rootfs.tar.gz 5d6e7f... initrd.img 8a9b0c... kernel/vmlinuz 3d4e5f... kernel/config 9a0b1c... boot-params.conf 2e3f4a... build.toml ``` Verification procedure: 1. Extract the archive to a temp directory 2. Compute SHA-256 of each file listed in `hashes.sha256` 3. Compare against the stored checksums 4. Reject the image if any checksum mismatches --- #### `rootfs.tar.*` — Guest OS Filesystem (REQUIRED) A tar archive of the guest OS root filesystem. Supported compression formats: | Format | Extension | Use Case | |--------|-----------|----------| | gzip | `.tar.gz`, `.tgz` | General purpose, fastest decompression | | xz | `.tar.xz` | Smallest size, slower decompression | | zstd | `.tar.zst` | Best compression/decompression tradeoff | The rootfs must contain: - `/sbin/init` or `/usr/sbin/init` — init system - `/usr/bin/kata-agent` or `/usr/local/bin/kata-agent` — Kata agent - `/etc/resolv.conf` — DNS configuration --- #### `initrd.*` — Initial Ramdisk (ONE OF REQUIRED) The initial ramdisk loaded into VM memory at boot. At least one of initrd or cramfs must be present. | Format | Extension | Use Case | |--------|-----------|----------| | gzip cpio | `.img`, `.cpio.gz` | Most common, used by QEMU and Dragonball | | LZ4 cpio | `.cpio.lz4` | Fastest decompression, Firecracker | | XZ cpio | `.cpio.xz` | Smallest size, Cloud Hypervisor | | cramfs | `.cramfs` | Read-only compressed fs, embedded targets | --- #### `kernel/` — Guest Kernel (REQUIRED) The guest kernel is a **required** component of every QCrows image. Bundling the kernel with its rootfs eliminates the #1 source of compatibility bugs in Kata deployments — mismatched kernel/rootfs pairs cause boot failures, missing modules, and silent data corruption. Since QCrows images are typically built from source-based distros where the kernel is compiled alongside the rootfs, there is no reason to ship them separately. | File | Required | Description | |------|----------|-------------| | `vmlinuz` | one of | Compressed kernel (QEMU, Firecracker, CLH on x86) | | `vmlinux` | one of | Uncompressed ELF kernel (CLH on some arches, Dragonball) | | `config` | **required** | Kernel `.config` for build reproducibility and validation | **Kernel Validation Rules:** When importing a QCrows image, the consumer MUST: 1. **Verify kernel binary exists** — At least one of `kernel/vmlinuz` or `kernel/vmlinux` must be present 2. **Verify kernel config exists** — `kernel/config` must be present and parseable 3. **Verify kernel version** — The version string embedded in the kernel binary must match `kernel.version` in `metadata.toml` 4. **Check required Kata config options** — The kernel config must have these options enabled: - `CONFIG_VSOCKETS=y` — vsock communication for kata-agent - `CONFIG_VIRTIO=y` — virtio device support - `CONFIG_VIRTIO_PCI=y` (or `CONFIG_VIRTIO_MMIO=y`) — virtio transport - `CONFIG_DEVTMPFS=y` — device tmpfs for /dev - `CONFIG_DEVTMPFS_MOUNT=y` — auto-mount devtmpfs 5. **Check kernel format** — The binary must be a valid ELF (vmlinux) or bzImage (vmlinuz) depending on the declared type 6. **Check kernel size** — Warn if kernel exceeds 100MiB (uncompressed) or 50MiB (compressed) **Hypervisor–Kernel Format Requirements:** | VMM | Kernel Format | Required | |-----|--------------|----------| | QEMU | vmlinuz (bzImage) | x86_64 | | QEMU | vmlinux (ELF) | aarch64, s390x, ppc64le | | Cloud Hypervisor | vmlinux (ELF) | all arches | | Firecracker | vmlinux (ELF) | all arches | | Dragonball | vmlinux (ELF) | all arches | When `kernel.included = true` in `metadata.toml`, the import tool MUST: 1. Copy the kernel to `/usr/share/kata-containers/` alongside the rootfs 2. Copy the kernel config to `/usr/share/kata-containers/` for reference 3. Update the relevant `configuration.toml` to point to the new kernel path 4. If `boot-params.conf` exists, append its parameters to the hypervisor's `kernel_params` in `configuration.toml` 5. Verify the kernel version matches `kernel.version` in metadata 6. Validate required Kata config options are enabled in `kernel/config` --- #### `boot-params.conf` — Kernel Command Line (OPTIONAL) Kernel command line parameters specific to this image. One parameter per line. ```ini # boot-params.conf console=ttyS0 root=/dev/vda1 rw agent.log=debug agent.vsock_port=1024 ``` When present, the import tool appends these to the hypervisor's `kernel_params` in `configuration.toml` rather than replacing the global defaults. --- #### `build.toml` — Build Provenance (OPTIONAL, Recommended) Records how the image was built. Critical for source-based distros where reproducibility depends on knowing exact build flags and source versions. ```toml [ build ] system = "gentoo" # gentoo | sourcemage | buildroot | lunar | lede | btc | sorcery | custom timestamp = "2026-07-16T10:00:00Z" host_arch = "x86_64" target_arch = "x86_64" # may differ for cross-compilation [ build.options ] # Gentoo-specific profile = "default/linux/amd64/17.1" cflags = "-O2 -pipe -march=native" use_flags = "minimal -X -gtk -systemd kata agent vsock" # Source Mage / Sorcery-specific # grimoire = "stable" # spells = "kata-agent glibc musl busybox" # Buildroot-specific # defconfig = "kata_x86_64_defconfig" # br2_external = "/path/to/kata-br2-external" # LEDE-specific # target = "x86/64" # packages = "kata-agent ca-certificates" # Lunar-specific # moonbase = "stable" # modules = "kata-agent busybox musl" [ build.sources ] kernel_source = "https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.32.tar.xz" kernel_hash = "abc123..." agent_source = "https://github.com/kata-containers/kata-containers/archive/refs/tags/3.5.0.tar.gz" agent_hash = "def456..." [ build.reproducibility ] reproducible = true build_id = "20260716-alpine-3.20-kata-x86_64-v1" ``` **Supported Build Systems:** | ID | Name | Package Manager | Typical Use | |----|------|----------------|-------------| | `gentoo` | Gentoo Linux | Portage | Full control, hardened builds | | `sourcemage` | Source Mage GNU/Linux | Sorcery | Source-based, spell system | | `sorcery` | Sorcery (Source Mage's pm) | cast/dispel | Alias for sourcemage | | `buildroot` | Buildroot | make + kconfig | Embedded, cross-compilation | | `lunar` | Lunar Linux | lin/lrm | Source-based, rolling | | `lede` | LEDE / OpenWrt | opkg + make | Routers, embedded, IoT | | `btc` | BTC / Blinkenlights | custom | Niche / custom pipeline | | `custom` | Custom | — | Any unlisted build system | --- #### `spec.md` — Build Guide (OPTIONAL) A Markdown document describing how to reproduce or modify this image. Should include: - Step-by-step build instructions - Required host packages - Configuration choices and their rationale - Known limitations or incompatibilities - References to the build system's documentation --- #### `firmware/` — Firmware Blobs (OPTIONAL) Additional firmware files needed by the guest. Common in embedded/LEDE scenarios. Files are copied to `/usr/share/kata-containers/firmware/` during import. --- #### `device-tree/` — Device Tree Blobs (OPTIONAL) `.dtb` files for ARM or RISC-V targets. Required when the VMM doesn't support ACPI or when targeting custom hardware. --- ## 3. QCrows File Lifecycle ### 3.1 Creating a QCrows Image ``` Source Distro Build → rootfs + initrd + kernel │ ▼ qcrows-pack tool (reads metadata.toml, menu.toml, build.toml) │ ▼ example.qcrows (tar archive) ``` The `qcrows-pack` tool (see Section 4) takes a build output directory and a set of metadata files, generates the hashes, and creates the `.qcrows` archive. ### 3.2 Importing into Cockpit ``` Drag .qcrows into Cockpit UI │ ▼ 1. Extract to /tmp/qcrows-xxx/ 2. Verify hashes.sha256 3. Read metadata.toml → validate format version, arch, compatibility 4. Read menu.toml → render UI entry 5. Copy rootfs → /usr/share/kata-containers/ 6. Copy initrd → /usr/share/kata-containers/ 7. Copy kernel → /usr/share/kata-containers/ (if included) 8. Update configuration.toml with new paths + boot params 9. Register in Cockpit's image catalog ``` ### 3.3 Verification Before import, the consumer MUST: 1. Verify `hashes.sha256` integrity 2. Validate `metadata.toml` schema 3. Check `image.compatibility.hypervisors` against the host's VMM 4. Check `image.arch` against the host's architecture 5. Verify rootfs contains `/sbin/init` and `kata-agent` 6. Verify initrd format matches the `initrd.type` declaration --- ## 4. Tooling ### 4.1 `qcrows-pack` — Create a QCrows Archive ```bash qcrows-pack \ --rootfs ./build/rootfs.tar.gz \ --initrd ./build/initrd.img \ --kernel ./build/vmlinuz \ --kernel-config ./build/.config \ --metadata ./metadata.toml \ --menu ./menu.toml \ --build ./build.toml \ --boot-params ./boot-params.conf \ --output alpine-3.20-kata.qcrows ``` ### 4.2 `qcrows-verify` — Verify Integrity ```bash qcrows-verify alpine-3.20-kata.qcrows # → PASS: all checksums match # → PASS: metadata.toml valid (format_version 0.1.0) # → PASS: rootfs contains /sbin/init # → PASS: rootfs contains /usr/bin/kata-agent # → PASS: kernel version matches metadata (6.6.32) ``` ### 4.3 `qcrows-inspect` — Read Metadata Without Extraction ```bash qcrows-inspect alpine-3.20-kata.qcrows # → Name: alpine-3.20-kata # → Version: 3.20.1 # → Arch: x86_64 # → Hypervisors: qemu, cloud-hypervisor # → Kernel: 6.6.32 (included) # → Initrd: cpio-gzip (included) # → Rootfs: tar-gzip, ~42 MiB # → Build: gentoo, 2026-07-16 ``` ### 4.4 `qcrows-export` — Export to qcow2 or ISO Convert a `.qcrows` archive into a bootable disk image or live ISO. This enables three deployment scenarios beyond the standard Kata import flow: 1. **QEMU direct boot** — Export to qcow2 and boot as a standalone VM without Kata 2. **Live USB** — Write an ISO to a USB stick for portable, bootable Kata images 3. **Kata deployment from media** — ISO contains a `/kata/` directory with all components ready for host-side import #### Export to qcow2 ```bash # Auto-sized qcow2 with MBR boot qcrows-export --format qcow2 alpine-3.20-kata.qcrows -o alpine-3.20-kata.qcow2 # Fixed 2GB disk with EFI partition layout qcrows-export --format qcow2 --disk-size 2G --efi alpine-3.20-kata.qcrows -o alpine-efi.qcow2 # Boot the result qemu-system-x86_64 -m 1G -smp 2 -drive file=alpine-3.20-kata.qcow2,format=qcow2 -enable-kvm ``` The qcow2 export creates a partitioned disk image with the rootfs extracted onto an ext4 filesystem, the kernel installed in `/boot`, and an extlinux (MBR) or GRUB (EFI) bootloader configured. The disk size is auto-calculated from the compressed rootfs size with a 256MiB headroom minimum, or specified explicitly with `--disk-size`. **qcow2 export pipeline:** ``` .qcrows archive │ extract → verify hashes → locate components ▼ raw disk image (parted → mkfs → mount) │ extract rootfs onto partition │ install kernel to /boot │ generate fstab + bootloader config ▼ qcow2 conversion (qemu-img convert -c) ``` **qcow2 options:** | Option | Description | Default | |--------|-------------|---------| | `--disk-size SIZE` | Disk image size (e.g., 2G, 500M) | Auto: rootfs × 2.5 + 256M | | `--no-compress` | Disable qcow2 compression | Compressed | | `--efi` | Create GPT + EFI System Partition | MBR + extlinux | #### Export to ISO ```bash # MBR-bootable live ISO (hybrid — dd-able to USB) qcrows-export --format iso alpine-3.20-kata.qcrows -o alpine-live.iso # EFI-bootable ISO qcrows-export --format iso --efi alpine-3.20-kata.qcrows -o alpine-efi.iso # Write to USB dd if=alpine-live.iso of=/dev/sdX bs=4M status=progress && sync # Boot with QEMU qemu-system-x86_64 -m 1G -smp 2 -cdrom alpine-live.iso -enable-kvm ``` The ISO export creates a bootable optical disc image with the kernel and initrd in `/boot/`, the rootfs in `/live/`, and a complete Kata deployment bundle in `/kata/`. The ISO uses isolinux for MBR boot (with isohybrid for USB support) or GRUB for EFI boot. **ISO directory layout:** ``` iso-root/ ├── boot/ │ ├── isolinux/ │ │ ├── isolinux.bin │ │ ├── isolinux.cfg │ │ └── ldlinux.c32 │ ├── grub/ │ │ └── grub.cfg │ ├── vmlinuz # Guest kernel │ ├── initrd # Initial ramdisk │ └── config # Kernel .config ├── live/ │ ├── vmlinuz # Kernel for live boot │ ├── initrd # Initrd for live boot │ └── rootfs.tar.gz # Rootfs for live boot ├── kata/ # Kata deployment bundle │ ├── vmlinuz │ ├── rootfs.tar.gz │ ├── initrd │ ├── config │ ├── metadata.toml │ ├── menu.toml │ ├── boot-params.conf │ └── build.toml └── README.txt ``` **ISO options:** | Option | Description | Default | |--------|-------------|---------| | `--boot-label LABEL` | Volume label for the ISO | QCROWS | | `--root-label LABEL` | Label for root filesystem reference | ROOTFS | | `--efi` | Create EFI-bootable ISO with grub-mkrescue | MBR + isolinux | **Prerequisites:** | Format | Required Tools | |--------|---------------| | qcow2 | `qemu-img`, `parted`, `mkfs.ext4`, `mount`, `tar` | | iso (MBR) | `xorriso` or `genisoimage`, `isolinux`/`syslinux` | | iso (EFI) | `grub-mkrescue` | ### 4.5 `qcrows-initrd-regen` — Environment-Aware Initrd Regeneration Rebuild the initrd component of a QCrows bundle with precise awareness of the Kata Containers runtime environment. Unlike `dracut` or `mkinitramfs`, this tool produces an initrd where `kata-agent` IS the final process (no `pivot_root`, no `switch_root`) and includes ONLY the kernel modules required by the detected VMM transport layer. ```bash # Auto-detect everything from the host environment qcrows-initrd-regen alpine-3.20-kata.qcrows # Target a specific VMM with lz4 compression qcrows-initrd-regen alpine.qcrows --vmm qemu --compress lz4 # Update the bundle in-place qcrows-initrd-regen alpine.qcrows --in-place --vmm cloud-hypervisor # Custom agent binary and extra networking modules qcrows-initrd-regen gentoo.qcrows --agent /usr/bin/kata-agent \ --extra-modules "tun,veth,bridge" -o custom-initrd.img ``` **Auto-detection pipeline:** ``` .qcrows bundle │ extract → read kernel/config → read metadata.toml ▼ Environment Detection ├── VMM: kata-runtime symlink → configuration.toml → [hypervisor.*] section ├── Compression: kernel/.config → CONFIG_RD_LZ4/GZIP/XZ/ZSTD → fastest available ├── Init style: rootfs listing → /sbin/init|/sbin/openrc-init|busybox → systemd|openrc|busybox └── Agent: rootfs scan → /usr/bin/kata-agent → copy into initrd ▼ Module Selection (VMM Matrix) ├── Core: ext4, vfat, squashfs, overlay, loop, dm_mod, nls_* ├── VMM Required: e.g., QEMU → virtio_pci, virtio_blk, virtio_net, ... └── VMM Optional: only if compiled (=y or =m) in kernel config ▼ Initrd Assembly ├── Directory skeleton (bin, sbin, lib, etc, proc, sys, dev) ├── kata-agent binary + shared libraries (ldd resolution) ├── /init script (init-style-aware: systemd/openrc/busybox) ├── Kernel modules (deduplicated, exclusions applied) ├── Strip locales, docs, man, Python cache, static libs, debug symbols ▼ Archive + Compress + Validate ├── cpio newc format + selected compression ├── Validate: file exists, format matches, /init present, kata-agent present, size < 512MB └── Optional: --in-place updates the QCrows bundle and recomputes hashes ``` **VMM kernel module matrix:** | Module | QEMU | Cloud Hypervisor | Firecracker | Dragonball | |--------|------|-----------------|-------------|------------| | `virtio_pci` | Required | — | — | — | | `virtio_mmio` | — | Required | Required | — | | `virtio_blk` | Required | Required | Required | Required | | `virtio_net` | Required | Required | Required | Required | | `virtio_rng` | Required | Required | Required | Required | | `virtio_console` | Required | Required | Optional | Required | | `virtio_balloon` | Required | Required | — | Optional | | `virtio_gpu` | Required | Optional | — | Optional | | `virtio_scsi` | Optional | Optional | — | — | | `virtio_input` | Optional | — | — | — | | `virtio_crypto` | Optional | — | — | — | | `virtio_mem` | Optional | — | — | — | | `virtio_pmem` | Optional | — | — | — | | `9pnet_virtio` | Optional | Optional | — | Optional | Core modules included for all VMMs: `ext4`, `vfat`, `nls_cp437`, `nls_iso8859_1`, `dm_mod`, `dm_bufio`, `loop`, `squashfs`, `overlay`. **Compression priority order** (auto-detection selects the first supported): | Priority | Format | Config Symbol | Boot Speed | Compression Ratio | |----------|--------|--------------|------------|-------------------| | 1 | cpio-lz4 | `CONFIG_RD_LZ4` | Fastest | Moderate | | 2 | cpio-zstd | `CONFIG_RD_ZSTD` | Fast | Good | | 3 | cpio-gzip | `CONFIG_RD_GZIP` | Moderate | Good | | 4 | cpio-xz | `CONFIG_RD_XZ` | Slowest | Best | **Init style generation:** | Style | Detection Trigger | /init Behavior | |-------|------------------|----------------| | systemd | `/sbin/init` or `/sbin/systemd` in rootfs | Mount vfs → depmod → exec `/sbin/init` | | openrc | `/sbin/openrc-init` in rootfs | Mount vfs → depmod → exec `/sbin/openrc-init` | | busybox | Neither found (default) | Mount vfs → depmod → exec `/usr/bin/kata-agent` as PID 1 | **Options:** | Option | Description | Default | |--------|-------------|---------| | `--vmm VMM` | Target VMM: qemu/cloud-hypervisor/firecracker/dragonball | Auto-detect | | `--compress ALGO` | Compression: gzip/lz4/xz/zstd | Auto-detect from kernel config | | `--format FORMAT` | Force format: cpio-gzip/cpio-lz4/cpio-xz/cpio-zstd/cramfs | Auto-detect | | `--init-style STYLE` | Init system: systemd/openrc/busybox | Auto-detect from rootfs | | `--agent PATH` | Path to kata-agent binary | Auto-discover from rootfs | | `--in-place` | Replace initrd inside the QCrows bundle | Output to file | | `--extra-modules LIST` | Comma-separated additional modules | — | | `--exclude-modules LIST` | Comma-separated modules to exclude | — | | `--no-strip-locales` | Keep locale files | Stripped | | `--no-strip-docs` | Keep documentation | Stripped | | `--keep-temp` | Preserve temp directory for inspection | Cleaned up | --- ## 5. Integration with Build Systems ### 5.1 Gentoo ```bash # Build rootfs from a Gentoo stage3 with kata-agent ROOT=/tmp/gentoo-kata emerge --root=/tmp/gentoo-kata \ sys-apps/kata-agent sys-kernel/kata-kernel \ sys-apps/openrc net-dns/dnsmasq # Pack the result qcrows-pack --rootfs /tmp/gentoo-kata-rootfs.tar.gz \ --kernel /tmp/gentoo-kata/boot/vmlinuz-* \ --metadata metadata.toml --menu menu.toml \ --build build.toml --output gentoo-kata.qcrows ``` ### 5.2 Source Mage (Sorcery) ```bash # Cast the required spells cast kata-agent busybox musl # Create rootfs from the installed system # (sorcery provides sorcery queue/install for rootfs creation) qcrows-pack --rootfs ./rootfs.tar.gz \ --initrd ./initrd.img \ --metadata metadata.toml --menu menu.toml \ --build build.toml --output sourcemage-kata.qcrows ``` ### 5.3 Buildroot ```bash # Build with Kata-specific defconfig make kata_x86_64_defconfig make # Output: output/images/rootfs.tar.gz, output/images/bzImage qcrows-pack \ --rootfs output/images/rootfs.tar.gz \ --kernel output/images/bzImage \ --kernel-config output/build/linux-*/.config \ --metadata metadata.toml --menu menu.toml \ --build build.toml --output buildroot-kata.qcrows ``` ### 5.4 LEDE / OpenWrt ```bash # Build with Kata target make menuconfig # Select x86/64 target, add kata-agent package make -j$(nproc) # LEDE output: bin/targets/x86/64/rootfs.tar.gz qcrows-pack \ --rootfs bin/targets/x86/64/rootfs.tar.gz \ --kernel bin/targets/x86/64/vmlinux \ --metadata metadata.toml --menu menu.toml \ --build build.toml --output lede-kata.qcrows ``` ### 5.5 Lunar Linux ```bash # Create a minimal rootfs with Lunar's module system lin kata-agent busybox musl qcrows-pack --rootfs ./rootfs.tar.gz \ --metadata metadata.toml --menu menu.toml \ --build build.toml --output lunar-kata.qcrows ``` --- ## 6. Relationship to Existing Formats | Format | Target | Self-Describing | Includes Kernel | UI Metadata | Integrity | |--------|--------|-----------------|-----------------|-------------|-----------| | Raw rootfs.tar.gz | Kata | No | No | No | No | | Raw initrd.img | Kata | No | N/A | No | No | | OCI Image | runc/CRI-O | Yes (config.json) | No | No | Yes (digests) | | QCOW2 | QEMU | No | No | No | No | | Docker Image | Docker/Moby | Yes (manifest) | No | No | Yes (digests) | | **QCrows** | **Kata/VM** | **Yes (metadata.toml)** | **Required** | **Yes (menu.toml)** | **Yes (hashes.sha256)** | QCrows fills a specific gap: no existing format provides self-description AND kernel bundling AND UI metadata AND integrity for VM container images. --- ## 7. Versioning QCrows format versions follow semver. The `format_version` field in `metadata.toml` indicates which spec version the image conforms to. | Version | Status | Changes | |---------|--------|---------| | 0.1.0 | Draft | Initial specification | | 0.2.0 | Draft | Kernel promoted to REQUIRED; kernel config made required; added kernel validation rules (required Kata config options, version matching, format checking); added hypervisor–kernel format matrix; boot-params.conf integration with configuration.toml | | 0.2.1 | Draft | Added `qcrows-export` tool for qcow2 and ISO export; ISO layout specification with `/kata/` deployment bundle; qcow2 partitioning and bootloader configuration | | 0.2.2 | Draft | Added `qcrows-initrd-regen` tool for environment-aware initrd regeneration; VMM kernel module matrix (QEMU/CLH/Firecracker/Dragonball); compression auto-detection from kernel config; init style detection (systemd/openrc/busybox); initrd validation pipeline | Breaking changes in the format will increment the major version. Consumers MUST reject images with an unsupported `format_version`. --- ## 8. Security Considerations 1. **Hash verification** — Consumers MUST verify `hashes.sha256` before extracting any executable content from the archive. This prevents tampering in transit. 2. **Build provenance** — The `build.toml` file enables supply chain auditing. Consumers can verify that an image was built from known sources with expected flags. 3. **setuid scanning** — Import tools SHOULD warn about setuid binaries in rootfs (matches existing Kata validation rules). 4. **Kernel module loading** — The `boot-params.conf` file should be inspected for dangerous parameters (e.g., `module.sig_enforce=0`). 5. **No automatic execution** — QCrows files contain no executable hooks. Import is purely a file copy + config update operation.