Images
A virtual machine starts from a base image: a Linux cloud image registered once on the node. Each machine gets its own disk layered on top of the image, so many machines can share one image and the image itself never changes.
Part of Compute, in early access.
Which images work
- Linux cloud images that configure themselves on first boot with cloud-init from a "NoCloud" data source — the official cloud images of Debian ("genericcloud"), Ubuntu, and most other distributions. The first-boot configuration arrives on a small read-only disk labelled
cidata(what it contains). - Formats: qcow2 or raw. A raw image is converted to qcow2 on the way in.
- Self-contained files only. An image that refers to a backing file or keeps its data in a separate file is refused, as is an encrypted one.
- Up to 50 GiB per image file.
- x86_64 guests (see Current limits).
Images that do not run cloud-init still boot, but nothing inside them is set up for you: give them their address yourself, or turn on DHCP for their network.
Registering an image
From an http:// or https:// URL — the SHA-256 is required, and the image
cannot be used unless the download matches it:
sudo cenvero-str-ctl image register --name debian-13 \
--url https://cloud.debian.org/images/cloud/trixie/latest/debian-13-genericcloud-amd64.qcow2 \
--sha256 <sha256 of that file> --wait
Most distributions publish checksums next to their images. Debian publishes
SHA-512 sums: download the image once, check it against them, and use
sha256sum on the same file for the value above.
Or copy a file that is already on the node, from any directory (the SHA-256 is then optional, and checked when given):
sudo cenvero-str-ctl image register --name cirros --path /root/cirros-0.6.3-x86_64-disk.img --wait
The command opens the file itself and hands the open file to the agent, which copies and checks it exactly like a download — so a file in your home directory or a temporary directory works too. The path must name a regular file — not a link, directory, device or pipe. Copying from a path is only possible on the node's own command line, never over the API.
Registration runs in the background. --wait waits until the image is ready
(or failed, with the reason); without it the command returns at once and the
image shows as downloading. At most two images are fetched at a time.
The image name may use letters, digits, ., _ and - (up to 64 characters,
starting with a letter or digit) and must be unique on the node.
Listing, showing and deleting
cenvero-str-ctl image list
cenvero-str-ctl image show img-3f9a1c2e
sudo cenvero-str-ctl image delete img-3f9a1c2e
{
"image": {
"id": "img-3f9a1c2e",
"name": "debian-13",
"state": "ready",
"sha256": "5754395abffb1d384d50f6d0945d46d1beb7be42a7e786e4fc4a6f27270ab16f",
"format": "qcow2",
"source_format": "qcow2",
"virtual_size": 3221225472,
"file_size": 340983808,
"source_url": "https://cloud.debian.org/images/cloud/trixie/latest/debian-13-genericcloud-amd64.qcow2",
"created_at": "2026-09-28T09:14:02Z"
}
}
state | Meaning |
|---|---|
downloading | Being fetched or copied, checked and converted |
ready | Machines can be created from it |
failed | See error (a checksum mismatch, a refused format, a download error, …). The partial file is gone; delete the entry and register again |
An image cannot be deleted while any machine's disk is made from it (the error
names those machines), nor while it is still downloading. An image that was
still downloading when the node restarted is marked failed — register it again.
virtual_size is the size of the disk inside the image, in bytes: a machine's
disk can never be smaller than that.
Over the API
# register from a URL (202: it downloads in the background)
curl -k -X POST "$NODE/api/v1/images" -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"debian-13","url":"https://…/debian-13-genericcloud-amd64.qcow2","sha256":"<hex>"}'
curl -k "$NODE/api/v1/images" -H "Authorization: Bearer $TOKEN"
curl -k "$NODE/api/v1/images/img-3f9a1c2e" -H "Authorization: Bearer $TOKEN"
curl -k -X DELETE "$NODE/api/v1/images/img-3f9a1c2e" -H "Authorization: Bearer $TOKEN"
Registering from a path on the node is refused over the API.
The registration answers with the task that brings the image in ("task").
Its progress is in bytes — of the size the server announces, when it does — and
it can be stopped while it runs; the image is then marked failed, and you delete
it or register it again:
curl -k "$NODE/api/v1/tasks/{task}" -H "Authorization: Bearer $TOKEN"
curl -k -X POST "$NODE/api/v1/tasks/{task}/cancel" -H "Authorization: Bearer $TOKEN"
sudo cenvero-str-ctl task log {task} --follow # the same on the node
At most two images come in at a time; a third waits (its task reads queued).
A download the agent was in the middle of when it restarted is marked failed
("interrupted; register it again"), and so is its task.
A note on download addresses. Image downloads may not connect to loopback, link-local or unspecified addresses. Private addresses are allowed, so you can keep images on a mirror inside your network — which also means anyone holding an operator API token can make the node fetch from your internal network.