- Persist golden VM tag to clones/{id}/tag at spawn time
- GET /clones now returns [{id, tag}] objects instead of plain IDs
- Web UI renders tag as a dim label next to each clone entry (clone 3 · default)
- Pre-existing fixes included in this commit:
- console: tee all PTY output to clones/{id}/console.log for boot capture
- network: destroy stale tap before recreating to avoid EBUSY errors
- orchestrator: fix ubuntu systemd boot (custom fc-console.service, fstab,
mask serial-getty udev dep, longer settle time, correct package list)
- config: remove quiet/loglevel=0 from default boot args
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add Alpine, Debian, and Ubuntu rootfs support to `init [distro]`.
Golden snapshots are now namespaced under `golden/<tag>/` so multiple
baselines can coexist. `spawn [tag] [N]` selects which snapshot to
clone from. Systemd-based distros (Debian, Ubuntu) get a fc-net-init
systemd unit; Alpine keeps its inittab-based init.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces optional per-clone IP assignment using the Firecracker Microvm
Metadata Service (MMDS). A background daemon (fc-net-init) is baked into
the rootfs during init and captured in the golden snapshot — on clone
resume it polls 169.254.169.254 and applies the IP/GW/DNS config injected
by the orchestrator immediately after snapshot restore.
- config.go: add AutoNetConfig bool (FC_AUTO_NET_CONFIG=1)
- orchestrator.go: embed fc-net-init daemon + MMDS link-local route in
init script; set AllowMMDS: true on golden NIC; spawnOne/SpawnSingle
accept net bool and propagate it via FC_AUTO_NET_CONFIG in proxy env
- console.go: set AllowMMDS: true on clone NIC; call configureMmds()
after m.Start() when AutoNetConfig is enabled
- network.go: add configureMmds() — PUT /mmds with ip/gw/dns over the
clone's Firecracker Unix socket
- serve.go: POST /clones accepts optional {"net": bool} body to override
the global AutoNetConfig default per-request
- web/terminal.html: spawn button always sends {"net": true}
- docs/commands.md: document manual config + MMDS autoconfiguration
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces a browser-based terminal interface backed by xterm.js, served
directly from the binary via an embedded HTML asset.
New HTTP server (`serve [addr]`, default :8080):
GET / — xterm.js terminal UI; ?id=N selects a clone
GET /clones — JSON list of running clone IDs
POST /clones — spawn a new clone; returns {"id": N}
DELETE /clones/{id} — destroy a clone by ID
GET /ws/{id} — WebSocket console for clone {id}
binary frames = raw PTY I/O
text frames = JSON resize {"rows":N,"cols":M}
Supporting changes:
- orchestrator: add SpawnSingle() and KillClone(id) for per-clone lifecycle
management from the HTTP layer
- console: add a resize sideband Unix socket (console-resize.sock) that
accepts newline-delimited JSON {"rows","cols"} messages and applies them
to the PTY master via pty.Setsize; the WebSocket handler writes to this
socket on text frames so browser window resizes propagate into the VM
- deps: add gorilla/websocket v1.5.3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>