809 lines
31 KiB
Markdown
Executable File
809 lines
31 KiB
Markdown
Executable File
# 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.
|