# banger Persistent Firecracker development VMs managed through a Go daemon, CLI, and TUI. ## Requirements - Linux host with KVM (`/dev/kvm` access) - Core VM lifecycle: `sudo`, `ip`, `dmsetup`, `losetup`, `blockdev`, `truncate`, `pgrep`, `ps` - Guest rootfs patching: `e2cp`, `e2rm`, `debugfs` - Guest work disk creation/resizing: `mkfs.ext4`, `e2fsck`, `resize2fs`, `mount`, `umount`, `cp` - SSH and logs: `ssh` - DNS publishing: `mapdns` - Optional NAT: `iptables`, `sysctl` - Image build helper flow: `bash`, `curl`, `jq`, `sha256sum` `banger` validates these per command and returns actionable errors instead of assuming one workstation layout. ## Runtime Bundle Runtime artifacts are no longer tracked directly in Git. Source checkouts use a generated `./runtime/` bundle, while installed binaries use `$(prefix)/lib/banger`. The bundle contains: - `firecracker` - `bundle.json` with the bundle's default kernel/initrd/modules/rootfs paths - a kernel, initrd, and modules tree referenced by `bundle.json` - `rootfs-docker.ext4` - `rootfs.ext4` when present - `packages.apt` - `id_ed25519` - the helper scripts used by image builds and installs Bootstrap a source checkout explicitly: ```bash make runtime-bundle ``` `make runtime-bundle` reads [`runtime-bundle.toml`](/home/thales/projects/personal/banger/runtime-bundle.toml), downloads the published bundle, verifies its SHA256, and unpacks it into `./runtime/`. `make install` will not fetch artifacts for you. The manifest must point at a published or locally staged bundle before bootstrap can work. ## Build ```bash make runtime-bundle make build ``` Install into `~/.local/bin` by default, with the runtime bundle under `~/.local/lib/banger`: ```bash make install ``` After `make install`, the installed `banger` and `bangerd` do not need the repo checkout to keep working. ## Basic VM Workflow Create and boot a VM: ```bash banger vm create --name calm-otter --disk-size 16G ``` List VMs: ```bash banger vm list ``` Inspect a VM: ```bash banger vm show calm-otter banger vm stats calm-otter ``` SSH into a running VM: ```bash banger vm ssh calm-otter ``` Stop, restart, kill, or delete it: ```bash banger vm stop calm-otter banger vm start calm-otter banger vm restart calm-otter banger vm kill --signal TERM calm-otter banger vm delete calm-otter ``` Update stopped VM settings: ```bash banger vm set calm-otter --memory 2048 --vcpu 4 --disk-size 32G ``` Launch the TUI: ```bash banger tui ``` ## Daemon The CLI auto-starts `bangerd` when needed. Useful daemon commands: ```bash banger daemon status banger daemon socket banger daemon stop ``` `banger daemon status` prints the daemon PID, socket path, and `bangerd.log` location. State lives under XDG directories: - config: `~/.config/banger` - state: `~/.local/state/banger` - cache: `~/.cache/banger` - runtime socket: `$XDG_RUNTIME_DIR/banger/bangerd.sock` Installed binaries resolve their runtime bundle from `../lib/banger` relative to the executable. Source-checkout binaries resolve it from `./runtime` next to the repo-built `./banger`. You can override either with `runtime_dir` in `~/.config/banger/config.toml` or `BANGER_RUNTIME_DIR`. `mapdns` uses its own default data store unless you set `mapdns_data_file` or `BANGER_MAPDNS_DATA_FILE`. Useful config keys: - `log_level` - `runtime_dir` - `firecracker_bin` - `mapdns_bin` - `mapdns_data_file` - `ssh_key_path` - `namegen_path` - `customize_script` - `default_rootfs` - `default_base_rootfs` - `default_kernel` - `default_initrd` - `default_modules_dir` - `default_packages_file` ## Logs - daemon lifecycle logs: `~/.local/state/banger/bangerd.log` - raw Firecracker output per VM: `~/.local/state/banger/vms//firecracker.log` - raw image-build helper output: `~/.local/state/banger/image-build/*.log` `bangerd.log` is structured JSON. Set `log_level` in `~/.config/banger/config.toml` or `BANGER_LOG_LEVEL` to one of `debug`, `info`, `warn`, or `error`. ## Images List images: ```bash banger image list ``` Build a managed image: ```bash banger image build --name docker-dev --docker ``` Show or delete images: ```bash banger image show docker-dev banger image delete docker-dev ``` `banger` auto-registers the bundled `default_rootfs` image when it exists. If the bundle does not include a separate base `rootfs.ext4`, `image build` falls back to using `rootfs-docker.ext4` as its default base image. ## Networking And DNS Enable NAT when creating or updating a VM: ```bash banger vm create --name web --nat banger vm set web --nat banger vm set web --no-nat ``` For daemon-managed VMs, NAT is applied directly by `bangerd` using host `iptables` rules derived from the VM's current guest IP and TAP device. Running VMs are published as `.vm` through `mapdns`. ## Storage Model - VMs share a read-only base rootfs image. - Each VM gets its own sparse writable system overlay for `/`. - Each VM gets its own persistent ext4 work disk mounted at `/root`. - Stopping a VM preserves its overlay and work disk. ## Rebuilding The Repo Default Rootfs `packages.apt` controls the base apt packages baked into rebuilt images. To rebuild the source-checkout default image in `./runtime/rootfs-docker.ext4`: ```bash make rootfs ``` If the package manifest changed and you want a fresh source-checkout image: ```bash rm -f ./runtime/rootfs-docker.ext4 ./runtime/rootfs-docker.ext4.packages.sha256 make rootfs ``` `make rootfs` expects a bootstrapped runtime bundle. If `./runtime/rootfs.ext4` is not available, pass an explicit `--base-rootfs` to `./make-rootfs.sh`. ## Maintaining The Runtime Bundle Maintain the checked-in manifest in [`runtime-bundle.toml`](/home/thales/projects/personal/banger/runtime-bundle.toml) with the published bundle URL, SHA256, and `bundle_metadata` defaults. Package a local `./runtime/` tree for publication: ```bash make runtime-package ``` That writes `dist/banger-runtime.tar.gz` and prints its SHA256 so you can update the manifest before publishing or testing bootstrap changes. ## Remaining Shell Helpers The runtime VM lifecycle is managed through `banger`. The remaining shell scripts are not the primary user interface: - `customize.sh`: implementation used by `banger image build`; it now reads assets from `BANGER_RUNTIME_DIR` and stores transient state under `BANGER_STATE_DIR`/XDG state - `make-rootfs.sh`: convenience wrapper for rebuilding `./runtime/rootfs-docker.ext4` - `interactive.sh`: manual one-off rootfs customization over SSH - `nat.sh`: legacy host NAT helper used by the shell customization flows - `packages.sh`, `dns.sh`: shell helper libraries - `verify.sh`: smoke test for the Go workflow (`./verify.sh --nat` adds NAT coverage)