docs: the subnet auto-pick — help, README, changelog, doctor wording (#80)

help setup-host and the README now lead with what a bare run does (free
default → 10.88; existing bridge → converge; claimed default → auto-pick
10.89…10.127, announced) and demote BOX_SUBNET to what it is: the pin for
scripted hosts, honored or refused, never overridden. The changelog names
the drill/rehearsal payoff — nested box-in-box with zero flags. The
doctor's this-machine #80 verdict stops saying "setup-host now refuses
this" (it no longer does, it picks around it): a poisoned stack predates
the fix or was pinned onto the uplink.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
dan-claude-bot 2026-07-18 21:20:51 +00:00
parent 5d893ba2e1
commit ff94af93c3
4 changed files with 50 additions and 23 deletions

View file

@ -7,6 +7,23 @@ which records not just what changed but what each drill run proved.
### Added ### 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** - **`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 (#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 the exact subnet and gateway of the guest's own uplink: the guest then held

View file

@ -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): the host lacks `dnsmasq-base` (Debian cloud images skip Recommends):
`sudo apt-get install -y dnsmasq-base`. `sudo apt-get install -y dnsmasq-base`.
The stack's subnet is `10.88.0.0/24` by default; `BOX_SUBNET` picks another The stack's subnet is `10.88.0.0/24` when free. setup-host **never builds on
`/24` (`BOX_SUBNET=10.89.0.0/24 box setup-host` — the bridge address, the a subnet something else already claims** — most tellingly when this machine's
ACL's gateway carve-out and the firewall all derive from it). setup-host own default gateway sits inside it, which means it is being run *inside a
**refuses to build on a subnet something already claims** — most tellingly box*: a nested `boxnet` on the guest's own uplink subnet captures its gateway
when this machine's own default gateway sits inside it, which means it is address and blackholes the guest's egress in intermittent,
being run *inside a box*: a nested `boxnet` on the guest's own uplink subnet maddening-to-attribute blackouts
captures its gateway address and blackholes the guest's egress in ([#80](https://github.com/heavy-duty/box/issues/80)). Instead of refusing, a
intermittent, maddening-to-attribute blackouts bare `box setup-host` decides for itself: an existing `boxnet` bridge is
([#80](https://github.com/heavy-duty/box/issues/80)). `BOX_SUBNET` is the converged on as-is (the bridge is the pin — it is never re-addressed), and a
sanctioned way out for a nested or otherwise-conflicted install, and claimed default triggers an auto-pick of the first free `/24` from
`box doctor` recognizes the poisoned state (a gateway held as a local `10.89.0.0/24` through `10.127.0.0/24`, announced loudly — so drills and
address, duplicate uplink routes) on the machine it runs on and inside every rehearsals *inside a box* work with zero flags. `BOX_SUBNET=<a.b.c.0/24>`
box it probes. 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` 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 re-homes each legacy box onto `boxnet` (authed state preserved), and

23
bin/box
View file

@ -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 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. 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 stack's subnet: 10.88.0.0/24 when free; with an existing boxnet it
(the bridge, the gateway carve-out and the firewall all derive from it). It converges on the bridge's own subnet; and when the default is claimed by
REFUSES, before touching anything, where the target subnet is already claimed something else — most tellingly this machine's own default gateway, i.e.
— most tellingly when this machine's own default gateway sits inside it, setup-host running INSIDE a box — it auto-picks the first free /24 from
i.e. when you are running setup-host INSIDE a box: a nested stack on the 10.89.0.0/24 through 10.127.0.0/24 and says so. A nested stack on the
guest's own uplink subnet captures its gateway address and blackholes its guest's own uplink subnet would capture its gateway address and blackhole
egress, intermittently (issue #80). The sanctioned way to nest: 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 setup-host # picks/converges by itself
BOX_SUBNET=10.89.0.0/24 box setup-host # nested, or a conflicted host 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 Multi-user hosts: setup-host builds the stack once, for everyone. An admin
then hands individual users the restricted tier with 'box grant <user>' — then hands individual users the restricted tier with 'box grant <user>' —

View file

@ -129,7 +129,8 @@ if [ -n "$sig" ]; then
while IFS= read -r line; do no "$line"; done <<<"$sig" 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 "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 "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 "fix: move the nested bridge off the uplink's subnet:"
inf " sudo incus network set boxnet ipv4.address 10.89.0.1/24" inf " sudo incus network set boxnet ipv4.address 10.89.0.1/24"
inf " (or remove the nested stack: box teardown-host)" inf " (or remove the nested stack: box teardown-host)"