Each spawned clone now runs under a _console-proxy daemon that connects
firecracker's ttyS0 (stdin/stdout) to a PTY and serves it on a Unix
socket at clones/<id>/console.sock for the VM's lifetime.
sudo ./fc-orch spawn 1
sudo ./fc-orch console 1 # Ctrl+] to detach
spawnOne delegates VM startup to the proxy process (Setsid, detached)
and waits for console.sock to appear before returning. Kill continues
to work via PID files — proxy and firecracker PIDs are both recorded.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add --dev flag to main that enables logrus caller info (file:line) for
easier debugging without changing production log output
- Wire firecracker SDK logger (WithLogger) and FIFO log file to both the
golden VM and each clone machine so Firecracker's own logs are surfaced
- Log the exact shell commands being run (cp --reflink, ip tuntap, ip link,
firecracker binary) at Info level before each syscall/exec, making it
straightforward to reproduce steps manually
- Extract snapshot.go with loadSnapshotWithNetworkOverride: a direct PUT
/snapshot/load call over the Unix socket that includes network_overrides,
remapping the stored tap to the per-clone tap name (Firecracker v1.15+
feature not yet exposed by SDK v1.0.0)
- Use firecracker.WithSnapshot + a Handlers.FcInit.Swap to replace the SDK's
LoadSnapshotHandler with the above when Bridge != "none"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add docs/commands.md with per-command purpose, step-by-step shell/SDK
call sequences, config tables, outputs, and error conditions
- Rename module from github.com/you/fc-orchestrator to github.com/kacerr/fc-orchestrator
- Add KernelURL field to Config so the download URL is configurable via
FC_KERNEL_URL instead of being hardcoded in Init()
- Expose FC_KERNEL_URL in the usage string
- Add verbose logging of dd/mkfs.ext4/mount/tar calls in buildRootfs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
A "poor man's" Firecracker VM orchestrator that boots a single golden VM,
snapshots it, then restores N clone VMs from that snapshot with minimal
per-clone overhead.
How it works:
- `init` — downloads a Linux 6.1 kernel and builds a minimal Alpine 3.20
rootfs (512 MiB ext4) with a basic init script
- `golden` — boots the golden VM, lets it settle, then pauses and snapshots
it (vmstate + memory file); the golden VMM is then terminated
since only the artifacts are needed
- `spawn N` — restores N clone VMs concurrently from the golden snapshot:
* rootfs: filesystem-level COW copy via `cp --reflink` (falls
back to a plain copy if reflinks are not supported)
* memory: shared golden `mem` file; Firecracker's MAP_PRIVATE
lets the kernel handle COW page-by-page at no up-front cost
* vmstate: small file, cheap regular copy per clone
* networking: per-clone TAP device (fctapN) bridged to fcbr0
with iptables MASQUERADE NAT on the default route interface
- `status` — reads PID files and checks /proc to report alive/dead clones
- `kill` — stops in-memory clones, kills any stragglers via PID files,
and tears down all fctap* devices
- `cleanup` — kill + remove all state dirs and the bridge
All tunables (binary path, base dir, kernel/rootfs paths, vCPUs, memory,
bridge name/CIDR) are configurable via environment variables.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>