diff --git a/CHANGELOG.md b/CHANGELOG.md index 60b118f..e66176c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,23 @@ which records not just what changed but what each drill run proved. ### Added +- **`setup-host` auto-picks a free subnet — nested box-in-box with zero + flags** (#80, completing its fix #1: "refuse … or automatically select a + non-colliding subnet"). A bare `box setup-host` now decides the subnet + itself, in four deliberate cases: an explicit `BOX_SUBNET` is honored or + refused, never silently overridden (scripted hosts keep exact semantics); + an existing `boxnet` bridge is converged on as-is — the bridge IS the pin — + turning the old bare-re-run agree-gate refusal into plain convergence + (unless a foreigner *also* claims the bridge's subnet: that is #80's + poisoned state, and converging would rebuild on it, so it still refuses and + names the bridge move); a free `10.88.0.0/24` stays the default; and a + *claimed* default — the nested case: a drill or rehearsal running inside a + box, whose own uplink owns 10.88 — scans `10.89.0.0/24` … `10.127.0.0/24` + in order, takes the first free candidate, announces the pick and the + claimant loudly, and only refuses when every candidate is claimed. The + decision happens before any mutation, and everything downstream (the + bridge, `BOX_GW`, the ACL's gateway carve-out, the firewall, the doctor's + expectations) derives from it. - **`setup-host` refuses a claimed subnet, and `BOX_SUBNET` picks another** (#80) — run inside a box, `setup-host` used to build a nested `boxnet` on the exact subnet and gateway of the guest's own uplink: the guest then held diff --git a/README.md b/README.md index 8ef93b6..f0d82f3 100644 --- a/README.md +++ b/README.md @@ -129,19 +129,23 @@ re-apply at boot via `box-firewall.service` — no post-reboot ritual. If the host lacks `dnsmasq-base` (Debian cloud images skip Recommends): `sudo apt-get install -y dnsmasq-base`. -The stack's subnet is `10.88.0.0/24` by default; `BOX_SUBNET` picks another -`/24` (`BOX_SUBNET=10.89.0.0/24 box setup-host` — the bridge address, the -ACL's gateway carve-out and the firewall all derive from it). setup-host -**refuses to build on a subnet something already claims** — most tellingly -when this machine's own default gateway sits inside it, which means it is -being run *inside a box*: a nested `boxnet` on the guest's own uplink subnet -captures its gateway address and blackholes the guest's egress in -intermittent, maddening-to-attribute blackouts -([#80](https://github.com/heavy-duty/box/issues/80)). `BOX_SUBNET` is the -sanctioned way out for a nested or otherwise-conflicted install, and -`box doctor` recognizes the poisoned state (a gateway held as a local -address, duplicate uplink routes) on the machine it runs on and inside every -box it probes. +The stack's subnet is `10.88.0.0/24` when free. setup-host **never builds on +a subnet something else already claims** — most tellingly when this machine's +own default gateway sits inside it, which means it is being run *inside a +box*: a nested `boxnet` on the guest's own uplink subnet captures its gateway +address and blackholes the guest's egress in intermittent, +maddening-to-attribute blackouts +([#80](https://github.com/heavy-duty/box/issues/80)). Instead of refusing, a +bare `box setup-host` decides for itself: an existing `boxnet` bridge is +converged on as-is (the bridge is the pin — it is never re-addressed), and a +claimed default triggers an auto-pick of the first free `/24` from +`10.89.0.0/24` through `10.127.0.0/24`, announced loudly — so drills and +rehearsals *inside a box* work with zero flags. `BOX_SUBNET=` +pins the subnet explicitly for scripted hosts (the bridge address, the ACL's +gateway carve-out and the firewall all derive from it); a pin is honored or +refused, never silently overridden. `box doctor` recognizes the poisoned +state (a gateway held as a local address, duplicate uplink routes) on the +machine it runs on and inside every box it probes. A host still carrying the pre-0.4.0 stack: `box migrate-host --all-boxes` re-homes each legacy box onto `boxnet` (authed state preserved), and diff --git a/bin/box b/bin/box index 2618795..a669144 100755 --- a/bin/box +++ b/bin/box @@ -502,16 +502,21 @@ install.sh runs it for you, so this is for re-applying by hand. One run is enough. If it has to add you to the incus-admin group it re-runs itself under that group — no re-login, no second invocation. -The stack's subnet is 10.88.0.0/24 by default; BOX_SUBNET picks another /24 -(the bridge, the gateway carve-out and the firewall all derive from it). It -REFUSES, before touching anything, where the target subnet is already claimed -— most tellingly when this machine's own default gateway sits inside it, -i.e. when you are running setup-host INSIDE a box: a nested stack on the -guest's own uplink subnet captures its gateway address and blackholes its -egress, intermittently (issue #80). The sanctioned way to nest: +The stack's subnet: 10.88.0.0/24 when free; with an existing boxnet it +converges on the bridge's own subnet; and when the default is claimed by +something else — most tellingly this machine's own default gateway, i.e. +setup-host running INSIDE a box — it auto-picks the first free /24 from +10.89.0.0/24 through 10.127.0.0/24 and says so. A nested stack on the +guest's own uplink subnet would capture its gateway address and blackhole +its egress, intermittently (issue #80); the auto-pick is why a drill or +rehearsal inside a box now works with zero flags. BOX_SUBNET pins the +subnet explicitly (the bridge, the gateway carve-out and the firewall all +derive from it) — a pin is never overridden: setup-host REFUSES, before +touching anything, when the pinned subnet is claimed by a foreigner or +disagrees with an existing bridge. - box setup-host - BOX_SUBNET=10.89.0.0/24 box setup-host # nested, or a conflicted host + box setup-host # picks/converges by itself + BOX_SUBNET=10.90.0.0/24 box setup-host # scripted hosts: pin it Multi-user hosts: setup-host builds the stack once, for everyone. An admin then hands individual users the restricted tier with 'box grant ' — diff --git a/drill/doctor.sh b/drill/doctor.sh index 6a33185..982443d 100755 --- a/drill/doctor.sh +++ b/drill/doctor.sh @@ -129,7 +129,8 @@ if [ -n "$sig" ]; then while IFS= read -r line; do no "$line"; done <<<"$sig" inf "a box stack was built on a machine whose uplink already owns its subnet —" inf "run inside a box, that is issue #80: egress blacks out intermittently while" - inf "everything looks healthy. setup-host now refuses this; this machine already has it." + inf "everything looks healthy. setup-host now auto-picks a free subnet for the" + inf "nested case, so this stack predates the fix (or was pinned onto the uplink)." inf "fix: move the nested bridge off the uplink's subnet:" inf " sudo incus network set boxnet ipv4.address 10.89.0.1/24" inf " (or remove the nested stack: box teardown-host)"