Skip to main content

Golden images

Zorvia has three ways to make a golden image. All of them end as a CDI DataSource that new VMs clone. The Golden Images page in the console (/app/golden-images) shows all three.

PathOSBuilt byStart it from
Import an upstream cloud imageLinuxZorvia (CDI import)Create VM → "Download an OS image", or zorvia guest image-bundle
Capture a VM you customizedAnyZorvia (CDI clone of the VM disk)VM details → create image
Build an unattended, sysprepped imageWindowsKryton (dockur install, Sysprep, qcow2 capture)Golden Images → Build

Windows golden images (via Kryton)​

Kryton installs Windows unattended in a dockur container, generalizes it with Sysprep, captures a qcow2, and can then import it into KubeVirt as a CDI DataSource. Zorvia drives this through its server-side Kryton client, so the browser never sees KRYTON_TOKEN.

Requirements:

  • Kryton integration configured (KRYTON_URL, KRYTON_TOKEN, KRYTON_PROJECT).
  • The Kryton host has docker and /dev/kvm. Kryton reports this as capabilities.goldenImages; when it is false (for example a libvirt-only Kryton), the page explains why and hides the Build form.

In the console: Golden Images → Windows golden builds, pick a Windows image, optionally a version label, and Build. The table polls while the build installs, runs Sysprep and captures. When a build is ready:

  • Bootstrap imports the qcow2 into a CDI DataSource in Kryton's image namespace (kryton-images by default), so Kryton machines can clone it.
  • Passport shows the guestkit Cutover Passport (BitLocker, VirtIO drivers, activation, blockers) when guestkit ran on the build host. A low score is informational; it does not block Bootstrap.

The same through the API:

curl -sk -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"imageId":"windows-11-enterprise","auto":true}' \
"https://HOST:30152/api/v1/kryton/golden?project=default"
curl -sk -H "Authorization: Bearer $TOKEN" https://HOST:30152/api/v1/kryton/golden
curl -sk -X POST -H "Authorization: Bearer $TOKEN" \
"https://HOST:30152/api/v1/kryton/golden/$BUILD_ID/bootstrap?project=default"

Starting a build or a bootstrap needs the vm.create permission, the same as capturing a VM. The dockur viewer URL on a build (consoleUrl) points at the Kryton host and is not proxied through Zorvia.

Kryton rejects Linux image IDs here; use the import or capture paths below for Linux.

Deploy Linux images (containerdisk + CDI golden)​

Zorvia supports two ways to boot major Linux distros from upstream quay.io/containerdisks:

PathWhen to useWhat happens
ContainerDiskDemo / quick createVM references quay.io/... directly; the node pulls at start. No PVC import.
CDI golden (zorvia guest image-bundle)Shared golden library, rollback, many VMsImport once into a versioned PVC + stable DataSource; VMs clone from that.

