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.
| Path | OS | Built by | Start it from |
|---|---|---|---|
| Import an upstream cloud image | Linux | Zorvia (CDI import) | Create VM → "Download an OS image", or zorvia guest image-bundle |
| Capture a VM you customized | Any | Zorvia (CDI clone of the VM disk) | VM details → create image |
| Build an unattended, sysprepped image | Windows | Kryton (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 ascapabilities.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
DataSourcein Kryton's image namespace (kryton-imagesby 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:
| Path | When to use | What happens |
|---|---|---|
| ContainerDisk | Demo / quick create | VM references quay.io/... directly; the node pulls at start. No PVC import. |
CDI golden (zorvia guest image-bundle) | Shared golden library, rollback, many VMs | Import 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)​
| Distro | Image |
|---|---|
| Ubuntu | quay.io/containerdisks/ubuntu:26.04, :24.04, :22.04 |
| Fedora | quay.io/containerdisks/fedora:44, :43 |
| CentOS Stream | quay.io/containerdisks/centos-stream:10, :9 |
| Debian | quay.io/containerdisks/debian:13, :12 |
| AlmaLinux | quay.io/containerdisks/almalinux:10, :9 |
| openSUSE | quay.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​
- Apply the versioned
DataVolumeand wait until CDI import reaches Succeeded. - Validate the imported PVC with a disposable VM.
- Apply the stable
DataSourcealias only after validation succeeds. - 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.