# banger Minimal Firecracker launcher. ## Requirements - Linux host with KVM (`/dev/kvm` access) - `sudo`, `ip`, `curl`, `ssh`, `jq` - `dmsetup`, `losetup`, `blockdev` (device-mapper snapshot for rootfs) - `e2cp`, `e2rm` (writes hostname and resolv.conf into rootfs snapshot) ## Files - `firecracker`: Firecracker binary - `wtf/root/boot/vmlinux-6.8.0-94-generic`: guest kernel - `wtf/root/boot/initrd.img-6.8.0-94-generic`: guest initrd - `wtf/root/lib/modules/6.8.0-94-generic/`: guest kernel modules - `rootfs.ext4`: guest root filesystem (base image if present) - `rootfs-docker.ext4`: docker-ready guest rootfs (built via `make-rootfs.sh`) - `packages.apt`: apt packages baked into rebuilt guest images - `id_ed25519`: SSH key for `root` - `mapdns`: local DNS mapping CLI used to publish `.vm` → guest IP records ## Run ``` ./run.sh ``` ## Experimental Go Control Plane There is now an XDG-based Go daemon + CLI prototype alongside the shell scripts. It keeps persistent VM/image state in SQLite under your XDG state directory and talks over a Unix socket under your XDG runtime directory. Build it with: ``` make build ``` Or directly with Go: ``` go build -o ./banger ./cmd/banger go build -o ./bangerd ./cmd/bangerd ``` Basic usage: ``` ./banger daemon status ./banger tui ./banger vm list ./banger vm create --name calm-otter --disk-size 16G ./banger vm set calm-otter --memory 2048 --vcpu 4 ./banger image list ``` Notes: - `banger` auto-starts the per-user daemon when needed. - `banger tui` launches a terminal UI for browsing, creating, editing, and operating VMs. - VM configs are persistent by default. - RAM, vCPU, and work-disk size edits are stopped-only. - The Go image build path currently delegates guest customization to `customize.sh`. ## Run Options ``` ./run.sh --name calm-otter --vcpu 4 --ram 2048 --overlay-size 12G ``` - `--name`: must be unique and match `[a-z0-9][a-z0-9-]{0,63}`. - `--vcpu`: defaults to 2, max 16. - `--ram`: MiB, defaults to 1024, max 32768. - `--overlay-size`: writable dm-snapshot size for VM changes under `/`, including `/root` and `/var` (default: 8G). - `--rootfs`: path to the rootfs image (default: `./rootfs-docker.ext4`). - `--kernel`: path to the kernel image (default: `./wtf/root/boot/vmlinux-6.8.0-94-generic`). - `--initrd`: path to the initrd image (default: `./wtf/root/boot/initrd.img-6.8.0-94-generic`). ## Storage Layout - `rootfs.ext4` is used as the read-only origin for a per-VM device-mapper snapshot mounted as `/`. - Each VM gets one sparse writable overlay file (`cow.ext4`) that stores its changes on top of the shared base image. - `/root` and `/var` live inside that per-VM overlay, so VMs can install packages without copying separate disks per VM. - `run.sh` masks stale `home.mount` and `var.mount` units at boot so older images with `/dev/vdb` and `/dev/vdc` entries in `/etc/fstab` still boot. - `/run` and `/tmp` should be tmpfs via `/etc/fstab`. ## SSH ``` ssh -i "./id_ed25519" root@ ``` Shortcut: ``` ./ssh.sh ``` ## VM DNS - Spawned VMs register `.vm` → guest IP through `mapdns set`. - VM teardown removes the mapping through `mapdns rm`. - `mapdns` writes to `/home/thales/.local/share/mapdns/records.json`. ## Internet Access VMs do not get internet access by default. You must enable forwarding and NAT: ``` ./nat.sh up ``` This enables `net.ipv4.ip_forward=1` and installs per-VM NAT rules for the VM's guest IP and TAP device. To remove rules: ``` ./nat.sh down ``` Check status with: ``` ./nat.sh status ``` ## Shutdown ``` reboot ``` ## Customize Rootfs (Docker + Kernel Modules) Use `customize.sh` to build a writable rootfs with Docker and kernel modules preloaded so Docker works out of the box. Pass the base rootfs as a positional argument; the output defaults to `docker-` in the same directory unless you pass `--out`. Base guest packages come from `./packages.apt`. Edit that file to bake tools like `vim` and `tmux` into rebuilt images. ``` ./customize.sh ./rootfs.ext4 --size 6G --docker ``` Options: - `--size`: optional size for the output image. - `--kernel`: kernel path (default: `./wtf/root/boot/vmlinux-6.8.0-94-generic`). - `--initrd`: initrd path (default: `./wtf/root/boot/initrd.img-6.8.0-94-generic`). - `--modules`: kernel modules directory (default: `./wtf/root/lib/modules/6.8.0-94-generic`). - `--docker`: install Docker packages into the image. - `--out`: output rootfs path (default: `docker-`). After boot, enable NAT and validate Docker: ``` ./nat.sh up ssh -i "./id_ed25519" root@ "systemctl enable --now docker" ssh -i "./id_ed25519" root@ "docker run --rm hello-world" ``` ## Build Rootfs On Demand `run.sh` defaults to `./rootfs-docker.ext4`. If it is missing, `run.sh` will invoke `make-rootfs.sh` to build it. ``` ./make-rootfs.sh ``` `make-rootfs.sh` chooses the first available base image: - `./rootfs.ext4` If `./packages.apt` changes after `rootfs-docker.ext4` is built, `run.sh` will warn and keep using the existing image. `make-rootfs.sh` will also warn and exit without rebuilding while the image already exists. To rebuild after package changes: ``` rm -f ./rootfs-docker.ext4 ./rootfs-docker.ext4.packages.sha256 ./make-rootfs.sh ``` ## Interactive Customization To create a writable copy and customize it manually over SSH (no automatic package/config changes), use: ``` ./interactive.sh ./rootfs-docker.ext4 ``` You can override the output path: ``` ./interactive.sh ./rootfs-docker.ext4 --out ./my-rootfs.ext4 ``` ## VM Info File Each VM writes: - `state/vms//vm.json`: local metadata under `.meta` plus the raw Firecracker config under `.config`. ## Log Notes - `PCI: Fatal: No config space access function found` and `MissingAddressRange` lines are expected with `pci=off` in `run.sh`. - `SELinux: Could not open policy file ...` is expected in the minimal rootfs.