The mise tooling bootstrap was failing silently when --nat wasn't set: the VM came up, the user landed in ssh, and tools were missing with no obvious cause. Two coupled fixes: * `-d`/`--detach`: create + prep + bootstrap, exit without attaching to ssh. Reconnect later with `banger vm ssh <name>`. Rejects the ambiguous combos `-d --rm` and `-d -- <cmd>`. * NAT precondition: when the workspace has a .mise.toml or .tool-versions, vm run now refuses before VM creation if --nat isn't set. Error message points at --nat or --no-bootstrap. * `--no-bootstrap`: explicit opt-out for users who want a vanilla VM with their workspace and no tooling install. Detached bootstrap runs synchronously (foreground tee'd to the log file) so the CLI only returns once installs finish. Interactive mode keeps today's nohup'd background behaviour so the ssh session starts promptly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .githooks | ||
| cmd | ||
| configs | ||
| docs | ||
| images/golden | ||
| internal | ||
| scripts | ||
| .gitignore | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| CONTRIBUTING.md | ||
| cosign.pub | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| Makefile | ||
| mise.toml | ||
| README.md | ||
banger
One-command development sandboxes on Firecracker microVMs.
Spin up a clean Linux VM with your repo and tooling preloaded, drop
into ssh, and tear it down — all from one command. banger is built
for the dev loop, not the server use case: guests are short-lived,
single-user, reachable at <name>.vm from your host, and disposable.
Quick start
Requirements:
- Linux x86_64 with KVM
- Systemd
- Firecracker >= v1.5
Install:
curl -fsSL https://releases.thaloco.com/banger/install.sh | bash
The installer downloads the signed release, then prompts for sudo for install. Read more about how banger uses sudo
Verify host configuration:
banger doctor
First VM:
The first run may take a couple minutes for the bundle download. Subsequent
vm runs are expected to take from 1 to 3 seconds.
banger vm run --name my-vm
This auto-pulls the default image and drops you into an interactive ssh session.
Disconnecting an interactive session leaves the VM running,
--rm auto-deletes the VM when the session or command exits.
vm run
banger vm run ./my-repo # copy /my-repo into /root/repo — drops into ssh
banger vm run ./repo -- make test # workspace + run command, exits with its status
banger vm run --rm -- script.sh # ephemeral: VM is deleted on exit
banger vm run -d ./repo --nat # detached: prep + bootstrap, exit (no ssh attach)
If a repository is passed, banger copies your repo's git-tracked files
into /root/repo and runs a mise bootstrap from .mise.toml /
.tool-versions if either is present. The bootstrap reaches the
public internet, so workspaces with mise manifests require --nat;
pass --no-bootstrap to skip the install entirely. Untracked files
are skipped by default — pass --include-untracked to ship them
too, or --dry-run to preview the file list.
In command mode (-- <cmd>), the exit code propagates through
banger. In detached mode (-d), banger creates the VM, runs
workspace prep + bootstrap synchronously, then exits — no ssh
attach. Reconnect later with banger vm ssh <name>.
Other VM verbs
The CLI tries to feel familiar — every command and subcommand has
--help. Beyond vm run: vm list shows running VMs (--all for
every state), vm ssh <name> reconnects to one, vm exec <name> -- <cmd> runs a command without a shell, vm stop / vm kill shut a
VM down (graceful / hard), vm delete removes a stopped one, and
vm prune sweeps every non-running VM.
--nat: outbound internet
By default, a guest can't reach the internet.
Pass --nat to enable it (host-side MASQUERADE):
banger vm run --nat ./repo -- npm install
--nat works on vm run and vm create. To toggle on an existing
VM: banger vm set --nat <name> (or --no-nat to remove it).
Hostnames: <vm>.vm
banger's daemon runs a DNS server for the .vm zone. With host-side
DNS routing, curl http://sandbox.vm:3000 works from anywhere on
the host — no IP juggling. On systemd-resolved hosts, banger wires
this up automatically; everywhere else there's a manual recipe in
docs/dns-routing.md.
For ssh sandbox.vm (instead of banger vm ssh sandbox):
banger ssh-config --install
That adds a marker-fenced Include line to ~/.ssh/config.
banger ssh-config --uninstall reverses it.
Config
~/.config/banger/config.toml. All keys optional; the two most
useful:
[vm_defaults]
vcpu = 4
memory_mib = 4096
disk_size = "16G"
[[file_sync]]
host = "~/.aws"
guest = "~/.aws"
[[file_sync]]
host = "~/.config/gh/hosts.yml"
guest = "~/.config/gh/hosts.yml"
vm_defaults overrides banger's host-derived sizing. file_sync
copies host files into the VM's work disk at create time — handy
for credentials and dotfiles you want in every sandbox. Full
reference: docs/config.md.
Updating
banger update --check # is a newer release available?
sudo banger update # download, verify, swap, restart, run doctor
The release tarball is cosign-verified against a public key embedded
in the running binary. On any post-swap failure, banger auto-restores
the previous install. See docs/privileges.md
for the trust model.
Uninstalling
sudo banger system uninstall # remove services + binaries; keep state
sudo banger system uninstall --purge # also wipe VMs, images, caches under /var/lib/banger
User config (~/.config/banger/) and SSH key
(~/.local/state/banger/ssh/) stay put either way — delete them by
hand if you want a full clean slate.
Security
Guest VMs are single-user dev sandboxes, not multi-tenant servers.
sshd accepts only the host SSH key (no passwords, no
kbd-interactive), and guests are reachable only through the host
bridge (172.16.0.0/24). Don't expose the bridge or guest IPs to
an untrusted network.
The privileged surface lives entirely in bangerd-root.service and
is documented in docs/privileges.md.
Further reading
docs/config.md— full config reference.docs/dns-routing.md—<vm>.vmhost-side resolution.docs/image-catalog.md— image bundles and how to publish.docs/kernel-catalog.md— kernel bundles.docs/oci-import.md— pulling arbitrary OCI images.docs/advanced.md—vm create, scripting, custom rootfs.docs/privileges.md— trust model, capability set, daemon split.CONTRIBUTING.md— building from source, running tests.