Two coupled fixes that together make the daemon-restart path of `banger update` non-destructive for running guests: 1. Unit templates set `KillMode=process` on bangerd.service and bangerd-root.service. The default control-group behaviour sent SIGKILL to every process in the cgroup on stop/restart — including jailer-spawned firecracker children, since fork/exec doesn't escape a systemd cgroup. With process mode only the unit's main PID is signalled; FC children stay alive in the (unowned) cgroup until the new helper instance starts up and re-claims them. 2. `fcproc.FindPID` falls back to the jailer-written pidfile at `<chroot>/firecracker.pid` (sibling of the api-sock target) when `pgrep -n -f <api-sock>` doesn't find a match. pgrep can't see jailer'd FCs because their cmdline only carries the chroot-relative `--api-sock /firecracker.socket`, not the host-side path. The pidfile is jailer's actual record of the post-exec FC PID, so reconcile can verify the surviving process is the right one (comm == "firecracker") and re-seed handles.json without tearing down the VM's dm-snapshot. Verified live on the dev host: started a VM, restarted the helper unit, restarted the daemon unit, and confirmed the FC PID was unchanged, vm list still showed the guest as running, and `banger vm ssh` returned the same boot_id pre and post restart. The systemd journal now reports "firecracker remains running after unit stopped" and "Found left-over process X (firecracker) in control group while starting unit. Ignoring." — exactly the shape `KillMode=process` is supposed to produce. Tests cover both the parser (parseVersionOutput from the v0.1.2 fix) and the new pidfile lookup: happy path, missing pidfile, stale pid, wrong comm, garbage content, non-symlink api-sock, whitespace tolerance. CHANGELOG corrects v0.1.0's misleading "daemon restarts do not interrupt running guests" line and documents the unit-refresh caveat: existing v0.1.0–v0.1.3 installs need a one-time `sudo banger system install` after updating to v0.1.4 to pick up the new KillMode directive (`banger update` swaps binaries, not unit files). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8.8 KiB
Changelog
All notable changes to banger are documented here. The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
The version line printed by banger version is the canonical reference
for what's installed; this file is the canonical reference for what
changed between versions.
Unreleased
v0.1.4 - 2026-04-29
Fixed
- Daemon restarts no longer kill running VMs. Two changes together:
- The
bangerd-root.serviceandbangerd.serviceunit templates now setKillMode=process. The default (control-group) sent SIGKILL to every process in the unit's cgroup on stop/restart, including the jailer-spawned firecracker children — fork/exec doesn't escape a systemd cgroup. WithKillMode=processonly the unit's main PID is signalled; firecracker children survive. fcproc.FindPIDnow also looks up jailer'd firecracker processes via the pidfile jailer writes at<chroot>/firecracker.pid(sibling of the api-sock target). Previously the only lookup path waspgrep -n -f <api-sock>, which can't see jailer'd processes because their cmdline only carries the chroot-relative--api-sock /firecracker.socket. Reconcile after a daemon restart now correctly re-attaches to surviving guests instead of mistaking them for stale and tearing down their dm-snapshot.
- The
Notes
- v0.1.0's CHANGELOG line "daemon restarts do not interrupt running
guests" was wrong: it was true at the systemd cgroup layer in
theory but the default
KillModedefeated it, and even withKillMode=processthe daemon's reconcile would mistake surviving FCs for stale and tear them down. v0.1.4 is the version where this actually works end-to-end. - Updating from v0.1.0–v0.1.3 to v0.1.4 still kills running VMs
because the driver of the update is the buggy older binary.
Updates from v0.1.4 onward preserve running VMs across the
helper+daemon restart that
banger updateperforms. - Existing v0.1.0–v0.1.3 installs that update to v0.1.4 do NOT
automatically pick up the new unit files —
banger updateswaps binaries, not systemd units. Runsudo banger system installonce on those hosts after updating to refresh the units. New v0.1.4+ installs get the correct units from the start.
v0.1.3 - 2026-04-29
No functional changes. Verification release: v0.1.2 fixed
banger update's install.toml handling, but the fix only takes
effect when v0.1.2 (or later) is the driver of an update. v0.1.3
exists so a host running v0.1.2 can update to it and confirm the
fix works end-to-end with the new code in the driver seat.
v0.1.2 - 2026-04-29
Fixed
banger updatenow writes the freshly-installed binary's commit and built_at fields to/etc/banger/install.toml, not the running CLI's. Previously install.toml'sversionwas correct after an update butcommit+built_atstill pointed at the pre-update binary's identity, which madebanger doctorraise a false-positive "CLI/install drift" warning on every update. Caught by the v0.1.0 → v0.1.1 live update smoke-test.
v0.1.1 - 2026-04-29
Added
install.sh— one-command installer published athttps://releases.thaloco.com/banger/install.sh. Runs as the invoking user, downloads + verifies the latest signed release with the embedded cosign public key, and re-execssudoonly for the actual system-install step. Pre-sudo summary explains in plain language why elevation is needed.BANGER_INSTALL_NONINTERACTIVE=1env var oninstall.shfor non-interactive use throughcurl | bash(CI, automated provisioning).
v0.1.0 - 2026-04-29
First public release. banger runs disposable development sandboxes as Firecracker microVMs: each sandbox boots in a few seconds, gets its own root filesystem and network, and exits on demand.
Added
Sandbox VMs
banger vm runboots a microVM, drops you into ssh, and tears it down on exit. Optional positional path ships a host repo into the guest;-- cmd argsruns a command non-interactively and exits with its status.- Long-lived VMs via
vm create/vm start/vm stop/vm restart/vm ssh/vm exec/vm logs/vm stats/vm ports/vm kill.vm listandpsenumerate state;vm prunedeletes every non-running VM. vm workspaceships a host repo into a guest and pulls diffs back.- Per-VM cgroup-isolated firecracker process under jailer chroot; daemon restarts do not interrupt running guests.
Images
banger image pull <name>pulls a curated rootfs+kernel bundle from the banger image catalog.image pull <oci-ref>pulls any OCI image.image list/image show/image delete/image promote/image registerround out the lifecycle.image cachemanages the OCI layer-blob cache.- Concurrent pulls of the same image are coalesced; the first pull wins, the rest wait.
Kernels
banger kernel pull <name>pulls a Firecracker-compatible kernel from the banger kernel catalog.kernel list/kernel show/kernel rmmanage the local store.
Host networking
- Per-host bridge with NAT; per-VM tap device; deterministic IPv4 assignment; iptables rules installed/removed with VM lifecycle.
- DNS routing: local resolver on
127.0.0.1:42069answers queries for<vm>.vmso plainssh <vm>.vmreaches the guest. banger ssh-configwrites a one-time~/.ssh/configinclude so ssh, scp, and rsync resolve<vm>.vmfrom any terminal.
System install
sudo banger system installinstalls an owner-mode daemon (bangerd.service) and a root-helper (bangerd-root.service) as systemd units. The owner daemon runs as the invoking user; only the root helper holds privilege, and only for a vetted set of operations.system status/system restart/system uninstallround out the lifecycle.daemonis a thin alias.banger doctoraudits host readiness: architecture, CLI/install version drift, state store, host runtime, vm lifecycle prerequisites, vsock guest agent, vm defaults, ssh shortcut, /root work disk, DNS, NAT, firecracker binary version, systemd units, socket permissions, helper unit hardening directives.
Self-update
banger updatedownloads, verifies, and installs newer releases from the public manifest. Flow: fetch manifest, refuse if any VM operation is in flight, download tarball +SHA256SUMS+SHA256SUMS.sig, verify the cosign signature against the embedded public key, verify the tarball hash, stage to a scratch dir, runbangerd --check-migrationsagainst the staged binary, atomically swap the three banger binaries, restart the systemd units, runbanger doctor, finalise the install record.- Pre-restart abort and post-restart auto-rollback both restore the previous install on failure.
banger update --checkreports whether a newer release is available without applying it;--to vX.Y.Zpins a specific version;--dry-runprints the plan;--forceskips the in-flight-op refusal.
Trust model
- Every release is cosign-signed. The public key is embedded in the
banger binary at build time; the signed payload is
SHA256SUMS, which in turn covers the release tarball. Verification uses the Go standard library (crypto/ecdsa.VerifyASN1); cosign is needed only for signing, not for verification. - The release manifest URL is hardcoded into the binary so a compromised daemon config cannot redirect the updater to a different bucket.
CLI surface
- Top-level:
vm,ps,image,kernel,ssh-config,system,daemon,doctor,update,version,completion. banger versionreports the version, commit SHA, and build timestamp baked in via ldflags at release-build time.
Compatibility
- The host-side and guest-side vsock agent protocol is informally
stable across patch versions (v0.1.x). Minor-version bumps
(v0.2.x) may change it; existing VMs created against an older
minor will need to be re-pulled.
banger doctorwarns when a running VM's agent is older than the daemon expects but does not block lifecycle operations. - The on-disk store schema is forward-only. Downgrading the binary
against a database written by a newer binary is unsupported; the
updater detects this via
bangerd --check-migrationsand refuses the swap rather than starting up against an incompatible store. - Linux only. amd64 only. KVM required.