The lab had a registry that production does not, so it tested a fiction
The lab raised a `registry` VM, pushed ~73 images into it from the workstation, and rewrote every manifest reference — third-party ones included — to point at it. No production mesh has such a thing. So every bed proved that a machine could fetch an image from a registry that exists nowhere else, and the bootstrap problems that only appear when a machine has to fetch for itself went unfound. What replaces it is the two things that are true in the world: **Public images come from the public internet.** mesh-lab already created a NAT'd uplink for exactly this and attached it to any machine declaring `egress`; no scenario ever declared it. They do now, and third-party references are left exactly as the catalogue writes them. **The mesh's own images have no registry and never will.** mesh-control, mesh-builder, mesh-route-proxy and the per-module runtimes are built from source and exist in no registry. A machine gets them the way an operator's machine does — they are built here and loaded onto it — and is then named by the digest of its own image configuration, which mesh-host now accepts as "an image this machine already holds". `images:` therefore means only *ours*, and a third-party entry is refused rather than quietly loaded: otherwise the fiction returns one convenient line at a time. It is per-machine as well, because "everything, everywhere" was never a description of anything real — handing whole-mesh-full's union to its two 30GiB workstations would fill the disk with runtimes nothing on them will start. **The uplink and the declared gateway would have fought, silently.** A gateway container and the transit router reach the scenario and nothing else; a default route through either is a black hole for anything outside, and it beats the uplink's DHCP route on metric. So a machine with egress states the scenario's ranges explicitly — through the same gateway or transit it would have defaulted to, so the overlay-across-NAT path is unchanged — and leaves the default to the uplink. A range with no path inside the scenario becomes `unreachable` rather than falling through: 192.168.1.0/24 is an ordinary private range in fact, and letting it escape would put scenario traffic on whatever network the workstation is sitting on. `scenarioRoutesFor` is pure and tested, because a decision only a full raise could check is one nobody checks. The registry-reachability check the raise gained earlier is kept, pointed at the real thing: every machine with egress must resolve a name and reach the internet before the raise says it finished. Same failure it was written for — a raise that returns, an apply that dies on its first pull, an instance left a bare shell — now guarding the path that actually carries. The base image's trust of the documentation ranges as plain-HTTP registries STAYS. It was never only for the lab's registry: the mesh has one of its own, the `registry` module, serving artifacts to the whole mesh over plain HTTP from whatever node runs it. Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
This commit is contained in:
+14
-7
@@ -87,10 +87,16 @@ export async function buildBaseImage(
|
||||
|
||||
// Trust the documentation ranges as plain-HTTP registries.
|
||||
//
|
||||
// A scenario's registry is scenery inside the scenario, serving over HTTP, and a runtime
|
||||
// will not pull from one without being told. Scoped to RFC 5737 and RFC 3849 ranges rather
|
||||
// than a specific address, because those never route on the real internet — so this cannot
|
||||
// make a real machine trust a real registry, whatever it is copied onto.
|
||||
// **Kept after the lab's own registry was deleted, because it was never only for that.** The
|
||||
// mesh HAS a registry — the `registry` module, `mesh-registry`, serving artifacts to the whole
|
||||
// mesh on port 5000 over plain HTTP from whatever node runs it. In a scenario that node's
|
||||
// address is a documentation-range address, and a runtime will not pull from a plain-HTTP
|
||||
// registry without being told to. Take this away and the artifact store is unusable from every
|
||||
// machine but the one hosting it.
|
||||
//
|
||||
// Scoped to RFC 5737 and RFC 3849 ranges rather than a specific address, because those never
|
||||
// route on the real internet — so this cannot make a real machine trust a real registry,
|
||||
// whatever it is copied onto.
|
||||
await incus([
|
||||
"exec", BUILDER, "--", "sh", "-c",
|
||||
`mkdir -p /etc/docker && printf '%s' '${JSON.stringify({
|
||||
@@ -162,8 +168,8 @@ export async function buildBaseImage(
|
||||
|
||||
// Read back that the runtime will actually pull over plain HTTP from a documentation
|
||||
// range. Writing the file is not the same as the daemon honouring it, and a base image
|
||||
// that looks right here fails much later — in a sealed scenario, as a container that
|
||||
// cannot fetch its image, which is a long way from the cause.
|
||||
// that looks right here fails much later — as a container that cannot fetch its image
|
||||
// from the mesh's own artifact store, which is a long way from the cause.
|
||||
const trusted = await incusOk(
|
||||
["exec", BUILDER, "--", "docker", "info", "--format", "{{.RegistryConfig.InsecureRegistryCIDRs}}"],
|
||||
60_000,
|
||||
@@ -172,7 +178,8 @@ export async function buildBaseImage(
|
||||
throw new BaseImageError(
|
||||
`the runtime in ${BUILDER} does not trust the documentation ranges as plain-HTTP ` +
|
||||
`registries. It reported: ${trusted?.trim() || "nothing"}\n` +
|
||||
` Every scenario raised from this image would fail to pull from its own registry.`,
|
||||
` Every scenario raised from this image would fail to pull from the mesh's own ` +
|
||||
`artifact store, which serves plain HTTP inside the scenario.`,
|
||||
);
|
||||
}
|
||||
log(" trusts the documentation ranges as registries");
|
||||
|
||||
Reference in New Issue
Block a user