Skip to content
Corium-OSPublic

About

An immutable Kubernetes node, built as an OCI image. Fedora bootc, k0s baked into a read-only /usr, configured with cloud-init.

Topics

Resources

Stars

13 stars

Watchers

1 watching

Forks

Repository files navigation

Corium

Corium

An immutable, container-native Linux distribution that boots into a Kubernetes node.

Latest release CI Image build Kubernetes 1.34 to 1.36 k0s floor v1.36.5+k0s.0 Fedora bootc Go version License: MIT

Corium is Fedora bootc with k0s in the read-only system, a Kubernetes version you can choose independently of the OS image, and a small declarative configuration layer on top of cloud-init.

Status: 0.x. The architecture is settled and the path works end to end — a node boots, joins, upgrades, drains itself before rebooting, rolls back when it comes up broken, and refuses an image that is not signed. Two things are not settled. The configuration surface can still change between minor releases, and the testing is narrower than it looks: everything has been verified on virtual machines, none of it on physical hardware. Pin a version, read the changelog, and do not put anything on it you would miss.


What it looks like

A complete single-node Kubernetes cluster:

#cloud-config
corium:
  role: single

A worker joining an existing one:

#cloud-config
corium:
  role: worker
  join:
    token: <k0s join token>

That is the whole interface for the common case. Everything else has a default, and every default is overridable. See examples for the full surface, including the escape hatches.


Managing a node

Every node runs a small management API that answers for itself and nothing else. It is on by default: a machine installed from the ISO with no configuration prints a pairing code on its console and waits to be told what it is, rather than being unreachable. cctl is the client: it claims a node, reads what it is, restarts a service, drains it, and rolls it on to a new image. cctl ui is the same thing with a page in front of it.

The cctl dashboard: six node cards showing role, cluster, k0s version, greenboot and uptime, one with an image staged and one unreachable

It runs on your machine, not on the nodes. The server binds loopback, holds your client certificate, and talks to each node over the same mutual TLS every other command uses. No machine gains a port, a password or a session because somebody opened a browser — which is what keeps what it is not true. It reads, and it restarts a unit, cordons, uncordons and drains. It cannot reboot, reset, apply a configuration or upgrade anything: those are irreversible, or they are rollouts whose order across nodes matters, and a button is the wrong shape for both.


The idea

Three properties, chosen together because each one reinforces the others.

The operating system is a container image. Corium is built with a Containerfile, pushed to a registry, and versioned by digest. You inspect it with podman, scan it with the scanner you already run, promote it between environments by moving a tag, and roll it back atomically. There is no separate image-building toolchain to learn, because the one you use for your applications already works.

Kubernetes ships with the OS, and its version is still yours to choose. The k0s binary lives in the read-only /usr, so a node always has a working Kubernetes and needs no network to get one. What that binary is can be overlaid by a signed system extension, which makes the Kubernetes version an axis of its own: a Fedora security fix no longer drags a Kubernetes minor bump behind it, and moving between Kubernetes releases no longer means rebasing the OS. Both axes stay immutable — nothing is ever written in place — and a node remains a disposable artefact rebuilt from a digest rather than a machine that accumulates state.

Configuration is cloud-init, where cloud-init exists. Not a bespoke API, not a new config language: the mechanism every hypervisor and cloud already speaks. Corium adds a corium: block that collapses the tedious parts into a handful of keys, and gets out of the way the moment you need something it did not anticipate.

Where cloud-init does not exist — bare metal without a seed device, PXE, an appliance shipped preconfigured — the same configuration is read from a file, the kernel command line, or a default baked into the image. One schema, four ways in.

What it is not

Corium is not a fleet manager — it provisions nodes and stops there. It does not fork or patch k0s. It does not invent a configuration language. Those are deliberate omissions: the project is an opinionated integration, and its value is in what it declines to do.

Prior art, honestly

Talos Linux is the dominant option in this space and is excellent; it is also an API-driven system with no shell and its own configuration model, which is a real commitment. Kairos covers similar ground — immutable OS, pluggable Kubernetes distribution, cloud-init configuration — but deliberately builds its own A/B partition scheme on top of an arbitrary base distribution rather than using the OSTree/bootc lineage.

Corium's bet is narrower and specific: that for teams already living in OCI registries and GitOps, an operating system that is an image — built, signed, scanned, and promoted like every other image they ship — is worth more than a bespoke mechanism, however good.

The comparison covers these and the rest properly, including the cases where you should pick something else.

Where a node's configuration comes from

Sources are tried in order, most specific first, and the first one that answers wins:

Source For
/etc/corium/config.yaml An operator's answer for this machine
cloud-init Every cloud and hypervisor: NoCloud, ConfigDrive, EC2, Azure, GCE, OpenStack, Hetzner, VMware
corium.config= on the kernel command line PXE and netboot, where the command line is all you control
/usr/share/corium/config.yaml A default baked into a derived image

A source that fails for any reason other than being absent stops the search. An unreachable config URL means your intent is unknown, and falling through to a baked-in default is how a node silently joins the wrong cluster.

Installable artefacts

mise run artefacts produces, via image-builder:

Artefact For Built by
qcow2 Proxmox, KVM, libvirt image-builder build --bootc-ref
raw Bare metal, and most clouds' import paths image-builder build --bootc-ref
anaconda-iso Interactive or kickstarted bare-metal installs the bootc-image-builder entry point

Both builders are pinned by digest and come from the same upstream release. The disks are on the code path upstream develops; the ISO is on the compatibility entry point bootc-image-builder left behind when it was archived in June 2026, because that is the only one that still builds the type — and that type is itself on its way out upstream. ADR 9 is the plan for the rest.

You only need to build these if you have changed the image. Every release publishes the ISO and the qcow2 ready-made and signed: see Downloads for where they live, why nothing is attached to the release itself, and how to check what you got.

Documentation

Start here

Installing

  • Downloads — where the ISO and the qcow2 are published, and how to verify them
  • Proxmox — a node on a Proxmox host, start to finish
  • OpenStack — a node on an OpenStack cloud, UEFI image included
  • Rescue mode — a dedicated server, installed from a provider's rescue system
  • HA cluster — building a three-controller control plane by hand
  • Stretched cluster — one cluster across two locations

Operating

  • Upgrades — moving a node to a new image, changing its Kubernetes version, rolling back
  • cctl — every command of the management CLI, what each role reaches, and how to read a refusal
  • Building your own image — deriving an image, signing it so nodes accept it
  • Cilium — replacing kube-router, including the kube-proxy-free variant
  • Software RAID — mdadm arrays on a node's spare disks, and where a RAID root stands
  • WireGuard overlay — joining hosts across sites over an encrypted overlay

Reference

  • Configuration reference — every field, and what Corium does with it
  • Examples — annotated documents for each common node shape
  • Feature support — what is modelled, what passes through to k0s, what is out of scope
  • Comparison — Talos, Kairos, Flatcar, and when not to use Corium
  • Changelog — what each release changed, and what is known to be broken
  • AGENTS.md — contributor and agent guidelines, architectural decisions
  • docs/adr/ — architecture decision records

Licence

MIT. See LICENSE.

About

An immutable Kubernetes node, built as an OCI image. Fedora bootc, k0s baked into a read-only /usr, configured with cloud-init.

Topics

Resources

Stars

13 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages