Repository navigation
Conversation
brig is to drive Linux sandboxes through hull, as it does on macOS (brig-sh/hull#105). hull on Linux is a containerd client that boots through urunc, so it needs this bundle's urunc, monitors and guest assets, but hull publishes no Linux release to fetch. So the build makes it from brig-sh/hull at a pinned commit, the way it makes urunc: fetched by SHA, refused if the checkout is anything else, recorded in pins.env as HULL_REF and HULL_PINNED, and checked by CI. hull is pure Go, so it is a static cross compile with no telemetry endpoint. stock leaves it out, as it leaves out hvi. nerdctl stays, and stays brig's runtime: the brig this bundle carries drives only nerdctl on Linux, and brig refuses an egress policy, a route, an isolated network and a published port on hull on Linux, so the shipped profiles would not run there yet. BRIG_RUNTIME=hull opts in. Two launcher changes make that opt-in work. BRIG_RUNTIME_BIN now follows BRIG_RUNTIME: it was always the bundle's nerdctl, and brig handed that path with BRIG_RUNTIME=hull drives nerdctl with hull's command line. A bundle without hull names no binary for it. And the launcher exports NETCONFPATH, the directory nerdctl.toml names: hull reads only the variable, and without it a root install's hull looks in /etc/cni/net.d and does not find the bundle's bridge network. hull's pin follows urunc's: hull checks the urunc keys it writes against one urunc commit, 3c00b69 at fb41d4a, which is this bundle's. Refs: brig-sh/hull#105 Signed-off-by: Charalampos Mainas <cmainas@nofire.ai>
|
@claude-fleet review |
|
Review task queued. Task: 21a2dc0d-f392-42fe-b8df-62dbd496b925 |
There was a problem hiding this comment.
Verified the hull pin against the real repo (cloned brig-sh/hull at fb41d4a), ran the pin tests and the cgo revert check.
Approve: one nit.
Findings:
- nit, scripts/build-bundle.sh:1495 — the reason given for exporting
NETCONFPATHis wrong; hull does find an installed bundle'snet.don its own
Verified:
make linux LINUX_ARCH=<arch>exists and writesdist/hull_linux_<arch>, which is what the build copies out — hullMakefile:126-131vs scripts/build-bundle.sh:1105.- No
TELEMETRY_ENDPOINTmeans an empty endpoint, not a default one — hullMakefile:66-68; the test also fails if the flag appears (tests/source-pins.sh:140). - hull is pure Go, so
CGO_ENABLED=0with no--platformis a real cross build —Makefile:130passesGOOS/GOARCHtogo build. - The pin is fetched by SHA and a different checkout is refused —
checkout_sourcescripts/build-bundle.sh:990-1008, exercised by tests/source-pins.sh:132-177. HULL_REF/HULL_BRANCHbehave as urunc's: branch without ref refused (scripts/build-bundle.sh:158-160), non-full-SHA refused by the new sharedrequire_sha(scripts/build-bundle.sh:170-180), empty ref builds the tip with a warning.- "hull checks the urunc keys against one urunc commit, which has to be this bundle's urunc" —
internal/urunckeys/go.modrequiresurunc v0.8.2-0.20261029205741-3c00b69ff9ac, equal toURUNC_REF_DEFAULT(scripts/build-bundle.sh:131). - The launcher's exports do reach hull:
NETCONFPATH(hullcmd/hull/net_linux.go:536),CONTAINERD_ADDRESSandCONTAINERD_NAMESPACE(internal/containerd/containerd.go:49,53, read via consts),BRIG_BOOT_ASSETS(internal/bootassets/bootassets.go). NETCONFPATHis the directorynerdctl.tomlnames, in both layouts: root/plain$ETC_DIR/cni/net.d(scripts/build-bundle.sh:1418 vs 1470, 1486), rootless non-root$XDG_CONFIG_HOME/brig/cni/net.d(scripts/build-bundle.sh:670 vs 1477), which is also exactly hull'srootlessBrigNetConfDir.hull --versionends inlinux/<arch>), so the CI pattern holds — hullinternal/buildinfo/buildinfo.go:167-176.BRIG_RUNTIME_BINnow followsBRIG_RUNTIMEand still defers to the environment; a bundle without hull emits nohull)branch (scripts/build-bundle.sh:1504-1513).[ "$HULL_INSTALLED" = true ] && install …(scripts/build-bundle.sh:1233) is safe underset -e: a failing non-final command of an AND list does not exit the shell.
Checks run:
sh tests/source-pins.sh→ 12 ok, no failures.- Revert check: dropped
-e CGO_ENABLED=0from scripts/build-bundle.sh:1103 →FAIL: hull was built with cgo; file restored, tree clean. git ls-remote https://github.com/brig-sh/hull HEAD→fb41d4a05d4a…, i.e. the pin is the current tip ofmain, not a commit behind it.
Smaller things:
- hull's
--snapshotterflag has no environment source (hullcmd/hull/run_linux.go:92-95), so the launcher'sCONTAINERD_SNAPSHOTTERapplies to nerdctl only and aBRIG_RUNTIME=hullrun on a plain bundle will not pick up devmapper. Nothing to change here, but it is the same class of gap as theNETCONFPATHone and may be worth a line in the README's hull section. - The bundled hull will report its version as
dev: the by-SHA--depth 1fetch carries no tags, so the Makefile'sgit describeis empty (hullMakefile:25) andbuildinfofalls back to"dev"(internal/buildinfo/buildinfo.go:81). The commit is still in the string and inpins.env, and the CI assertion only looks at the platform suffix, so this is cosmetic. - README.md:310 still says the bundle's hvi
v0.1.0-rc.2(commit2ed8f61) is "the one hull ships on macOS". At the newly pinned hull commit,hvi.pinnames0.1.0-rc.1/65570c7. hull does no runtime hvi version check, so this is a stale sentence rather than a build problem, but now that hull is pinned the claim is checkable. - For
--variant stock,pins.envgetsHULL_PINNED=(scripts/build-bundle.sh:1605 withHULL_PINNED=""), whereURUNC_PINNEDis alwaystrueorfalse. A consumer that reads the field gets an empty value rather than a boolean. CI only builds generic-boot, so nothing checks it. brig-env.shis the one generated script the lint job does notsh -n(ci.yml:22-50 covers the uninstaller, the rootless setup and brig-ctl), and the newcase/esacis now assembled from three heredocs. The new launcher step sources it, which covers it in practice.
Not checked:
- A full
scripts/build-bundle.shrun, the docker hull build, and an install: the bundle job is the first real exercise, as the description says. - Whether urunc
5c6bc7060is what hull's Linux network gateway needs, and the claims about brigv0.5.0refusing egress policies, routes,network: isolatedand published ports on hull on Linux — both live in other repos. - hull's behaviour at runtime on Linux beyond the environment variables above (gateway, assets verification, instance state paths).
Not checked:
- A full scripts/build-bundle.sh run, the docker hull build and an install (CI's bundle job is the first full build)
- Whether urunc 5c6bc7060 is what hull's Linux network gateway needs (other repo)
- brig v0.5.0's refusal of egress policies, routes, network: isolated and published ports on hull on Linux (other repo)
- hull's runtime behaviour on Linux beyond the environment variables the launcher sets
Task 21a2dc0d-f392-42fe-b8df-62dbd496b925 on ci-16gb-fsn1-1, model claude-opus-5, effort medium.
| # devmapper needs the system thin pool, so a rootless stack stays on overlayfs. | ||
| export CONTAINERD_SNAPSHOTTER="\${CONTAINERD_SNAPSHOTTER:-$SNAPSHOTTER}" | ||
| export CNI_PATH="\${CNI_PATH:-$CNI_DIR}" | ||
| # NETCONFPATH, set above, is the directory nerdctl.toml names. nerdctl reads |
There was a problem hiding this comment.
nit: The comment's reason for exporting NETCONFPATH is wrong: hull does not fall back to /etc/cni/net.d for an installed bundle. hull's cniConfig walks bootassets.BundleDirs() first and uses
/etc/cni/net.d when it exists, where BundleDirs is /var/lib/brig/data (plus ~/.local/share/brig/data for a non-root euid) -- i.e. exactly the default root and user install prefixes -- and it then prefers $XDG_CONFIG_HOME/brig/cni/net.d for a rootless user.Failure: no runtime failure; the export is correct and matches nerdctl.toml. The claim is what is wrong, and a later reader judging a change against it (for instance, dropping the export or assuming hull has no bundle discovery) would be reasoning from a false premise.
Evidence: hull at the pinned fb41d4a, cmd/hull/net_linux.go:507-539 (bundleDirs loop, then rootlessBrigNetConfDir, then $NETCONFPATH) and internal/bootassets/bundle_linux.go:34-57 (systemBundle = /var/lib/brig/data). The same wording is in the PR description.
Fix: say that hull's own discovery covers the default prefixes and that the export is what makes a retargeted install (install.sh --prefix) work, and is read in preference to that discovery.
ananos
left a comment
There was a problem hiding this comment.
thanks @cmainas, nice to have hull in the bundle! The pin, the static build and the pins.env plumbing follow urunc's recipe, which is the right call. Two things to fix before this goes in, both inline:
- The hull the bundle builds reports
v0.0.0-..., and brig reads that as an old hull. - After
eval "$(brig-ctl env)",BRIG_RUNTIME=hullkeeps the nerdctl binary.
Two smaller ones, fine as follow-ups: nothing checks that HULL_REF and URUNC_REF agree (the README says they must, so a check against internal/urunckeys/go.mod after the checkout would make it true), and golang:1.26.8 is a tag rather than a digest, as for urunc. Also, hull does find an installed bundle's etc/cni/net.d on its own (net_linux.go, bundleDirs), so the NETCONFPATH comment should say the export keeps hull and nerdctl.toml on one directory, not that hull reads only the variable.
| hsrc="$TMP_DIR/hull-src" | ||
| HULL_PINNED=true | ||
| [ -n "$HULL_REF" ] || HULL_PINNED=false | ||
| h_commit="$(checkout_source "$HULL_REPO" "$HULL_BRANCH" "$HULL_REF" "$hsrc")" |
There was a problem hiding this comment.
This is a depth-1 fetch with no tags, so Go stamps the module as a pseudo-version, and hull's buildinfo prefers that over its git describe fallback. The CI run of this PR shows it: hull v0.0.0-20261111171032-fb41d4a05d4a (fb41d4a, 2026-11-11, go1.26.8, linux/arm64).
brig parses that as 0.0.x, older than rc23, so with BRIG_RUNTIME=hull it stops pinning boot assets by digest and falls back to tag verification with a weaker-verification alert (hullVersionPinsDigest, wrap/verify.go). brig doctor would also list the runtime as hull 0.0.0.
We should fetch the tags (or enough history for git describe --tags --long --match 'v[0-9]*' to find one) before make linux, and have the CI step assert that hull --version does not start with hull v0.0.0.
| CFG | ||
| if [ "$HULL_INSTALLED" = true ]; then | ||
| cat >> "$STAGE/etc/brig-env.sh" <<CFG | ||
| hull) export BRIG_RUNTIME_BIN="\${BRIG_RUNTIME_BIN:-$BIN_DIR/hull}" ;; |
There was a problem hiding this comment.
${BRIG_RUNTIME_BIN:-...} keeps an inherited value whatever runtime set it. The README's flow hits this: eval "$(brig-ctl env)" exports BRIG_RUNTIME_BIN=.../nerdctl, and a later BRIG_RUNTIME=hull brig doctor reaches brig with that path, so brig drives nerdctl with hull's command line. Nothing re-reads this file in between. The CI check sources it under env -i, so it cannot see this.
Two ways out, maybe both: say in the README that BRIG_RUNTIME goes before the eval (or pass BRIG_RUNTIME_BIN too), and have this arm replace an inherited bin that equals the other runtime's default. A CI case that sources the file twice, default then BRIG_RUNTIME=hull, would lock it in.
Summary
brig is moving to drive Linux sandboxes through hull, as on macOS (brig-sh/hull#105). hull on Linux boots through this bundle's urunc, monitors and guest assets, but it publishes no Linux release, so the bundle now builds it from a pinned commit, the way it builds urunc.
nerdctl stays, and stays the default: the bundled brig
v0.5.0drives only nerdctl on Linux, and brig still refuses egress policies, routes,network: isolatedand published ports on hull on Linux, so the shipped profiles would not run there yet.BRIG_RUNTIME=hullopts in.Changes
brig-sh/hullatfb41d4a, fetched by SHA and refused if the checkout differs, built static (CGO_ENABLED=0) with no telemetry endpoint, and recorded inpins.envasHULL_REF/HULL_PINNED.HULL_REF/HULL_BRANCHwork like urunc's. stock leaves it out, as it leaves out hvi.BRIG_RUNTIME_BINwas always the bundle's nerdctl, soBRIG_RUNTIME=hullwould have driven nerdctl with hull's command line. It now followsBRIG_RUNTIME, and a bundle without hull names no binary for it.NETCONFPATH. hull reads only the variable, so a root install's hull would look in/etc/cni/net.dand miss the bundle's bridge. The value is the directorynerdctl.tomlalready names.tests/source-pins.shcovers hull's pin; CI checks the recorded pin, thathull --versionends inlinux/<arch>, and what the launcher exports for each runtime.Testing
tests/*.shall pass, including the new hull cases. The cgo check fails withCGO_ENABLED=0removed.brig-env.shgeneration code, run for plain and rootless bundles with and without hull, exports what the new CI step expects in all twelve cases.fb41d4awith the recipe's checkout andmake linux, but with the host's Go 1.26.8 rather than thegolang:1.26.8container: a static binary whose--versionends inlinux/amd64).build-bundle.shbuild, the docker step of the hull build, and an install. CI's bundle job is the first full build.Follow-ups
5c6bc7060(feat/linux-hvi-v050-socket) is what hull's Linux network gateway needs. Moving to it waits for a hull-assets release built from it, sincecheck-assets.shrefuses a mismatch./var/log/hull,~/.local/state/hull), andnix/runtime.nixdoes not carry hull.