banger/AGENTS.md
Thales Maciel 8f4be112c2
Generic kernel + init= boot path for OCI-pulled images
Closes the full arc: banger kernel pull + image pull + vm create + vm ssh
now works end-to-end against docker.io/library/debian:bookworm with zero
manual image building.

Generic kernel:
 - New scripts/make-generic-kernel.sh builds vmlinux from upstream
   kernel.org sources using Firecracker's official minimal config
   (configs/firecracker-x86_64-6.1.config). All critical drivers
   (virtio_blk, virtio_net, ext4, vsock) compiled in — no modules,
   no initramfs needed.
 - Published as generic-6.12 in the catalog (kernels.thaloco.com).
 - catalog.json updated with the new entry.

Direct-boot init= override (vm_lifecycle.go):
 - For images without an initrd (direct-boot / OCI-pulled), banger now
   passes init=/usr/local/libexec/banger-first-boot on the kernel
   cmdline. The script runs as PID 1, mounts /proc /sys /dev /run,
   checks for systemd — if present execs it immediately; if not
   (container images), installs systemd-sysv + openssh-server via the
   guest's package manager, then execs systemd.
 - Also passes kernel-level ip= parameter via BuildBootArgsWithKernelIP
   so the kernel configures the network interface before init runs
   (container images don't ship iproute2, so the userspace bootstrap
   script can't call ip(8)).
 - Masks dev-ttyS0.device and dev-vdb.device systemd units that
   otherwise wait 90s for udev events that never fire in Firecracker
   guests started from container rootfses.

first-boot.sh rewritten as universal init wrapper:
 - Works as PID 1 (mounts essential filesystems) OR as a systemd
   oneshot (existing behavior).
 - Installs both systemd-sysv AND openssh-server (container images
   have neither).
 - Dispatch updated: debian, alpine, fedora, arch, opensuse families
   + ID_LIKE fallback. All tests updated.

Opencode capability skip for direct-boot images:
 - The opencode readiness check (WaitReady on vsock port 4096) now
   returns nil for images without an initrd, since pulled container
   images don't ship the opencode service. Without this, the VM
   would be marked as error for lacking an opinionated add-on.

Docs: README and kernel-catalog.md updated to recommend generic-6.12
as the default kernel for OCI-pulled images. AGENTS.md notes the new
build script.

Verified live:
 - banger kernel pull generic-6.12
 - banger image pull docker.io/library/debian:bookworm --kernel-ref generic-6.12
 - banger vm create --image debian-bookworm --name testbox --nat
 - banger vm ssh testbox -- "id; uname -r; systemctl is-active banger-vsock-agent"
 → uid=0(root), kernel 6.12.8, Debian bookworm, vsock-agent active,
   sshd running, SSH working.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 20:12:56 -03:00

3.4 KiB

Repository Guidelines

Always run make build before commit.

Project Structure

  • cmd/banger and cmd/bangerd are the main user entrypoints.
  • internal/ contains the daemon, CLI, RPC, storage, Firecracker integration, guest helpers, and the experimental web UI.
  • internal/daemon/ is the composition root; pure helpers live in its subpackages (opstate, dmsnap, fcproc, imagemgr, session, workspace). See internal/daemon/ARCHITECTURE.md.
  • scripts/ contains explicit manual helper workflows for rootfs and kernel preparation.
  • build/bin/ is the canonical source-checkout build output.
  • build/manual/ is the canonical source-checkout location for manual rootfs/kernel artifacts.

Build and Test

  • make build builds ./build/bin/banger, ./build/bin/bangerd, and ./build/bin/banger-vsock-agent.
  • make test runs go test ./....
  • make lint runs gofmt -l, go vet ./..., and shellcheck --severity=error on scripts/*.sh. Run before commits.
  • ./build/bin/banger doctor checks host readiness.
  • ./build/bin/banger image build --from-image <image> builds a managed image from an existing registered image.
  • ./build/bin/banger image register ... registers an unmanaged host-side image stack.
  • ./build/bin/banger image promote <image> copies an unmanaged image into daemon-owned managed artifacts.
  • scripts/make-generic-kernel.sh builds a Firecracker-optimized vmlinux from upstream sources (no initrd, all drivers built-in). This is the recommended kernel for OCI-pulled images.
  • make void-kernel, make rootfs-void, and make void-register drive the experimental Void flow under ./build/manual.
  • scripts/publish-kernel.sh <name> packages a locally-imported kernel and uploads it to the catalog; see docs/kernel-catalog.md.
  • banger image pull <oci-ref> --kernel-ref <name> pulls a rootfs from any OCI registry; see docs/oci-import.md (experimental — file-ownership caveat).

Image Model

  • Managed images own the full boot set: rootfs, optional work-seed, kernel, optional initrd, and optional modules.
  • There is no runtime bundle and no auto-registered default image from disk paths.
  • default_image_name selects a registered image only.

Config

  • Config lives at ~/.config/banger/config.toml.
  • Firecracker comes from PATH by default, or firecracker_bin.
  • SSH uses ssh_key_path or an auto-managed default key at ~/.config/banger/ssh/id_ed25519.

Coding Style

  • Prefer small, direct Go code and standard library solutions.
  • Keep shell scripts strict with set -euo pipefail.
  • Use gofmt for Go formatting.
  • When a CLI accepts either an inline string or a file input, always prefer the file-based form.
  • For shell commands and AI/LLM tooling, prefer passing files as input whenever the CLI allows it.
  • Create temporary files as needed to follow the file-first rule.
  • Examples: use git commit -F <file> instead of git commit -m <message>, and use prompt files instead of inline prompt strings when invoking LLM CLIs.

Testing Guidance

  • Primary automated coverage is go test ./....
  • For lifecycle changes, smoke-test with vm create, vm ssh, vm stop, and vm delete.
  • If guest provisioning changes, document whether existing images must be rebuilt or recreated.

Security

  • Do not commit secrets.
  • VM workflows require sudo and /dev/kvm.
  • The default SSH key is local configuration, not a checked-in runtime artifact.