Create VM (GET /api/images) lists ready containerdisks. Golden CDI YAML is generated by zorvia guest image-bundle (http or docker:// registry sources).

The web console's "Download an OS image" flow in Create VM does the same import without a manual kubectl apply: POST /api/images/cloud/download resolves a catalog entry to an HTTP or registry source, builds the same DataVolume/DataSource bundle as image-bundle, and applies both directly to the cluster. The response's output_path is a datavolume:<name> reference — pass it straight back as the Create VM disk image once the job reaches Completed (poll GET /api/images/downloads).

Ready quay.io containerdisks (major Linux)​

DistroImage
Ubuntuquay.io/containerdisks/ubuntu:26.04, :24.04, :22.04
Fedoraquay.io/containerdisks/fedora:44, :43
CentOS Streamquay.io/containerdisks/centos-stream:10, :9
Debianquay.io/containerdisks/debian:13, :12
AlmaLinuxquay.io/containerdisks/almalinux:10, :9
openSUSEquay.io/containerdisks/opensuse-leap:16.0, :15.6, opensuse-tumbleweed:1.0.0

Rocky Linux and Alpine are not offered: quay.io/containerdisks has no such repository. | VirtIO (Windows) | quay.io/containerdisks/virtio-win (CD-ROM helper, not a root OS) |

These match the OS templates in src/templates/mod.rs and the SPA image catalog.

Instant VM (containerdisk)​

Pick an image in Create VM, or pass the quay path with format: containerdisk. No CDI import is required; KubeVirt pulls the OCI disk at VM start.

CDI golden image bundles​

zorvia guest image-bundle generates a versioned CDI DataVolume plus a stable DataSource alias. VMs can consume the stable name while promotion moves the alias to a new immutable PVC/DataVolume revision.

HTTP / HTTPS qcow2 source​

zorvia --namespace vm-images image-bundle ubuntu-golden \
--version 24.04-r2 \
--source https://images.example/ubuntu.qcow2 \
--source-type http \
--size 40Gi \
--storage-class fast \
--checksum sha256:abc123 \
--output ubuntu-golden.yaml

Registry sources (same quay containerdisks)​

Requires CDI and a working StorageClass. Namespace once, then generate + apply:

kubectl create ns vm-images

zorvia --namespace vm-images image-bundle ubuntu-golden \
--version 24.04-r1 \
--source docker://quay.io/containerdisks/ubuntu:24.04 \
--source-type registry \
--size 40Gi \
--storage-class fast \
--output ubuntu-golden.yaml

zorvia --namespace vm-images image-bundle fedora-golden \
--version 41-r1 \
--source docker://quay.io/containerdisks/fedora:44 \
--source-type registry \
--size 40Gi \
--storage-class fast \
--output fedora-golden.yaml

zorvia --namespace vm-images image-bundle debian-golden \
--version 12-r1 \
--source docker://quay.io/containerdisks/debian:12 \
--source-type registry \
--size 40Gi \
--storage-class fast \
--output debian-golden.yaml

zorvia --namespace vm-images image-bundle almalinux-golden \
--version 9-r1 \
--source docker://quay.io/containerdisks/almalinux:9 \
--source-type registry \
--size 40Gi \
--storage-class fast \
--output almalinux-golden.yaml

zorvia --namespace vm-images image-bundle rockylinux-golden \
--version 9-r1 \
--source docker://quay.io/containerdisks/rockylinux:9 \
--source-type registry \
--size 40Gi \
--storage-class fast \
--output rockylinux-golden.yaml

zorvia --namespace vm-images image-bundle centos-stream-golden \
--version 9-r1 \
--source docker://quay.io/containerdisks/centos-stream:9 \
--source-type registry \
--size 40Gi \
--storage-class fast \
--output centos-stream-golden.yaml

zorvia --namespace vm-images image-bundle alpine-golden \
--version 3.19-r1 \
--source docker://quay.io/containerdisks/alpine:3.19 \
--source-type registry \
--size 10Gi \
--storage-class fast \
--output alpine-golden.yaml

kubectl apply -f ubuntu-golden.yaml
# wait for DataVolume Succeeded, validate, then rely on the stable DataSource

To generate the full major-Linux library in one pass (set your StorageClass):

STORAGE_CLASS=fast ./fixtures/golden-images/generate-bundles.sh
kubectl apply -f fixtures/golden-images/out/

Promotion flow​

  1. Apply the versioned DataVolume and wait until CDI import reaches Succeeded.
  2. Validate the imported PVC with a disposable VM.
  3. Apply the stable DataSource alias only after validation succeeds.
  4. Keep the previous versioned PVC until rollback retention expires.

Phase 5 pipeline plan (experimental)​

For a dry-run build → scan → sign → promote plan (does not run scanners or cosign):

# Requires ZORVIA_EXPERIMENTAL=1 and ZORVIA_FEATURE_GOLDEN_PIPELINE=1 on the API
curl -sk -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"image_name":"ubuntu-golden","version":"24.04","namespace":"default"}' \
https://HOST:30152/api/v1/enterprise/golden-pipeline/plan

See PHASE5_ENTERPRISE.md.