This is an old revision of the document!
Table of Contents
Images
An Image in ZEDEDA Cloud is a metadata record that describes where an application image lives, what format it is, and how to verify it. ZEDEDA Cloud does not store the image binary — the edge node pulls it directly from the referenced Datastore at deployment time. Images can reference VM disk images or OCI container images.
Every image belongs to a Datastore. Before creating an image record, the Datastore must already exist.
Image Types
| image_type value | GUI Label | Used For |
|---|---|---|
IMAGE_TYPE_APPLICATION | Edge App | Application images: VM disks (qcow2, raw, vmdk) and container images (OCI). The most common type. |
IMAGE_TYPE_EVE | EVE-OS | EVE-OS firmware images for edge node onboarding and OS upgrades. See EVE-OS Images. |
Image Formats
| image_format | Category | Description |
|---|---|---|
CONTAINER | Container | OCI container image pulled from a container registry by tag or digest |
QCOW2 | VM | QEMU Copy-On-Write v2 disk image. The standard format for KVM VMs on EVE-KVM. Most common for Linux VMs. |
RAW | VM | Raw disk image. Used for EVE-OS firmware and some VM images. |
VMDK | VM | VMware disk format. Can be used on EVE-KVM with QEMU support. |
VHD / VHDX | VM | Microsoft virtual disk formats. |
OVA | VM | Open Virtualization Archive. A bundle containing a VMDK and descriptor. |
For EVE-KVM workloads, QCOW2 is the recommended format for Linux VMs. It supports thin provisioning, snapshots, and compression.
Image Architecture
| image_arch | Meaning |
|---|---|
AMD64 | x86-64 nodes (Intel/AMD). The most common for edge servers and industrial PCs. |
ARM64 | 64-bit ARM nodes (NVIDIA Jetson, Raspberry Pi 4/5, etc.). |
An image record is tied to one architecture. You need separate image records for AMD64 and ARM64 variants of the same software.
Key Fields
| Field | Required | Notes |
|---|---|---|
name | Yes | Unique across the enterprise. Cannot be changed after creation. |
title | Yes | Display name. Can be changed. |
datastore_id | Yes | Must reference an existing Datastore. |
image_type | Yes | IMAGE_TYPE_APPLICATION or IMAGE_TYPE_EVE |
image_format | Yes | CONTAINER, QCOW2, RAW, VMDK, VHD, VHDX, OVA |
image_arch | Yes | AMD64 or ARM64 |
image_rel_url | Yes | Path within the datastore to the image. For containers: the image name and tag (e.g. nodered/node-red:latest). For files: the filename relative to the datastore path. |
image_sha256 | Recommended | SHA-256 hash of the image file. EVE-OS verifies this after download. Required for file-based images; optional for containers (digest is checked by the registry). |
image_size_bytes | Recommended | Expected size in bytes. Used by ZEDEDA to track storage. Set to 0 for containers (size unknown until pull). |
project_access_list | No | Which projects can use this image. Empty list = all projects. |
Terraform Examples
Container Image (Docker Hub)
Pulling a Node-RED container image from Docker Hub via the Docker Hub datastore. No SHA or size needed — OCI layer integrity is handled by the registry.
resource "zedcloud_image" "demo_node_red_1" {
datastore_id = zedcloud_datastore.demo_docker_hub.id
image_type = "IMAGE_TYPE_APPLICATION"
image_arch = "AMD64"
image_format = "CONTAINER"
image_size_bytes = 0
name = "TF-NODE-RED-CONTAINER-IMAGE"
title = "TF-NODE-RED-CONTAINER-IMAGE"
project_access_list = []
image_rel_url = "nodered/node-red:latest"
}
Notes:
* image_rel_url is the image reference exactly as you would use in docker pull — <repo>/<image>:<tag>
* image_size_bytes = 0 is correct for containers; EVE-OS does not need the size pre-declared
* image_sha256 is omitted; OCI registries use their own layer digest verification
* The datastore_id references the Docker Hub datastore (DATASTORE_TYPE_CONTAINERREGISTRY)
* To pin to a specific digest instead of a floating tag: image_rel_url = “nodered/node-red@sha256:abc123…”
VM Image (QCOW2 from local HTTP)
Ubuntu 24.04 (Noble) cloud image served from a local HTTP datastore. SHA256 and size are both provided for integrity verification.
resource "zedcloud_image" "demo_atl_ub_image_1" {
datastore_id = zedcloud_datastore.demo_atl_ds.id
image_type = "IMAGE_TYPE_APPLICATION"
image_arch = "AMD64"
image_format = "QCOW2"
image_sha256 = "834af9cd766d1fd86eca156db7dff34c3713fbbc7f5507a3269be2a72d2d1820"
image_size_bytes = 618925568
name = "TF-ATL-UBUNTU-24-IMAGE"
title = "TF-UBUNTU-24-IMAGE"
project_access_list = []
image_rel_url = "noble-server-cloudimg-amd64.img"
}
Notes:
* image_rel_url is the filename at the root of the HTTP server (combined with ds_path from the datastore to form the full URL)
* image_sha256 — EVE-OS will verify the downloaded file against this hash. If the hash doesn't match, the download is rejected and the app instance errors
* image_size_bytes — the size in bytes of the qcow2 file. Get this with: stat -c %s noble-server-cloudimg-amd64.img (Linux) or stat -f %z
'' (macOS)
* ''image_sha256 — get this with: sha256sum noble-server-cloudimg-amd64.img (Linux) or ''shasum -a 256 '' (macOS)
- The Ubuntu cloud image is a sparse qcow2 — the file on disk (618 MB) is much smaller than the virtual disk size. EVE-OS expands it when creating the volume.
VM Image (Azure Blob)
Same Ubuntu image but sourced from Azure Blob Storage instead of a local server:
resource "zedcloud_image" "demo_az_ub_image" {
datastore_id = zedcloud_datastore.demo_az_blob_ds.id
image_type = "IMAGE_TYPE_APPLICATION"
image_arch = "AMD64"
image_format = "QCOW2"
image_sha256 = "834af9cd766d1fd86eca156db7dff34c3713fbbc7f5507a3269be2a72d2d1820"
image_size_bytes = 618925568
name = "TF-AZ-UBUNTU-24-IMAGE"
title = "TF-AZ-UBUNTU-24-IMAGE"
project_access_list = []
image_rel_url = "vms/noble-server-cloudimg-amd64.img"
}
The image_rel_url is the blob path within the container (the ds_path from the datastore definition). So the full resolved URL would be: https://<account>.blob.core.windows.net/<container>/vms/noble-server-cloudimg-amd64.img
Multiple Datastores (Fallback)
You can reference up to 3 datastores on a single image for redundancy. EVE-OS tries them in order — useful for hybrid environments where a cloud primary and local secondary exist:
resource "zedcloud_image" "demo_ub_with_fallback" {
datastore_id = zedcloud_datastore.demo_az_blob_ds.id
image_type = "IMAGE_TYPE_APPLICATION"
image_arch = "AMD64"
image_format = "QCOW2"
image_sha256 = "834af9cd766d1fd86eca156db7dff34c3713fbbc7f5507a3269be2a72d2d1820"
image_size_bytes = 618925568
name = "TF-UBUNTU-24-WITH-FALLBACK"
title = "TF-UBUNTU-24-WITH-FALLBACK"
project_access_list = []
image_rel_url = "noble-server-cloudimg-amd64.img"
# Optional: additional datastores as fallback
datastores = [
zedcloud_datastore.demo_atl_ds.id # local HTTP fallback
]
}
ZEDUI Walkthrough
- Navigate to Library > Images - Click the + icon - Identity: Name (permanent), Title, Description, Project scope - Image Type: Edge App, Docker Compose, or Compose Runtime - Image Format: Container, ISO, QCOW2, or RAW - Image Architecture: AMD64 or ARM64 - Datastore: select up to 3 datastores (primary + fallback) - Image URL: the relative path within the datastore (for files) or the image:tag (for containers) - For file-based images: provide SHA256 and Size (bytes) — these can be entered manually or via Upload/Uplink - Click Add
ZCLI
# Container image zcli image create TF-NODE-RED-CONTAINER-IMAGE \ --datastore-name=TF-ZED-DEMO-DOCKER-HUB \ --arch=AMD64 \ --image-format=container \ --image-url=nodered/node-red:latest \ --type=Application \ --title=TF-NODE-RED-CONTAINER-IMAGE # QCOW2 VM image (register the record) zcli image create TF-ATL-UBUNTU-24-IMAGE \ --datastore-name=TF-ATL-ZED-DEMO-DS \ --arch=AMD64 \ --image-format=qcow2 \ --title=TF-ATL-UBUNTU-24-IMAGE \ --type=Application # Uplink (associate the file hash and size with the record) zcli image uplink TF-ATL-UBUNTU-24-IMAGE \ --datastore-name=TF-ATL-ZED-DEMO-DS \ --image-sha=834af9cd766d1fd86eca156db7dff34c3713fbbc7f5507a3269be2a72d2d1820 \ --image-size=618925568
Note: for file-based images, image create registers the metadata and image uplink associates the SHA256 and size. These are two separate steps in ZCLI, but a single resource block in Terraform.
API
# Container image
POST /v1/images
{
"name": "TF-NODE-RED-CONTAINER-IMAGE",
"imageType": "IMAGE_TYPE_APPLICATION",
"imageArch": "AMD64",
"imageFormat": "CONTAINER",
"datastoreId": "<docker_hub_datastore_id>",
"imageRelUrl": "nodered/node-red:latest",
"imageSizeBytes": 0
}
# QCOW2 VM image
POST /v1/images
{
"name": "TF-ATL-UBUNTU-24-IMAGE",
"imageType": "IMAGE_TYPE_APPLICATION",
"imageArch": "AMD64",
"imageFormat": "QCOW2",
"datastoreId": "<http_datastore_id>",
"imageRelUrl": "noble-server-cloudimg-amd64.img",
"imageSha256": "834af9cd766d1fd86eca156db7dff34c3713fbbc7f5507a3269be2a72d2d1820",
"imageSizeBytes": 618925568
}
What Happens on the Edge Node
The image record itself is never sent to the node — only the download instruction when an app instance referencing it is deployed:
- The controller sends the app instance config to EVE-OS including the resolved image URL, credentials, format, SHA256, and size
- For CONTAINER format: EVE-OS authenticates to the registry and pulls OCI layers using the standard OCI distribution protocol. Layers are stored in EVE-OS's containerd content store and deduped across images that share base layers.
- For QCOW2 / RAW / VMDK format: EVE-OS performs an HTTP(S)/S3/SFTP GET for the image file, streams it to the local volume pool, then verifies the SHA256 hash on completion. A mismatch aborts and marks the app instance as errored.
- Once downloaded, the image is cached in EVE-OS's local storage. If another app instance on the same node references the same image, it reuses the cached copy without re-downloading.
- For QCOW2 images, EVE-OS creates a copy-on-write overlay for each app instance so multiple VMs can share the same base image without writing to it.
Getting SHA256 and Size for a VM Image
Before creating a file-based image record, you need the SHA256 hash and byte size of the file:
# Linux sha256sum noble-server-cloudimg-amd64.img stat -c %s noble-server-cloudimg-amd64.img # macOS shasum -a 256 noble-server-cloudimg-amd64.img stat -f %z noble-server-cloudimg-amd64.img # PowerShell (Windows) Get-FileHash noble-server-cloudimg-amd64.img -Algorithm SHA256 (Get-Item noble-server-cloudimg-amd64.img).length
Common VM Images for EVE-KVM
| OS | Format | Source | Notes |
|---|---|---|---|
| Ubuntu 24.04 (Noble) | QCOW2 | Ubuntu Cloud Images | noble-server-cloudimg-amd64.img — cloud-init ready |
| Ubuntu 22.04 (Jammy) | QCOW2 | Ubuntu Cloud Images | jammy-server-cloudimg-amd64.img |
| Debian 12 | QCOW2 | Debian Cloud Images | debian-12-genericcloud-amd64.qcow2 |
| Windows Server | VHDX/VMDK | Microsoft / your own | Must convert to QCOW2 with qemu-img convert for EVE-KVM |
| Red Hat / RHEL | QCOW2 | Red Hat customer portal | Must use VirtIO disk controller — change in VM settings before export |
For Windows or RHEL VMs, the disk controller must be set to VirtIO before exporting the image, or the VM will fail to find its disk on EVE-KVM.
Related Resources
* Datastores * EVE-OS Images * Edge Apps
