Downloads
Every release publishes four things, all signed:
| What it is | Use it for | |
|---|---|---|
| The OS image | ghcr.io/corium-os/corium | Upgrading a node that already exists, and building your own artefacts |
| An installer ISO | ghcr.io/corium-os/corium-iso | Bare metal. Installs unattended |
| A qcow2 disk | ghcr.io/corium-os/corium-qcow2 | Proxmox, KVM, libvirt. This is what
deploy/proxmox/ takes as DISK_IMAGE |
cctl | Attached to the release page | Managing nodes from your own machine |
The exact commands for a given version, with its digests, are on that version’s release page: latest release. The coordinates change every release, so they are published with the release rather than written down here.
Installing cctl
The client runs on your machine and never on a node. Archives are attached to each release for linux and macOS, on amd64 and arm64.
With mise, which picks the archive matching your machine:
mise use -g 'github:Corium-OS/Corium[exe=cctl]@0.2.0'Both the quotes and the version are load-bearing, and leaving either out fails in a way that does not obviously point at them.
The quotes are for your shell: zsh treats [...] as a glob, so an unquoted
command never reaches mise at all — it reports no matches found before
anything runs.
The version is for two reasons. mise refuses a release younger than its age
setting allows, which is a supply-chain guard and means a freshly published
version is not installable for a while (no versions found ... matching date filter). And an unpinned install resolves to the newest tag, release
candidates included — pinning is how you say you meant the stable one.
By hand, checking what you downloaded:
version=0.2.0
base=https://github.com/Corium-OS/Corium/releases/download/v${version}
curl -fsSLO "${base}/cctl_${version}_linux_amd64.tar.gz"
curl -fsSLO "${base}/SHA256SUMS"
sha256sum --check --ignore-missing SHA256SUMS
tar -xzf "cctl_${version}_linux_amd64.tar.gz"--ignore-missing because SHA256SUMS lists every platform and you downloaded
one. Without it the check fails on the three archives you do not have, which
looks exactly like the failure that would matter.
The checksum file is signed with the same key as the OS image, so verifying it verifies every binary underneath:
curl -fsSLO "${base}/SHA256SUMS.sig"
curl -fsSLO https://raw.githubusercontent.com/Corium-OS/Corium/v${version}/build/files/usr/share/corium/cosign.pub
cosign verify-blob --key cosign.pub --signature SHA256SUMS.sig SHA256SUMSThere is no Windows build. Not a decision against it — nobody has run cctl
there once, and a download page that lists a platform nobody has started is a
download page worth less on every other line.
From a checkout instead, which is what a release binary is built from anyway:
git clone https://github.com/Corium-OS/Corium.git && cd Corium
mise run build # produces bin/cctl and bin/corium-agentSee cctl for what it does.
Three ways to the same bytes
# 1. With oras. One command, and it names the file for you.
oras pull ghcr.io/corium-os/corium-iso:0.1.0
# 2. Without oras. The registry issues pull tokens anonymously for public
# packages, so curl is enough.
token=$(curl -s "https://ghcr.io/token?scope=repository:corium-os/corium-iso:pull" | jq -r .token)
curl -L -H "Authorization: Bearer ${token}" -o corium-0.1.0-x86_64.iso \
https://ghcr.io/v2/corium-os/corium-iso/blobs/sha256:<the digest from the release notes>
# 3. From a browser, no tooling at all. The release notes carry the link.
https://<cdn>/corium-0.1.0-x86_64.isoThe third is a CDN copy. There is no index to browse, so the link for a given version lives in that version’s release notes rather than being guessable.
Why the disk artefacts are not attached to the release
A GitHub release asset must be under 2 GiB. The installer ISO is about 2.4 GB, so it cannot be one. The qcow2 would fit, but attaching only the disk artefact that happens to fit would read as though the ISO had been forgotten rather than left out deliberately, so both are published the same way.
That constraint turned out to be worth something. A file attached to a release page is an opaque blob whose provenance ends at whoever uploaded it. An artefact in a registry is addressed by digest and can carry a signature, which is the difference between this is the file we meant to give you and this is a file.
cctl is attached, because the same reasoning points the other way for it. It
is three megabytes, it is fetched by a person setting up a workstation rather
than by a machine, and the installers people already use — mise use github:Corium-OS/Corium[exe=cctl]@0.2.0' — read release assets and not
registries.
Signing it as a blob rather than as an OCI artefact costs one extra file and
keeps it reachable by the tools that would actually go looking.
Why there is a mirror
The registry is the right place to keep a release and an awkward place to send someone who just wants to try an operating system: route 1 means installing a tool, route 2 means a token and a digest. Neither is a link you can send to a colleague.
So the same bytes are also served from a CDN. Two things are worth being clear about:
- It is allowed to be down. If it is, the release still happened and the first two routes still work. Release notes offer a download link only when the upload and a read-back as an anonymous client both succeeded.
- It is a convenience, not the release. If the CDN and the registry ever disagreed, the registry is right. You do not have to take that on trust — the check below is what settles it.
Nothing published there is ever overwritten. Every file carries its version in its name, so a URL that worked once keeps meaning the same bytes.
Checking what you downloaded
Two different questions, and they need two different answers.
Who built this, and from what? That is the signature. It is attached to the artefact in the registry, and verifying it needs no key you have to obtain from somewhere first:
cosign verify ghcr.io/corium-os/corium-iso@sha256:<manifest digest> \
--certificate-identity-regexp 'https://github.com/Corium-OS/Corium/.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.comA passing check tells you which workflow run produced the artefact, from which commit and which tag, recorded in a public transparency log.
Did I receive those exact bytes? That is the hash. Every release publishes the SHA-256 of each artefact in its notes:
sha256sum corium-0.1.0-x86_64.iso
# must equal the hash printed in the release notesWhy there is no .sha256 file next to the download
Because it would not prove anything. A checksum file served from the same place as the file it describes is only as trustworthy as that place: anyone able to replace one can replace the other.
The hash in the release notes is different. It is the digest of the artefact’s
layer, and that digest is named inside the manifest that cosign signed. So
the chain closes:
cosign verify -> this manifest was produced by that workflow run
the manifest -> names this layer digest
sha256sum -> the file you hold has that digestEach link is checkable on its own, and none of them depends on the download host being honest. That is what makes it reasonable to fetch 2.4 GB from whichever route is fastest for you, and why a checksum file sitting beside the download would not have added anything.
Building them yourself
Nothing above is required. mise run artefacts produces the qcow2, the raw disk
and the ISO locally from any image you can pull, including one you have
modified. It needs a Linux host and sudo, because
bootc-image-builder mounts
the filesystem it creates. See the
quick start.
A raw disk image is not published. It would be roughly 5 GB, and the ISO already covers bare metal.