banger/README.md
Thales Maciel b33f24865c
vm run --rm: ephemeral sandboxes
New `--rm` flag deletes the VM once the ssh session or `-- cmd`
exits, making `vm run` one-shot. Exit code from command mode still
propagates correctly.

Semantics:
- Create fails → no VM to delete, nothing to do.
- SSH-wait timeout → VM intentionally kept alive so `vm logs <name>`
  shows why; the timeout error already pointed users at that. Even
  with --rm, this path skips delete — a wedged sshd is exactly when
  you want post-mortem access.
- Session/command ends (any exit code, any reason) → VM is deleted
  via `vm.delete` RPC. Uses a fresh 10s context so Ctrl-C during the
  session doesn't abort the cleanup.

New vmDeleteFunc seam at the top of banger.go alongside the other
RPC seams. Two tests cover the happy path (session ends cleanly →
delete fires with correct ref) and the skip-on-timeout path (ssh
wait errors → delete does NOT fire).

README updated with an ephemeral example and a note about the
timeout-skip behaviour.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 16:06:46 -03:00

196 lines
5.9 KiB
Markdown

# banger
One-command development sandboxes on Firecracker microVMs.
## Quick start
```bash
make install
banger vm run --name sandbox
```
`banger vm run` auto-pulls the default golden image (Debian bookworm
with systemd, sshd, Docker CE, git, jq, mise, and the usual dev tools)
and kernel from the embedded catalog if they aren't already local,
creates a VM, starts it, and drops you into an interactive ssh
session. First run takes a couple minutes (bundle download);
subsequent `vm run`s are seconds.
## Requirements
- Linux with `/dev/kvm`
- `sudo`
- Firecracker on `PATH`, or `firecracker_bin` set in config
- host tools checked by `banger doctor`
## Build + install
```bash
make install
```
Installs:
- `banger` (CLI)
- `bangerd` (daemon, auto-starts on first CLI call)
- `banger-vsock-agent` (companion, under `$PREFIX/lib/banger/`)
## `vm run`
One command, three modes:
```bash
banger vm run # bare sandbox — drops into ssh
banger vm run ./repo # workspace at /root/repo — drops into ssh
banger vm run ./repo -- make test # workspace + run command, exit with its status
banger vm run --rm -- script.sh # ephemeral: VM is deleted on exit
```
- Bare mode gives you a clean shell.
- Workspace mode (with a path) copies the repo's tracked + untracked
non-ignored files into `/root/repo` and kicks off a best-effort
mise tooling bootstrap from the repo's `.mise.toml` /
`.tool-versions`. Log: `/root/.cache/banger/vm-run-tooling-<repo>.log`.
- Command mode (`-- <cmd>`) runs the command in the guest; exit code
propagates through `banger`.
Disconnecting from an interactive session leaves the VM running. Use
`vm stop` / `vm delete` to clean up — or pass `--rm` so the VM
auto-deletes once the session / command exits.
`--branch` and `--from` apply only to workspace mode.
`--rm` delete is skipped when the initial ssh wait times out, so a
wedged sshd leaves the VM alive for `banger vm logs` inspection.
## Image catalog
`banger image pull <name>` resolves `<name>` in the embedded catalog
and fetches a pre-built bundle (rootfs.ext4 + manifest, tar+zstd). The
kernel referenced by the manifest auto-pulls too. `vm run` calls this
for you on demand.
Today's catalog:
| Name | Distro | Kernel |
|------|--------|--------|
| `debian-bookworm` | Debian 12 slim + sshd + docker + dev tools | `generic-6.12` |
The catalog ships embedded in the banger binary. See
[`docs/image-catalog.md`](docs/image-catalog.md) for maintenance.
## Power-user flows
Skip this section if `vm run` is enough.
### `vm create` — low-level primitive
For scripting or `--no-start` provisioning:
```bash
banger vm create --image debian-bookworm --name testbox --no-start
banger vm start testbox
banger vm ssh testbox
banger vm stop testbox
```
### `image pull <oci-ref>` — arbitrary container images
For images outside the catalog, pull from any OCI registry:
```bash
banger image pull docker.io/library/alpine:3.20 --kernel-ref generic-6.12
```
Layers are flattened, ownership is fixed, banger's guest agents are
injected, and a first-boot service installs `openssh-server` via the
guest's package manager. See [`docs/oci-import.md`](docs/oci-import.md)
for supported distros and caveats.
### `image register` — existing host-side stack
```bash
banger image register --name base \
--rootfs /abs/path/rootfs.ext4 \
--kernel-ref generic-6.12
```
For custom images, write a Dockerfile and either publish to the
catalog (see `docs/image-catalog.md`) or pull it via the OCI path.
### Workspace + session primitives
Long-lived guest commands managed by the daemon, attachable over a
local Unix socket bridge:
```bash
banger vm workspace prepare <vm> ./other-repo --guest-path /root/repo
banger vm session start <vm> --name planner --cwd /root/repo --stdin-mode pipe -- pi --mode rpc
banger vm session attach <vm> planner
banger vm session logs <vm> planner --stream stderr
banger vm session stop <vm> planner
```
For ACP-aware host tooling: `banger vm acp <vm>` bridges stdio to
guest `opencode acp` over SSH.
## Config
Config lives at `~/.config/banger/config.toml`. All keys optional.
Commonly set:
- `default_image_name` — image to use when `--image` is omitted
(defaults to `debian-bookworm`, auto-pulled from the catalog if not
local).
- `ssh_key_path` — host SSH key; if unset banger creates
`~/.config/banger/ssh/id_ed25519`.
- `firecracker_bin` — override the auto-resolved `PATH` lookup.
- `web_listen_addr` — experimental web UI (default
`127.0.0.1:7777`; set to `""` to disable).
- Network: `bridge_name`, `bridge_ip`, `cidr`, `tap_pool_size`,
`default_dns`.
Full key list in `internal/config/config.go`.
## Credential sync
If these host auth files exist, banger syncs them into the guest at
VM start:
| Host | Guest |
|------|-------|
| `~/.local/share/opencode/auth.json` | `/root/.local/share/opencode/auth.json` |
| `~/.claude/.credentials.json` | `/root/.claude/.credentials.json` |
| `~/.pi/agent/auth.json` | `/root/.pi/agent/auth.json` |
Host-side changes take effect after the VM restarts. Session/history
directories are not copied.
## Web UI (experimental)
`bangerd` serves a local web UI at `http://127.0.0.1:7777` by default.
Convenient for local observability, **not a stable interface**. Do
not expose the listen address to a shared network.
## Security
Guest VMs are single-user development sandboxes, not multi-tenant
servers. Every provisioned image is configured with:
```
PermitRootLogin yes
StrictModes no
```
The host SSH key is the only authentication mechanism, no password
auth is enabled, and VMs are reachable only through the host bridge
network (`172.16.0.0/24` by default). Do not expose the bridge
interface or guest IPs to an untrusted network.
## Notes
- Managed image delete removes the daemon-owned artifact dir.
- Layer blob cache for OCI pulls lives under `~/.cache/banger/oci/`.
- Image bundle cache doesn't exist — bundles are extracted directly
into the image store; re-pulls download fresh.