Production-ready virtual machine disk images for KubeVirt, distributed as OCI container images.
KMI provides curated, automatically updated VM disk images for running virtual machines on Kubernetes with KubeVirt. Each image is built from official upstream sources, customized for cloud environments, packaged as an OCI container image, and published to Docker Hub for easy consumption.
Key Features:
- 🔄 Automated Updates - Weekly builds ensure images include latest security patches
- 📦 OCI Distribution - Standard container registries for caching, mirroring, and air-gapped environments
- 🔐 Signed & Verified - All images signed with Cosign for supply chain security
- 🏗️ Multi-Architecture - Native amd64 and arm64 support where upstream provides
- ☁️ Cloud-Ready - Pre-configured with cloud-init and qemu-guest-agent
- 🧪 Tested - Automated testing validates boot, guest agent, and SSH connectivity
Deploy a Fedora VM on your KubeVirt cluster:
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: fedora-vm
spec:
running: true
template:
spec:
domain:
devices:
disks:
- name: containerdisk
disk:
bus: virtio
- name: cloudinitdisk
disk:
bus: virtio
resources:
requests:
memory: 2Gi
cpu: 2
volumes:
- name: containerdisk
containerDisk:
image: docker.io/containercraft/fedora:42
- name: cloudinitdisk
cloudInitNoCloud:
userData: |
#cloud-config
password: fedora
chpasswd: { expire: False }| Distribution | Version | Status | amd64 | arm64 | Image |
|---|---|---|---|---|---|
| AlmaLinux | 10 | Preview | ✅ | ✅ | containercraft/almalinux:10 |
| Arch Linux | Latest | Preview | ✅ | ❌ | containercraft/archlinux:latest |
| CentOS Stream | 10 | Preview | ✅ | ✅ | containercraft/centos:10 |
| Debian | 13 (Trixie) | Preview | ✅ | ✅ | containercraft/debian:13 |
| Fedora | 42 | Preview | ✅ | ✅ | containercraft/fedora:42 |
| Fedora CoreOS | 42 | Preview | ✅ | ✅ | containercraft/fcos:42 |
| FreeBSD | 15 Beta 2 | Preview | ✅ | ✅ | containercraft/freebsd:15 |
| Kali Linux | 2025.3 | Preview | ✅ | ❌ | containercraft/kali:latest |
| openSUSE Leap | 16 | Preview | ✅ | ✅ | containercraft/opensuse:leap-16 |
| openSUSE Tumbleweed | Rolling | Preview | ✅ | ❌ | containercraft/opensuse:tumbleweed |
| OpenWrt | 24 | Preview | ✅ | ✅ | containercraft/openwrt:24 |
| Rocky Linux | 10 | Preview | ✅ | ✅ | containercraft/rocky:10 |
| Talos Linux | 1.11 | Preview | ✅ | ✅ | containercraft/talos:1-11 |
| Ubuntu | 24.04 | Preview | ✅ | ✅ | containercraft/ubuntu:24-04 |
| VyOS | Rolling | Preview | ✅ | ❌ | containercraft/vyos:rolling |
Planned:
- Amazon Linux
- Neutrino (ContainerCraft minimal OS)
Note: All images are in Preview status while we finalize testing and promotion workflows.
graph LR
A[Upstream Source] --> B[Download]
B --> C[Customize]
C --> D[Package]
D --> E[Test]
E --> F[Sign]
F --> G[Publish]
- Download - Fetch official qcow2 images from upstream distribution mirrors
- Customize - Use libguestfs to inject cloud-init, qemu-guest-agent, and standard tooling
- Package - Wrap qcow2 disk in minimal OCI container (UBI Micro base)
- Test - Boot on KubeVirt, validate guest agent and SSH connectivity
- Sign - Generate Cosign signature for supply chain verification
- Publish - Push to Docker Hub with semantic version tags
kmi/
├── images/ # Image definitions
│ └── <flavor>/
│ ├── env.sh # Build configuration (URLs, checksums, arch)
│ └── virt.sysprep # Customization script (packages, configs)
├── hack/
│ ├── customize.sh # Main build script (libguestfs)
│ └── update.sh # Checksum updater for rolling releases
├── tests/ # BATS test suite
├── bake.hcl # Docker Buildx multi-arch configuration
└── Containerfile # OCI image wrapper
CI/CD:
- CircleCI - Builds qcow2 images on amd64/arm64 runners with large resource classes
- GitHub Actions - Tests images on kind with KubeVirt, promotes to production tags
Standard (Most distributions):
- Download compressed qcow2 from upstream
- Verify checksum
- Extract and customize with virt-sysprep
- Sparsify to reduce image size
- Package in OCI image
VyOS (Build from source):
- Clone vyos-build repository
- Build using official vyos-build container
- Extract generated qcow2
- Package without modification (no virt-sysprep)
Talos Linux (Image Factory):
- Download pre-built qcow2 from Talos Image Factory
- Package without modification (immutable OS)
- Skip SSH testing (Talos uses talosctl/gRPC API)
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: ubuntu-vm
spec:
running: true
template:
spec:
domain:
cpu:
cores: 2
memory:
guest: 4Gi
devices:
disks:
- name: containerdisk
disk:
bus: virtio
- name: cloudinitdisk
disk:
bus: virtio
volumes:
- name: containerdisk
containerDisk:
image: docker.io/containercraft/ubuntu:24-04
- name: cloudinitdisk
cloudInitNoCloud:
userData: |
#cloud-config
users:
- name: ubuntu
sudo: ALL=(ALL) NOPASSWD:ALL
ssh_authorized_keys:
- ssh-rsa AAAAB3NzaC1yc2E...See examples/vyos-basic/ for a complete VyOS router setup with dual Multus bridge interfaces (WAN/LAN).
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: talos-node
spec:
running: true
template:
spec:
domain:
cpu:
cores: 4
memory:
guest: 8Gi
devices:
disks:
- name: containerdisk
disk:
bus: virtio
volumes:
- name: containerdisk
containerDisk:
image: docker.io/containercraft/talos:1-11Note: Talos requires
talosctlfor configuration and management (no SSH).
-
Create image directory:
mkdir -p images/<distribution-name>/
-
Create
env.shwith build configuration:# Architecture-specific variables _ARCH=$(echo ${ARCH} | sed 's/amd64/x86_64/;s/arm64/aarch64/') # Download URLs BASE_URL=https://example.org/images/ DOWNLOAD_FILE=example-cloud.qcow2 # Checksums AMD64_SHA256SUM=abc123... ARM64_SHA256SUM=def456... # Optional: Skip tests SKIP=ssh # Optional: Disable customization for immutable images CUSTOMIZE=false SPARSIFY=false
-
Create
virt.sysprepwith customization commands:install git,vim,tmux,qemu-guest-agent run-command systemctl enable qemu-guest-agent -
Add to
bake.hcl:target "distribution-version" { inherits = ["defaults"] platforms = ["linux/amd64", "linux/arm64"] tags = [ tag("distribution", "version"), tag("distribution", "latest"), ] args = { FLAVOR = "distribution-version" } }
-
Add to CircleCI (
.circleci/config.yml):aliases: distribution-flavors: &_distribution-flavors - distribution-version workflows: build-and-publish-dev: jobs: - customize: matrix: parameters: flavor: *_distribution-flavors arch: [amd64, arm64] - cradle: requires: - customize-<< matrix.flavor >>-amd64 - customize-<< matrix.flavor >>-arm64 matrix: parameters: flavor: *_distribution-flavors
-
Test locally:
FLAVOR=distribution-version ARCH=amd64 bash hack/customize.sh docker buildx bake distribution-version --load
-
Submit PR with your changes
# Test customization script
FLAVOR=ubuntu-24-04 ARCH=amd64 bash hack/customize.sh
# Build OCI image locally
docker buildx bake ubuntu-24-04 --load
# Test with KubeVirt
kubectl apply -f tests/vmi.yaml
# Run test suite
FLAVOR=ubuntu-24-04 bats tests/run.batsImages are tested automatically on every build:
- Pod Ready - VM pod reaches Ready state
- Guest Agent - qemu-guest-agent responds via virtctl
- SSH Access - Public key authentication succeeds (skipped for Talos/OpenWrt)
Skip SSH test for distributions without SSH by default:
SKIP=sshNative multi-arch (amd64 + arm64):
- AlmaLinux, CentOS, Debian, Fedora, FCOS, FreeBSD, openSUSE Leap, OpenWrt, Rocky, Talos, Ubuntu
amd64 only (upstream limitation):
- Arch Linux, openSUSE Tumbleweed, VyOS
Planned arm64 support:
- VyOS (waiting for upstream arm64 builds)
All production images are signed with Cosign:
# Verify image signature
cosign verify docker.io/containercraft/ubuntu:24-04 \
--certificate-identity-regexp='https://github.com/ContainerCraft/kmi/.*' \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com- Checksums - All downloads verified against upstream SHA256/SHA512
- Reproducible - Builds use pinned versions and checksums
- Signed - Sigstore keyless signing with GitHub OIDC
- Transparent - Full build logs available in CI
Q: Why use OCI images for VM disks? A: Container registries provide caching, mirroring, and air-gapped support. Images can be pre-pulled to nodes and version-pinned for production stability.
Q: Can I use these with standalone QEMU/KVM? A: Yes! Extract the qcow2 from the OCI image:
docker create --name tmp containercraft/ubuntu:24-04
docker cp tmp:/disk/ubuntu-24-04.qcow2 ./ubuntu.qcow2
docker rm tmpQ: How do I pin to a specific build? A: Use image digest instead of tag:
image: docker.io/containercraft/ubuntu@sha256:abc123...Q: What's the difference between Preview and Stable? A: Preview images boot successfully but may have incomplete testing or customization. Stable images meet all criteria in our original README including metadata, testing, and documentation.
Q: Do images include proprietary drivers? A: No. Images use only upstream packages. Install proprietary drivers post-boot via cloud-init if needed.
This project is licensed under GPLv3. See LICENSE for details.
All packaged distributions retain their original licenses:
- AlmaLinux: BSD-3-Clause
- Arch Linux: Multiple (see Arch Linux Licensing)
- CentOS: Multiple open-source licenses
- Debian: DFSG-compliant licenses
- Fedora: Multiple open-source licenses
- FreeBSD: BSD-2-Clause
- openSUSE: Multiple open-source licenses
- OpenWrt: GPL-2.0
- Rocky Linux: BSD-3-Clause
- Talos: MPL-2.0
- Ubuntu: Mixed (mostly GPL/Apache/BSD)
- VyOS: GPL-3.0
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Contributing: See CONTRIBUTING.md (coming soon)
Built with:
- KubeVirt - Virtual machines on Kubernetes
- libguestfs - VM disk image modification
- Docker Buildx - Multi-architecture builds
- Cosign - Container signing and verification
- CircleCI - CI/CD platform
Special thanks to all upstream distribution maintainers for providing official cloud images.