diff --git a/CHANGELOG.md b/CHANGELOG.md index f9cb045..8715206 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,7 +65,7 @@ installer retires — but nothing current carries the old name. - **Debrand complete** — env vars, install dir, docs, template descriptions and the README all say `box`; the install URL is `heavy-duty/box` (GitHub redirects the old one, `BOX_REPO` overrides). -- **The drill grew from 47 to 83 checks** — the expose door opened, exercised +- **The drill grew from 47 to 84 checks** — the expose door opened, exercised and shut (with the contract re-probed around it), every template minted cold, a faithful pre-0.4.0 box re-homed through `migrate-host`, and the inline resource flags asserted (including their precedence over the diff --git a/README.md b/README.md index 10374c8..94aa408 100644 --- a/README.md +++ b/README.md @@ -252,7 +252,7 @@ drill installs the whole stack, mints every template cold, snapshots and clones, probes every boundary from inside the boxes, opens and shuts the `expose` door (and checks the contract survives it), re-homes a faithful pre-0.4.0 box through `migrate-host`, and removes what it minted — -currently **83 checks**. [drill/RUNS.md](drill/RUNS.md) is the full +currently **84 checks, 84 passing**. [drill/RUNS.md](drill/RUNS.md) is the full history, including every trap that fooled a run into a wrong verdict. ### Run the drill yourself diff --git a/drill/doctor.sh b/drill/doctor.sh index df91ebc..546c7cd 100755 --- a/drill/doctor.sh +++ b/drill/doctor.sh @@ -40,6 +40,12 @@ timeout 10 incus list >/dev/null 2>&1 || { exit 1 } +# A FRESH host (no boxnet) is not a DIRTY one. Everything below that would +# scream about a missing piece must first ask: missing from a stack, or never +# set up? setup-host creates all of it, and the drill runs setup-host itself — +# a bare host went 84/84 green minutes after this doctor called it unfit. +FRESH=0 + head_ "Network — boxnet" if incus network show boxnet >/dev/null 2>&1; then # dns.mode=none is SHIPPED — it is what stops a box enumerating its siblings @@ -79,12 +85,15 @@ if incus network show boxnet >/dev/null 2>&1; then [ "$ipv6" = none ] && ok "ipv6.address = none (the isolation contract — every ACL rule is IPv4-only)" \ || no "ipv6.address = $ipv6 — IPv6 is on and NOT covered by any ACL rule" else + FRESH=1 inf "boxnet does not exist (a fresh host — setup-host.sh will create it)" fi head_ "Firewall — the box-to-box drop" if sudo nft list table bridge box >/dev/null 2>&1; then ok "nft bridge table 'box' is present — boxes cannot reach each other" +elif [ "$FRESH" = 1 ]; then + inf "not installed yet (a fresh host — setup-host.sh installs it)" else no "the box-to-box drop is MISSING — boxes can reach each other" inf "an L3 ACL never sees frames switched between two ports of one bridge;" @@ -186,6 +195,16 @@ raw="$(incus network get boxnet raw.dnsmasq 2>/dev/null | tr '\n' ';')" if [ -n "$raw" ]; then ok "boxnet has a pinned resolver (raw.dnsmasq: $raw)" inf "boxes do NOT inherit the host's resolver — good (issue #33)" +elif [ "$FRESH" = 1 ]; then + # No boxnet, so there is nothing to pin YET. A VPN resolver on the host is + # worth naming, but it is a fact about the host, not a fault in a stack + # that does not exist — setup-host pins around it at creation. + if printf '%s' "$hostns" | grep -qE '(^| )100\.(6[4-9]|[7-9][0-9]|1[01][0-9]|12[0-7])\.'; then + inf "the host resolves via a CGNAT/Tailscale resolver ($hostns) — noted, not a fault:" + inf "setup-host pins the box resolver to public upstreams, so boxes will not inherit it (issue #33)" + else + inf "no boxnet yet — setup-host.sh pins its resolver at creation" + fi else # 100.64.0.0/10 is CGNAT — which is exactly Tailscale's range. if printf '%s' "$hostns" | grep -qE '(^| )100\.(6[4-9]|[7-9][0-9]|1[01][0-9]|12[0-7])\.'; then @@ -255,7 +274,12 @@ fi head_ "Verdict" if [ "$bad" -eq 0 ]; then - printf ' \033[32mclean\033[0m — this host is fit to mint boxes (and to drill).\n\n' + if [ "$FRESH" = 1 ]; then + printf ' \033[32mfresh\033[0m — no box stack on this host yet, and nothing dirty either.\n' + printf ' run: box setup-host (or the drill — it sets the host up itself)\n\n' + else + printf ' \033[32mclean\033[0m — this host is fit to mint boxes (and to drill).\n\n' + fi exit 0 fi printf ' \033[31m%s problem(s)\033[0m — this host is NOT fit to mint boxes (or to drill).\n' "$bad"