Four drift fixes from a doc sweep.
internal/daemon/doc.go
Replace the capability-hook description that still said "Hook
methods take *Daemon; VMService reaches them through a
capabilityHooks seam." Current reality: every capability is a
plain struct carrying its own service pointers
(workDiskCapability{vm,ws,store}, dnsCapability{net},
natCapability{vm,net,logger}); wireServices builds the default
list; no hook reaches *Daemon.
internal/daemon/ARCHITECTURE.md
The VMService field list still claimed guestWaitForSSH and
guestDial were "per-instance fields." Those were deleted as
refactor residue. Update the note to say the seams live on
*Daemon (reached by WorkspaceService via closures wired at
construction) and document the vsockHostDevice field that
replaced the old package-global vsockHostDevicePath.
AGENTS.md
Drop the "experimental web UI" mention (removed) and the
`session` subpackage (removed). Mention banger-vsock-agent as
the third cmd/ binary while we're here — AGENTS hadn't listed
it.
docs/kernel-catalog.md
The trust-model section still read as if upstream kernel sources
were fetched by HTTPS alone. Add a paragraph covering the PGP
verification make-generic-kernel.sh now does against the
detached .tar.sign and the three kernel.org release signing keys.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
142 lines
5.7 KiB
Markdown
142 lines
5.7 KiB
Markdown
# Kernel catalog
|
|
|
|
The kernel catalog ships pre-built Firecracker-ready kernel bundles so users
|
|
don't have to compile anything. The catalog is embedded into the banger
|
|
binary and updated each release.
|
|
|
|
End-user flow:
|
|
|
|
```bash
|
|
banger kernel list --available # browse the catalog
|
|
banger kernel pull generic-6.12 # download a bundle (no sudo, no make)
|
|
banger image register --name myimg --rootfs … --kernel-ref generic-6.12
|
|
```
|
|
|
|
## Architecture
|
|
|
|
Two parts:
|
|
|
|
1. **`internal/kernelcat/catalog.json`** — a JSON manifest embedded into the
|
|
banger binary via `go:embed`. Each entry carries a name, distro, arch,
|
|
kernel version, tarball URL, and tarball SHA256. Updating the catalog
|
|
means editing this file in the repo and rebuilding banger.
|
|
|
|
2. **Tarballs at `https://kernels.thaloco.com/`** — Cloudflare R2 bucket
|
|
`banger-kernels`, fronted by a public custom domain. Each tarball is
|
|
`<name>-<arch>.tar.zst` and contains `vmlinux`, optional `initrd.img`,
|
|
and an optional `modules/` tree at the archive root.
|
|
|
|
The `banger kernel pull` flow streams the tarball, verifies its SHA256
|
|
against the embedded catalog entry, decompresses it (zstd), extracts it
|
|
into `~/.local/state/banger/kernels/<name>/`, and writes a manifest. Path
|
|
traversal entries and unsafe symlinks are rejected.
|
|
|
|
## Kernel types
|
|
|
|
**`generic-<version>`** — built from upstream kernel.org sources with
|
|
Firecracker's official config. All essential drivers (virtio_blk,
|
|
virtio_net, ext4, vsock) compiled in — no modules, no initramfs. This
|
|
is the kernel the golden image pairs with and the recommended kernel
|
|
for OCI-pulled images. Build with `scripts/make-generic-kernel.sh`.
|
|
|
|
## Adding or updating an entry
|
|
|
|
The repo has no CI for kernel publishing yet. Catalog updates are manual
|
|
and infrequent (kernel version bumps every few weeks at most).
|
|
|
|
```bash
|
|
# 1. Build the kernel locally.
|
|
scripts/make-generic-kernel.sh
|
|
|
|
# 2. Import it into the local catalog so the canonical layout exists.
|
|
banger kernel import generic-6.12 \
|
|
--from build/manual/generic-kernel \
|
|
--distro generic \
|
|
--arch x86_64
|
|
|
|
# 3. Package, upload, patch catalog.json.
|
|
scripts/publish-kernel.sh generic-6.12 \
|
|
--description "Generic Firecracker kernel 6.12 (all drivers built-in, no initrd)"
|
|
|
|
# 4. Review and commit the catalog change.
|
|
git diff -- internal/kernelcat/catalog.json
|
|
git add internal/kernelcat/catalog.json
|
|
git commit -m 'kernel catalog: add/update generic-6.12'
|
|
|
|
# 5. Rebuild so the new catalog is embedded.
|
|
make build
|
|
```
|
|
|
|
`scripts/publish-kernel.sh` reads the locally-imported entry under
|
|
`~/.local/state/banger/kernels/<name>/`, builds a tar+zstd archive, uploads
|
|
it to R2 via `rclone`, HEAD-checks the public URL, and patches
|
|
`internal/kernelcat/catalog.json` with the new URL, SHA256, and size.
|
|
|
|
Environment overrides if the defaults need to change:
|
|
`RCLONE_REMOTE`, `RCLONE_BUCKET`, `BASE_URL`, `BANGER_KERNELS_DIR`.
|
|
|
|
## Removing an entry
|
|
|
|
1. Delete the line from `internal/kernelcat/catalog.json` and commit.
|
|
2. Delete the tarball from R2: `rclone delete r2:banger-kernels/<name>-<arch>.tar.zst`.
|
|
3. Rebuild banger.
|
|
|
|
Already-pulled local copies on user machines are not invalidated — they
|
|
keep working until the user runs `banger kernel rm <name>`. That's
|
|
intentional: pulling is idempotent, removing should not break anyone in
|
|
the middle of a workflow.
|
|
|
|
## Versioning conventions
|
|
|
|
- **Entry names**: `<family>-<major.minor>` (e.g. `generic-6.12`).
|
|
The major.minor is the kernel line. Patch-level bumps reuse the
|
|
entry name and replace the tarball; minor bumps create a new entry
|
|
(`generic-6.13`).
|
|
- **Architecture**: only `x86_64` is published today. The `arch` field in
|
|
the catalog schema is additive — adding `arm64` later is a config
|
|
change, not a schema change.
|
|
- **Tarball layout**: contents at the archive root (no top-level
|
|
versioned directory). `vmlinux` is required; `initrd.img` and
|
|
`modules/` are optional. Symlinks inside `modules/` are allowed but
|
|
must resolve within the archive.
|
|
|
|
## Trust model
|
|
|
|
The embedded `catalog.json` carries the SHA256 of each tarball. `banger
|
|
kernel pull` rejects any download whose hash doesn't match. This protects
|
|
against transport corruption and against an attacker swapping a tarball
|
|
on R2 without also pushing a banger release.
|
|
|
|
It does **not** protect against a compromise of the banger source repo
|
|
itself — an attacker who can land a commit can change both the catalog
|
|
SHA256 and the tarball. GPG/sigstore signing of the published catalog
|
|
tarballs is deferred until banger is public and the threat model
|
|
justifies the operational overhead.
|
|
|
|
Upstream kernel sources *are* verified: `scripts/make-generic-kernel.sh`
|
|
fetches the detached PGP signature alongside the tarball from
|
|
kernel.org and rejects the build if gpg can't verify it against one
|
|
of the three known release signing keys (Greg KH / Linus / Sasha
|
|
Levin). So a compromised kernel.org mirror can't slip a backdoored
|
|
tarball past a maintainer rebuilding the kernel locally.
|
|
|
|
## Hosting
|
|
|
|
Tarballs live in Cloudflare R2 (bucket `banger-kernels`), served at the
|
|
custom domain `kernels.thaloco.com`. The bucket is publicly readable;
|
|
writes require the `banger-kernels-publish` API token (kept locally,
|
|
never committed). R2's free tier covers the expected traffic comfortably
|
|
(zero egress fees, generous storage).
|
|
|
|
If hosting ever moves, catalog entries can be migrated by reuploading the
|
|
tarballs and editing the URLs in `catalog.json` — no other code changes
|
|
required.
|
|
|
|
## Tech debt
|
|
|
|
- Kernel publishing is manual; there is no CI yet. `scripts/make-generic-kernel.sh`
|
|
plus `scripts/publish-kernel.sh` is fine while refreshes are
|
|
infrequent and maintainer-only. CI becomes relevant once banger
|
|
goes public.
|
|
- `make lint-shell` runs at `--severity=error` only. Tightening to
|
|
`--severity=warning` is a nice-to-have but low priority.
|