Architecture

How the grain daemon, hypervisor, guest agent, and CLI fit together.

Big picture

CLI / SDKs
    │  unix socket or TCP (+ optional Bearer token)
    ▼
grain daemon
    │
    ├── store (VM meta under ~/.grain/vms)
    ├── image manager (~/.grain/images)
    ├── secrets / proxy state (optional features)
    │
    └── hypervisor runtime
            ├── qemu (default)  — HVF on Apple Silicon, KVM on Linux
            ├── firecracker     — experimental, Linux
            └── mock            — tests

Linux guest
    ├── cloud-init NoCloud seed (hostname, keys, mounts)
    ├── grain-agent :7475  (exec, shell, cp, fs, stats)
    └── optional sshd

Control plane

The daemon is the source of truth for which VMs exist, their ports, and disks. The CLI is a thin client. Automation should prefer the HTTP API or SDKs so behavior stays consistent.

Data path for a create

  1. Resolve image (auto → golden if Ready, else ubuntu-cloud)
  2. Ensure base disk (pull/import)
  3. Clone overlay / CoW disk
  4. Write cloud-init seed ISO
  5. Start hypervisor with hostfwd for SSH and agent
  6. Wait for readiness (ssh / agent / userdata)
  7. Optionally deploy agent over SSH if not baked

Networking model (QEMU user mode)

Guests use SLIRP user networking:

Why a guest agent?

SSH is excellent for interactive login and bootstrap. The agent is better for:

See Agent vs SSH.