A stack of three copper, bronze and patina slabs hovering above still water in a verdigris-streaked canyon, backlit by a low sun, glowing between the slabs.
01 KILNcontrol plane
02 INGOTlinux · libvirt
03 INGOTapple silicon · tart
FIG.0COPPER, OXIDIZED
copper

AN OXIDE-INSPIRED MINI CLOUD

A mini cloud for a couple of home machines.

Copper pools the computers on your tailnet into one place to run virtual machines. Written in Rust, run as plain systemd daemons.

INSTALL › READ THE DESIGN ›
$ cu create web --vcpus 2 --memory 2048

Anatomy. One machine runs kiln. Every other machine runs ingot. You talk to all of it with cu.

DESIGN NOTES ›
FIG.1
TAILNET · TRUST BOUNDARY
kiln sqlite · :8400
GET /desired ↓ ↑ POST /observed
ingot libvirt · x86_64
ingot libvirt · x86_64
ingot tart · aarch64

01kiln

The control plane. SQLite is the source of truth for what should be running, and where.

  1. 1.1Kiln never pushes commands. Nodes pull.
  2. 1.2No capacity means an immediate refusal.
  3. 1.3New nodes wait for an admin to approve them.
FIG.2
01 PULL desired state
02 DIFF against the hypervisor
03 ACT start, stop, delete
04 PUSH observed state
EVERY 10 S · IDEMPOTENT

02ingot

The node agent. It runs on every compute node and reconciles the hypervisor toward desired state.

  1. 2.1libvirt on Linux. Tart on Apple silicon.
  2. 2.2Every action is idempotent; kiln may resend anything.
  3. 2.3Cut off from kiln, VMs keep running and nothing changes.
FIG.3
CU_URL=http://kiln:8400PROJECT default
{{ln.p}}{{ln.t}}

03cu

The command line client. You choose the VM, down to its architecture. The cloud chooses the node.

  1. 3.1Projects group instances and belong to a user.
  2. 3.2API tokens, stored hashed, made by the admin.
  3. 3.3Delete is final. The boot disk goes with it.
FIG.4
DESIREDOBSERVEDYOU SEE
{{r.d}} {{r.o}} {{r.s}}

04state

Progress shows up as instance state, never as operation IDs to poll.

  1. 4.1Derived from desired and observed. Never stored.
  2. 4.2Failed starts retry with backoff for five minutes.
  3. 4.3Stop and delete work from any state.

Install. One script on the kiln machine, one on every node.

{{cur.note}}

{{cur.where}}
$ {{ln}}