Make spawned VMs easier to use and restore from the host. Add shared DNS and runtime helpers, publish <vm-name>.vm records through mapdns, and teach run/customize/interactive/restore to persist the metadata needed for SSH, DNS cleanup, and clean restores. Seed per-VM /home and /var disks from the rootfs snapshot so package state is present on first boot, add an interactive customization entrypoint plus ssh.sh and human-friendly list output, and let stop/kill/rm operate on multiple VM identifiers. Tear down stale TAP, dm, and loop state when VMs stop so restore can recreate them safely, and validate the updated scripts with bash -n plus targeted dry-run harnesses for teardown and restore paths.
136 lines
4.4 KiB
Markdown
136 lines
4.4 KiB
Markdown
# 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`)
|
|
- `id_ed25519`: SSH key for `root`
|
|
- `mapdns`: local DNS mapping CLI used to publish `<vm-name>.vm` → guest IP records
|
|
|
|
## Run
|
|
```
|
|
./run.sh
|
|
```
|
|
|
|
## Run Options
|
|
```
|
|
./run.sh --name calm_otter --vcpu 4 --ram 2048 --home-size 6G
|
|
```
|
|
- `--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.
|
|
- `--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`).
|
|
- `--home-size`: M/G suffixes supported (default: 2G).
|
|
- `--var-size`: M/G suffixes supported (default: 2G).
|
|
|
|
## Storage Layout
|
|
- `rootfs.ext4` is used as the read-only origin for a per-VM device-mapper snapshot mounted as `/`.
|
|
- Each VM gets writable ext4 disks mounted at `/home` and `/var`.
|
|
- `run.sh` seeds those `/home` and `/var` disks from the rootfs snapshot before boot so the guest sees the base image contents there on first boot.
|
|
- The base image must include `/etc/fstab` entries for `/dev/vdb` → `/home` and `/dev/vdc` → `/var`.
|
|
- `/run` and `/tmp` should be tmpfs via `/etc/fstab`.
|
|
|
|
## SSH
|
|
```
|
|
ssh -i "./id_ed25519" root@<guest_ip>
|
|
```
|
|
|
|
Shortcut:
|
|
```
|
|
./ssh.sh <vm-name-or-ip>
|
|
```
|
|
|
|
## VM DNS
|
|
- Spawned VMs register `<vm-name>.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 <id-or-name-prefix>
|
|
```
|
|
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 <id-or-name-prefix>
|
|
```
|
|
Check status with:
|
|
```
|
|
./nat.sh status <id-or-name-prefix>
|
|
```
|
|
|
|
## 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-<base filename>` in the same directory
|
|
unless you pass `--out`.
|
|
|
|
```
|
|
./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-<base filename>`).
|
|
|
|
After boot, enable NAT and validate Docker:
|
|
```
|
|
./nat.sh up <id-or-name-prefix>
|
|
ssh -i "./id_ed25519" root@<guest_ip> "systemctl enable --now docker"
|
|
ssh -i "./id_ed25519" root@<guest_ip> "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`
|
|
|
|
## 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/<id>/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.
|