refactor(templates): the tenant seeds carry rig's -box family suffix
rig is growing a second family of roles, and once a 'staging' role can mean either a fleet machine or a box tenant, the bare name stops naming anything. rig's answer is a suffix on the role (heavy-duty/rig#76): '-server' for fleet machines, '-box' for box tenants. box's answer is that a template keeps being named for the role it converges, so the tenant templates move with it: claude -> claude-box codex -> codex-box grok -> grok-box staging -> staging-box Templates are the only surface that spells a rig role out loud (BOX_BOOTSTRAP_ROLE, auto-run at mint since #81), so a directory that says one thing and a role key that says another is a trap with a 15-minute fuse: it mints clean and dies at convergence. Renamed with 'git mv' so the history of each seed follows it. 'blank' keeps its name. It seeds no tenant role and sets no BOX_BOOTSTRAP_ROLE, so it has nothing to agree with — renaming it would only churn the default template's name for symmetry's sake. Two namespaces move apart here and only one of them moved: the template name and the role are now claude-box, while the seed USER stays 'claude' — that is the user rig's role converges and the one 'box shell' lands in. test/cli.sh pins the pair per tenant rather than each half alone, because a later rename that moves one and forgets the other mints a box whose role dies looking for a user nobody created. drill.sh keeps its bare box NAMES ('codex', 'grok' — what the pre-flight banner announces and what teardown deletes) and only moves the --template it passes. The mint-time hints in cmd_new match both spellings of user.box.template, and that is not an alias for the role: 'rig bootstrap claude' is gone and nothing here softens the cut. The stamp is a fact about an INSTANCE, written at its own mint time and carried forward by every clone; refusing the old spelling would cut nothing over and only drop the login hint on boxes that predate today — the same reason user.claudebox is honored everywhere else. migrate-host.sh stamps re-homed legacy boxes claude-box, the name the template has today, so a re-homed box looks like a fresh mint rather than a fossil. Ordered AFTER rig's rename, and that is not a preference. The seeds install rig from RIG_REPO/RIG_REF, defaulting to heavy-duty/rig@main and unpinned until rig#32's releases, so these templates ask whatever main happens to be for 'rig bootstrap claude-box'. Against a pre-rename rig that role does not exist and cmd_new refuses to call the box ready. Merged in the other order the window closes instead of opening: rig's cut is hard, with no aliases, so the day it lands every unmerged box seed naming a bare role is the broken one. Closes #123 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
15b67d938e
commit
86dbb0449e
16 changed files with 176 additions and 87 deletions
44
CHANGELOG.md
44
CHANGELOG.md
|
|
@ -5,6 +5,50 @@ which records not just what changed but what each drill run proved.
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **The tenant templates carry rig's family suffix: `claude` → `claude-box`,
|
||||||
|
`codex` → `codex-box`, `grok` → `grok-box`, `staging` → `staging-box`**
|
||||||
|
(#123, following heavy-duty/rig#76) — rig is growing a second family of
|
||||||
|
roles, and once a `staging` role can mean either a fleet machine or a box
|
||||||
|
tenant, the bare name stops naming anything. rig's answer is a suffix on
|
||||||
|
the role itself — `-server` for fleet machines, `-box` for box tenants —
|
||||||
|
and box's answer is that a template keeps being named for the role it
|
||||||
|
converges. Templates are the only surface that spells a rig role out loud
|
||||||
|
(`BOX_BOOTSTRAP_ROLE`, auto-run at mint since #81), so a template whose
|
||||||
|
directory says one thing and whose role key says another is a trap with a
|
||||||
|
15-minute fuse: it mints clean and dies at convergence. `blank` keeps its
|
||||||
|
name — it seeds no tenant role, sets no `BOX_BOOTSTRAP_ROLE`, and
|
||||||
|
therefore has nothing to agree with. Two namespaces move apart here and
|
||||||
|
only one of them moved: the template name and the role are now
|
||||||
|
`claude-box`, while the seed USER stays `claude`, because that is the user
|
||||||
|
the rig role converges and the one `box shell` lands in. `test/cli.sh`
|
||||||
|
pins the pair per tenant rather than each half alone — a future rename
|
||||||
|
that moves one and forgets the other mints a box whose role dies looking
|
||||||
|
for a user nobody created.
|
||||||
|
|
||||||
|
**This lands after rig's rename, not before, and the ordering is not a
|
||||||
|
preference.** The seeds install rig from `RIG_REPO`/`RIG_REF`, which
|
||||||
|
default to `heavy-duty/rig@main` and are unpinned until rig#32's releases
|
||||||
|
— so a box minted from these templates asks whatever `main` happens to be
|
||||||
|
for `rig bootstrap claude-box`. Against a pre-rename rig that role does
|
||||||
|
not exist, `cmd_new` refuses to call the box ready, and the operator is
|
||||||
|
handed a failed mint for a change neither repo has finished making. Merged
|
||||||
|
in the other order the window closes instead of opening: rig's roles are a
|
||||||
|
hard cut with no aliases, so the day rig's rename lands, every unmerged
|
||||||
|
box seed naming a bare role is the broken one.
|
||||||
|
|
||||||
|
One deliberate asymmetry: the mint-time hints in `cmd_new` match both the
|
||||||
|
new and the old spelling of `user.box.template`. That is not an alias for
|
||||||
|
the role — nothing here softens the cut, and `rig bootstrap claude` is
|
||||||
|
gone. It reads a stamp left on an *instance* at its own mint time, which
|
||||||
|
every box minted before today carries forever and every clone carries
|
||||||
|
forward; refusing the old spelling would cut nothing over and only drop
|
||||||
|
the login hint on boxes that predate the rename, the same reason
|
||||||
|
`user.claudebox` is honored everywhere else. `migrate-host.sh` stamps
|
||||||
|
re-homed legacy boxes `claude-box`, the name the template has today, so a
|
||||||
|
re-homed box looks like a fresh mint rather than a fossil.
|
||||||
|
|
||||||
## 0.8.0 — 2026-07-19
|
## 0.8.0 — 2026-07-19
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
||||||
38
README.md
38
README.md
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
**Headless, trust-less, throwaway dev VMs.** One command mints a fresh,
|
**Headless, trust-less, throwaway dev VMs.** One command mints a fresh,
|
||||||
network-isolated Incus box from a **template**; the coding-agent templates
|
network-isolated Incus box from a **template**; the coding-agent templates
|
||||||
hand you a CLI agent on Debian 13 — `claude` (Claude Code), `codex` (OpenAI
|
hand you a CLI agent on Debian 13 — `claude-box` (Claude Code), `codex-box`
|
||||||
Codex), `grok` (xAI Grok) — **box mints, [rig](https://github.com/heavy-duty/rig)
|
(OpenAI Codex), `grok-box` (xAI Grok) — **box mints, [rig](https://github.com/heavy-duty/rig)
|
||||||
converges**: the template is a thin seed, and the agent tooling lands via a
|
converges**: the template is a thin seed, and the agent tooling lands via a
|
||||||
creds-free `rig bootstrap` role auto-run at mint
|
creds-free `rig bootstrap` role auto-run at mint
|
||||||
([#81](https://github.com/heavy-duty/box/issues/81)). The box is the product
|
([#81](https://github.com/heavy-duty/box/issues/81)). The box is the product
|
||||||
|
|
@ -217,13 +217,14 @@ VM boundary itself is proven on real hardware, like the rest of the drill).
|
||||||
## Quick start
|
## Quick start
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
box new --name work --template claude # a creds-free coding-agent box (~10 min cold)
|
box new --name work --template claude-box # a creds-free coding-agent box (~10 min cold)
|
||||||
box shell work # enter as the template's user
|
box shell work # enter as the template's user
|
||||||
```
|
```
|
||||||
|
|
||||||
Pick whichever coding-agent template you like — `claude`, `codex`, `grok` — or
|
Pick whichever coding-agent template you like — `claude-box`, `codex-box`,
|
||||||
`blank` for none. Inside the box, authenticate as needed. The `claude` template
|
`grok-box` — or `blank` for none. Inside the box, authenticate as needed. The
|
||||||
looks like this; the others follow the same shape with their own login step:
|
`claude-box` template looks like this; the others follow the same shape with
|
||||||
|
their own login step:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
claude # then run /login — copy the URL (press c), open it
|
claude # then run /login — copy the URL (press c), open it
|
||||||
|
|
@ -239,12 +240,12 @@ No coding agent is special — each is one template among several, and adding
|
||||||
another is just another directory. What ships today:
|
another is just another directory. What ships today:
|
||||||
|
|
||||||
| Template | What it becomes |
|
| Template | What it becomes |
|
||||||
| --------- | ---------------------------------------------------------------------- |
|
| ------------- | ------------------------------------------------------------------ |
|
||||||
| `blank` | Bare Debian 13 — same isolation, no tooling. The default. |
|
| `blank` | Bare Debian 13 — same isolation, no tooling. The default. |
|
||||||
| `claude` | Claude Code, creds-free — where this project started |
|
| `claude-box` | Claude Code, creds-free — where this project started |
|
||||||
| `codex` | OpenAI Codex CLI, creds-free |
|
| `codex-box` | OpenAI Codex CLI, creds-free |
|
||||||
| `grok` | xAI Grok CLI, creds-free |
|
| `grok-box` | xAI Grok CLI, creds-free |
|
||||||
| `staging` | Server-class: docker + sshd hardening via rig; VM-only, autostarts |
|
| `staging-box` | Server-class: docker + sshd hardening via rig; VM-only, autostarts |
|
||||||
|
|
||||||
**Templates are thin seeds; rig does the becoming**
|
**Templates are thin seeds; rig does the becoming**
|
||||||
([#81](https://github.com/heavy-duty/box/issues/81)). A template is a
|
([#81](https://github.com/heavy-duty/box/issues/81)). A template is a
|
||||||
|
|
@ -255,8 +256,11 @@ pin tokens below). The seed is deliberately small — the tenant user, tmux,
|
||||||
and [rig](https://github.com/heavy-duty/rig) preinstalled, nothing that
|
and [rig](https://github.com/heavy-duty/rig) preinstalled, nothing that
|
||||||
joins a tailnet or admits credentials — and after cloud-init settles, box
|
joins a tailnet or admits credentials — and after cloud-init settles, box
|
||||||
auto-runs the template's **creds-free** tenant role inside the guest
|
auto-runs the template's **creds-free** tenant role inside the guest
|
||||||
(`rig bootstrap claude` / `codex` / `grok` / `staging`,
|
(`rig bootstrap claude-box` / `codex-box` / `grok-box` / `staging-box`,
|
||||||
[rig#31](https://github.com/heavy-duty/rig/issues/31)). The agent CLI,
|
[rig#31](https://github.com/heavy-duty/rig/issues/31); the roles carry a
|
||||||
|
family suffix — `-box` for box tenants, `-server` for fleet machines — and a
|
||||||
|
template is named for the role it converges,
|
||||||
|
[rig#76](https://github.com/heavy-duty/rig/issues/76)). The agent CLI,
|
||||||
docker, the server posture and the agent-context file all come from that
|
docker, the server posture and the agent-context file all come from that
|
||||||
role — convergent and idempotent, so the same command re-run later converges
|
role — convergent and idempotent, so the same command re-run later converges
|
||||||
an *existing* box to a newer spec (`box shell <box>` →
|
an *existing* box to a newer spec (`box shell <box>` →
|
||||||
|
|
@ -265,8 +269,8 @@ an *existing* box to a newer spec (`box shell <box>` →
|
||||||
`box setup-host`, `box teardown-host` or the drill *inside* a box — once,
|
`box setup-host`, `box teardown-host` or the drill *inside* a box — once,
|
||||||
from rig's roles, instead of copy-pasted per template.
|
from rig's roles, instead of copy-pasted per template.
|
||||||
|
|
||||||
**Anything that joins or admits stays operator-run.** The `staging` box's
|
**Anything that joins or admits stays operator-run.** The `staging-box`
|
||||||
tailnet workload join holds a pre-auth key, so box only prints it as the
|
tenant's tailnet workload join holds a pre-auth key, so box only prints it as the
|
||||||
next step — `box shell <name>`, then `sudo rig bootstrap workload` — and
|
next step — `box shell <name>`, then `sudo rig bootstrap workload` — and
|
||||||
never sees the key ([#69](https://github.com/heavy-duty/box/issues/69)'s
|
never sees the key ([#69](https://github.com/heavy-duty/box/issues/69)'s
|
||||||
split, kept).
|
split, kept).
|
||||||
|
|
@ -279,9 +283,9 @@ carries `@RIG_REPO@`/`@RIG_REF@` tokens that box resolves at mint from the
|
||||||
environment:
|
environment:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
box new --name work --template claude # heavy-duty/rig @ main
|
box new --name work --template claude-box # heavy-duty/rig @ main
|
||||||
RIG_REPO=you/rig RIG_REF=my-branch \
|
RIG_REPO=you/rig RIG_REF=my-branch \
|
||||||
box new --name trial --template claude # a rig branch under review
|
box new --name trial --template claude-box # a rig branch under review
|
||||||
```
|
```
|
||||||
|
|
||||||
Both directions of that edge track `main` unpinned today — said honestly,
|
Both directions of that edge track `main` unpinned today — said honestly,
|
||||||
|
|
|
||||||
33
bin/box
33
bin/box
|
|
@ -185,7 +185,7 @@ OPTIONS
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
# mint a claude box and log in inside it — the tool never handles your token
|
# mint a claude box and log in inside it — the tool never handles your token
|
||||||
box new --name work --template claude
|
box new --name work --template claude-box
|
||||||
box shell work # then: run 'claude', then /login
|
box shell work # then: run 'claude', then /login
|
||||||
|
|
||||||
# log in once, reuse forever: checkpoint the authed box, clone from it
|
# log in once, reuse forever: checkpoint the authed box, clone from it
|
||||||
|
|
@ -242,13 +242,13 @@ help_cmd() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
new) cat <<'EOF'
|
new) cat <<'EOF'
|
||||||
Mint a box. Without --from, launches a fresh box from a template (default:
|
Mint a box. Without --from, launches a fresh box from a template (default:
|
||||||
blank — bare Debian 13, nobody home; --template claude gets Claude Code
|
blank — bare Debian 13, nobody home; --template claude-box gets Claude Code
|
||||||
installed, creds-free, ~10 min cold). With --from, clones an existing box or
|
installed, creds-free, ~10 min cold). With --from, clones an existing box or
|
||||||
one of its snapshots — login state, git creds and clones carry over,
|
one of its snapshots — login state, git creds and clones carry over,
|
||||||
isolation is preserved, and the clone knows its template's user without
|
isolation is preserved, and the clone knows its template's user without
|
||||||
being told.
|
being told.
|
||||||
|
|
||||||
A tenant template (claude, codex, grok, staging) is a THIN seed — the user,
|
A tenant template (claude-box, codex-box, grok-box, staging-box) is a THIN seed — the user,
|
||||||
tmux, rig (#81) — and after cloud-init box auto-runs the creds-free tenant
|
tmux, rig (#81) — and after cloud-init box auto-runs the creds-free tenant
|
||||||
role inside it ('rig bootstrap <role>', rig#31): that role installs the
|
role inside it ('rig bootstrap <role>', rig#31): that role installs the
|
||||||
agent CLI / server posture and the agent-context file. rig is preinstalled
|
agent CLI / server posture and the agent-context file. rig is preinstalled
|
||||||
|
|
@ -286,8 +286,8 @@ BOX_LAUNCH_TIMEOUT=<seconds> (default 600) bounds the 'incus launch' call —
|
||||||
a launch that overruns it fails loudly instead of hanging forever (#93).
|
a launch that overruns it fails loudly instead of hanging forever (#93).
|
||||||
|
|
||||||
box new --name scratch # blank, the default
|
box new --name scratch # blank, the default
|
||||||
box new --name work --template claude
|
box new --name work --template claude-box
|
||||||
box new --name lean --template claude --cpu 2 --memory 3GiB
|
box new --name lean --template claude-box --cpu 2 --memory 3GiB
|
||||||
box new --name feature --from work/authed
|
box new --name feature --from work/authed
|
||||||
EOF
|
EOF
|
||||||
;;
|
;;
|
||||||
|
|
@ -473,7 +473,7 @@ The in-box server must listen on 0.0.0.0:<port>, not only its own loopback —
|
||||||
a VM's forwarder connects to the box over the network. Inside an isolated box
|
a VM's forwarder connects to the box over the network. Inside an isolated box
|
||||||
that is safe: nothing but this proxy can reach the port.
|
that is safe: nothing but this proxy can reach the port.
|
||||||
|
|
||||||
box new --name web --template claude
|
box new --name web --template claude-box
|
||||||
box shell web # inside: run a dev server on 0.0.0.0:3000
|
box shell web # inside: run a dev server on 0.0.0.0:3000
|
||||||
box expose web 3000 # then open http://127.0.0.1:3000 in your browser
|
box expose web 3000 # then open http://127.0.0.1:3000 in your browser
|
||||||
EOF
|
EOF
|
||||||
|
|
@ -1183,14 +1183,23 @@ cmd_new() {
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
# The login hint belongs to the claude template — read the EFFECTIVE
|
# The login hint belongs to the claude-box template — read the EFFECTIVE
|
||||||
# template off the instance, so a clone of a claude box gets it too and a
|
# template off the instance, so a clone of a claude-box box gets it too and
|
||||||
# blank box is not told to run a binary it doesn't have.
|
# a blank box is not told to run a binary it doesn't have.
|
||||||
|
#
|
||||||
|
# Both spellings match, and that is not an alias for the ROLE. The role
|
||||||
|
# names are a hard cut (rig#76) — 'rig bootstrap claude' is gone, so the
|
||||||
|
# seeds ask for 'claude-box' and nothing here softens that. What these arms
|
||||||
|
# read is user.box.template, a stamp left on an INSTANCE at its own mint
|
||||||
|
# time: every box minted before the rename carries the bare name forever,
|
||||||
|
# and a clone carries it forward. Refusing the old spelling here would not
|
||||||
|
# cut anything over, it would only drop the hint on boxes that predate the
|
||||||
|
# rename — the same reason user.claudebox is honored everywhere else.
|
||||||
local eff; eff="$(incus config get "$instance" user.box.template 2>/dev/null || true)"
|
local eff; eff="$(incus config get "$instance" user.box.template 2>/dev/null || true)"
|
||||||
[ -z "$eff" ] && [ "$(incus config get "$instance" user.claudebox 2>/dev/null || true)" = 1 ] && eff=claude
|
[ -z "$eff" ] && [ "$(incus config get "$instance" user.claudebox 2>/dev/null || true)" = 1 ] && eff=claude-box
|
||||||
if [ "$eff" = claude ]; then
|
if [ "$eff" = claude-box ] || [ "$eff" = claude ]; then
|
||||||
echo "box: ready — 'box shell $name'. Log into Claude inside: run 'claude' then /login."
|
echo "box: ready — 'box shell $name'. Log into Claude inside: run 'claude' then /login."
|
||||||
elif [ "$eff" = staging ]; then
|
elif [ "$eff" = staging-box ] || [ "$eff" = staging ]; then
|
||||||
echo "box: ready — 'box shell $name'. The tailnet join stays operator-run (it holds a key box must never see):"
|
echo "box: ready — 'box shell $name'. The tailnet join stays operator-run (it holds a key box must never see):"
|
||||||
echo " box shell $name # then: sudo rig bootstrap workload --hostname $name"
|
echo " box shell $name # then: sudo rig bootstrap workload --hostname $name"
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
# box design
|
# box design
|
||||||
|
|
||||||
`box` is a CLI that mints and manages **trust-less, network-isolated VMs
|
`box` is a CLI that mints and manages **trust-less, network-isolated VMs
|
||||||
with a coding agent installed** (`claude`, `codex`, `grok`, or `blank` for
|
with a coding agent installed** (`claude-box`, `codex-box`, `grok-box`, or
|
||||||
none). It is infrastructure, not a project provisioner.
|
`blank` for none). It is infrastructure, not a project provisioner.
|
||||||
|
|
||||||
See issue #3 for the full reframe and rationale. This doc captures the durable
|
See issue #3 for the full reframe and rationale. This doc captures the durable
|
||||||
design decisions.
|
design decisions.
|
||||||
|
|
@ -60,15 +60,17 @@ instead of pretending to sanitize it.
|
||||||
A template is a **thin, creds-free seed** — base image, the tenant user,
|
A template is a **thin, creds-free seed** — base image, the tenant user,
|
||||||
tmux, and [rig](https://github.com/heavy-duty/rig) preinstalled — and what
|
tmux, and [rig](https://github.com/heavy-duty/rig) preinstalled — and what
|
||||||
the box *becomes* lives in rig's bootstrap roles (rig#31): box auto-runs the
|
the box *becomes* lives in rig's bootstrap roles (rig#31): box auto-runs the
|
||||||
template's creds-free tenant role after cloud-init (`rig bootstrap claude` /
|
template's creds-free tenant role after cloud-init (`rig bootstrap claude-box`
|
||||||
`codex` / `grok` / `staging`), which installs the agent CLI or server
|
/ `codex-box` / `grok-box` / `staging-box` — the roles carry a family suffix,
|
||||||
posture. The split is deliberate: cloud-init is a first-boot one-shot —
|
`-box` for box tenants and `-server` for fleet machines, and the templates are
|
||||||
|
named for the roles they converge, rig#76), which installs the agent CLI or
|
||||||
|
server posture. The split is deliberate: cloud-init is a first-boot one-shot —
|
||||||
not convergent, not re-runnable, only parse-and-grep testable — while a rig
|
not convergent, not re-runnable, only parse-and-grep testable — while a rig
|
||||||
role is an idempotent script with effective-state asserts that can also
|
role is an idempotent script with effective-state asserts that can also
|
||||||
converge an *existing* box to a newer spec. Anything that joins a tailnet or
|
converge an *existing* box to a newer spec. Anything that joins a tailnet or
|
||||||
holds a key (staging's workload join) stays operator-run through
|
holds a key (the staging-box tenant's workload join) stays operator-run
|
||||||
`box shell`; box prints it as a next step and never sees the key. The seed's
|
through `box shell`; box prints it as a next step and never sees the key. The
|
||||||
rig install is pinned by `RIG_REPO`/`RIG_REF` at mint (default
|
seed's rig install is pinned by `RIG_REPO`/`RIG_REF` at mint (default
|
||||||
`heavy-duty/rig@main`, unpinned — the honest edge until rig#32's releases),
|
`heavy-duty/rig@main`, unpinned — the honest edge until rig#32's releases),
|
||||||
and box's template suite holds the line with fail-closed absence greps: no
|
and box's template suite holds the line with fail-closed absence greps: no
|
||||||
agent CLI, no docker, no tailscale, no context-file heredocs in any
|
agent CLI, no docker, no tailscale, no context-file heredocs in any
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
`box` mints trust-less, creds-free, isolated VMs with a coding agent already
|
`box` mints trust-less, creds-free, isolated VMs with a coding agent already
|
||||||
installed (`box new/shell/snapshot/restore/exec/down/start/rm/status`) — the
|
installed (`box new/shell/snapshot/restore/exec/down/start/rm/status`) — the
|
||||||
`claude`, `codex`, and `grok` templates each ship a CLI agent. The tool knows
|
`claude-box`, `codex-box`, and `grok-box` templates each ship a CLI agent. The
|
||||||
**nothing** about your project. There is no `install` step and no host-run
|
tool knows **nothing** about your project. There is no `install` step and no
|
||||||
setup script.
|
host-run setup script.
|
||||||
|
|
||||||
A project makes itself easy to stand up inside a box by shipping an optional
|
A project makes itself easy to stand up inside a box by shipping an optional
|
||||||
`.box/` folder. This folder is **agent-facing documentation** — read and
|
`.box/` folder. This folder is **agent-facing documentation** — read and
|
||||||
|
|
|
||||||
|
|
@ -378,7 +378,7 @@ if ! timeout -k 10 300 ~/.local/share/box/current/host/setup-host.sh; then
|
||||||
fi
|
fi
|
||||||
inf "host setup complete"
|
inf "host setup complete"
|
||||||
|
|
||||||
# A real server has room for the claude template's resources (8GiB/4cpu), and
|
# A real server has room for the claude-box template's resources (8GiB/4cpu), and
|
||||||
# drilling the real numbers is worth more than drilling shrunken ones. Only
|
# drilling the real numbers is worth more than drilling shrunken ones. Only
|
||||||
# shrink if we must. Since 0.4.0 resources are per-box, stamped from the
|
# shrink if we must. Since 0.4.0 resources are per-box, stamped from the
|
||||||
# template at mint — a profile edit no longer reaches them; the supported
|
# template at mint — a profile edit no longer reaches them; the supported
|
||||||
|
|
@ -386,9 +386,9 @@ inf "host setup complete"
|
||||||
ram="$(awk '/MemTotal/{print int($2/1024/1024)}' /proc/meminfo)"
|
ram="$(awk '/MemTotal/{print int($2/1024/1024)}' /proc/meminfo)"
|
||||||
if [ "$ram" -lt 20 ]; then
|
if [ "$ram" -lt 20 ]; then
|
||||||
export BOX_MEMORY=3GiB BOX_CPU=2
|
export BOX_MEMORY=3GiB BOX_CPU=2
|
||||||
note "host has ${ram}GiB RAM — minting at 3GiB/2cpu via BOX_MEMORY/BOX_CPU (the claude template's 8GiB/4cpu is what was NOT drilled)"
|
note "host has ${ram}GiB RAM — minting at 3GiB/2cpu via BOX_MEMORY/BOX_CPU (the claude-box template's 8GiB/4cpu is what was NOT drilled)"
|
||||||
else
|
else
|
||||||
inf "host has ${ram}GiB RAM — drilling the claude template's resources (8GiB/4cpu) unchanged"
|
inf "host has ${ram}GiB RAM — drilling the claude-box template's resources (8GiB/4cpu) unchanged"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
KVM=0; [ -e /dev/kvm ] && KVM=1
|
KVM=0; [ -e /dev/kvm ] && KVM=1
|
||||||
|
|
@ -492,10 +492,10 @@ fi
|
||||||
|
|
||||||
# --- templates: the mint surface is itself a surface to test ----------------
|
# --- templates: the mint surface is itself a surface to test ----------------
|
||||||
tpl_missing=""
|
tpl_missing=""
|
||||||
for t in blank claude codex grok; do
|
for t in blank claude-box codex-box grok-box; do
|
||||||
box templates 2>/dev/null | grep -q "^ $t" || tpl_missing="$tpl_missing $t"
|
box templates 2>/dev/null | grep -q "^ $t" || tpl_missing="$tpl_missing $t"
|
||||||
done
|
done
|
||||||
[ -z "$tpl_missing" ] && ok "templates: lists blank, claude, codex, grok" \
|
[ -z "$tpl_missing" ] && ok "templates: lists blank, claude-box, codex-box, grok-box" \
|
||||||
|| no "templates listing is missing:$tpl_missing"
|
|| no "templates listing is missing:$tpl_missing"
|
||||||
box new --name tpl --template nosuch 2>&1 | grep -q 'no such template' \
|
box new --name tpl --template nosuch 2>&1 | grep -q 'no such template' \
|
||||||
&& ok "unknown template refused, points at 'box templates'" || no "an unknown template was not refused"
|
&& ok "unknown template refused, points at 'box templates'" || no "an unknown template was not refused"
|
||||||
|
|
@ -551,19 +551,22 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# The generic mechanic (metadata, placement, user, isolation parity) is proven
|
# The generic mechanic (metadata, placement, user, isolation parity) is proven
|
||||||
# once by blank+claude and needs no per-template repeat. What a NEW template
|
# once by blank+claude-box and needs no per-template repeat. What a NEW template
|
||||||
# still has to prove is its own payload: the CLI installs, lands on the
|
# still has to prove is its own payload: the CLI installs, lands on the
|
||||||
# non-interactive exec PATH, and answers --version. One mint each.
|
# non-interactive exec PATH, and answers --version. One mint each.
|
||||||
|
# The box NAME stays the bare agent name — it is what the pre-flight banner
|
||||||
|
# announces and what teardown deletes — while the TEMPLATE carries rig#76's
|
||||||
|
# family suffix. They are two different namespaces and only one of them moved.
|
||||||
for t in codex grok; do
|
for t in codex grok; do
|
||||||
case "$t" in codex) bin=codex; user=codex ;; grok) bin=grok; user=grok ;; esac
|
case "$t" in codex) bin=codex; user=codex ;; grok) bin=grok; user=grok ;; esac
|
||||||
printf '\n minting a %s box (cold — validates the template install)…\n' "$t"
|
printf '\n minting a %s box (cold — validates the template install)…\n' "$t"
|
||||||
if mint_box "/tmp/mint-$t.log" --name "$t" --template "$t"; then
|
if mint_box "/tmp/mint-$t.log" --name "$t" --template "$t-box"; then
|
||||||
[ "$(incus config get "$t" user.box.user 2>/dev/null)" = "$user" ] \
|
[ "$(incus config get "$t" user.box.user 2>/dev/null)" = "$user" ] \
|
||||||
&& ok "$t: template user stamped ($user)" || no "$t: user.box.user not $user"
|
&& ok "$t: template user stamped ($user)" || no "$t: user.box.user not $user"
|
||||||
if timeout -k 5 30 box exec "$t" -- "$bin" --version </dev/null >/dev/null 2>&1; then
|
if timeout -k 5 30 box exec "$t" -- "$bin" --version </dev/null >/dev/null 2>&1; then
|
||||||
ok "$t: '$bin --version' answers via box exec — installed and on the non-interactive PATH"
|
ok "$t: '$bin --version' answers via box exec — installed and on the non-interactive PATH"
|
||||||
else
|
else
|
||||||
no "$t: '$bin --version' FAILED via exec — not installed, or not on exec's PATH (the claude template's #15 bug)"
|
no "$t: '$bin --version' FAILED via exec — not installed, or not on exec's PATH (the claude-box template's #15 bug)"
|
||||||
inf "PATH as exec sees it: $(timeout -k 5 20 box exec "$t" -- printenv PATH </dev/null 2>/dev/null)"
|
inf "PATH as exec sees it: $(timeout -k 5 20 box exec "$t" -- printenv PATH </dev/null 2>/dev/null)"
|
||||||
# Do not throw the evidence away — say WHAT the installer actually left.
|
# Do not throw the evidence away — say WHAT the installer actually left.
|
||||||
# Do NOT throw the evidence away — say what the installer actually left
|
# Do NOT throw the evidence away — say what the installer actually left
|
||||||
|
|
@ -583,10 +586,10 @@ for t in codex grok; do
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
printf '\n minting a claude box (cold, ~10 min)…\n'
|
printf '\n minting a claude-box box (cold, ~10 min)…\n'
|
||||||
t0=$SECONDS
|
t0=$SECONDS
|
||||||
if mint_box /tmp/mint-drill.log --name drill --template claude; then
|
if mint_box /tmp/mint-drill.log --name drill --template claude-box; then
|
||||||
ok "box new --name drill --template claude ($((SECONDS - t0))s)"
|
ok "box new --name drill --template claude-box ($((SECONDS - t0))s)"
|
||||||
else
|
else
|
||||||
no "box new FAILED — tail: $(tail -3 /tmp/mint-drill.log | tr '\n' ' ')"
|
no "box new FAILED — tail: $(tail -3 /tmp/mint-drill.log | tr '\n' ' ')"
|
||||||
timeout -k 5 60 incus delete -f drill >/dev/null 2>&1
|
timeout -k 5 60 incus delete -f drill >/dev/null 2>&1
|
||||||
|
|
@ -799,7 +802,7 @@ fi
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
phase "E. box expose — a deliberate loopback door (#55)"
|
phase "E. box expose — a deliberate loopback door (#55)"
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
# archive is a running claude box (node is installed). Start a DETACHED
|
# archive is a running claude-box box (node is installed). Start a DETACHED
|
||||||
# listener on 0.0.0.0 inside it, expose the port, and prove the door works
|
# listener on 0.0.0.0 inside it, expose the port, and prove the door works
|
||||||
# from the HOST's loopback. Then prove removing it closes the door, and that a
|
# from the HOST's loopback. Then prove removing it closes the door, and that a
|
||||||
# NON-exposed port still obeys the ingress drop — the feature must not
|
# NON-exposed port still obeys the ingress drop — the feature must not
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,11 @@ legacy_boxes() {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Re-home one box. Legacy boxes are all claude boxes (the only template the old
|
# Re-home one box. Legacy boxes are all claude boxes (the only template the old
|
||||||
# tool minted), so the new metadata is the claude template's.
|
# tool minted), so the new metadata is the claude-box template's. The stamp
|
||||||
|
# names the template as it is called TODAY, not as it was called when the box
|
||||||
|
# was minted: it is what 'box shell' and the mint hints read, so a re-homed
|
||||||
|
# box should look like a fresh claude-box mint, not like a fossil (rig#76's
|
||||||
|
# family suffix — the template is named for the role it converges).
|
||||||
rehome_one() {
|
rehome_one() {
|
||||||
local b="$1" st
|
local b="$1" st
|
||||||
incus config get "$b" user.claudebox >/dev/null 2>&1 || { warn "$b is not a legacy box (no user.claudebox tag) — skipping"; return 1; }
|
incus config get "$b" user.claudebox >/dev/null 2>&1 || { warn "$b is not a legacy box (no user.claudebox tag) — skipping"; return 1; }
|
||||||
|
|
@ -75,7 +79,7 @@ rehome_one() {
|
||||||
|
|
||||||
# 1. TAG FIRST — additive and reversible. A box that stops here is still a
|
# 1. TAG FIRST — additive and reversible. A box that stops here is still a
|
||||||
# valid legacy box (the old tag is untouched) AND now a new one.
|
# valid legacy box (the old tag is untouched) AND now a new one.
|
||||||
incus config set "$b" user.box=1 user.box.template=claude user.box.user=claude \
|
incus config set "$b" user.box=1 user.box.template=claude-box user.box.user=claude \
|
||||||
|| { warn "$b: could not set new metadata — left untouched"; return 1; }
|
|| { warn "$b: could not set new metadata — left untouched"; return 1; }
|
||||||
|
|
||||||
# 2. Stop, reassign the profile (this is the network move), restart. Incus
|
# 2. Stop, reassign the profile (this is the network move), restart. Incus
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
# The claude template — a thin, creds-free seed (#81): Debian 13, the
|
# The claude-box template — a thin, creds-free seed (#81): Debian 13, the
|
||||||
# 'claude' user, tmux and rig. What the box BECOMES — the Claude Code CLI,
|
# 'claude' user, tmux and rig. What the box BECOMES — the Claude Code CLI,
|
||||||
# docker, node, the agent-context file with its #80 guard — is rig's job:
|
# docker, node, the agent-context file with its #80 guard — is rig's job:
|
||||||
# box auto-runs 'rig bootstrap claude' after mint (heavy-duty/rig#31).
|
# box auto-runs 'rig bootstrap claude-box' after mint (heavy-duty/rig#31).
|
||||||
|
# The template is named for the role it converges, suffix and all
|
||||||
|
# (heavy-duty/rig#76): rig's roles carry a family suffix — '-server' for
|
||||||
|
# fleet machines, '-box' for box tenants — and a seed that named the bare
|
||||||
|
# 'claude' would ask a post-rename rig for a role that no longer exists.
|
||||||
# KEY="value" only. Parsed against an allowlist, never sourced; there is no
|
# KEY="value" only. Parsed against an allowlist, never sourced; there is no
|
||||||
# key for a network or a security flag, on purpose — the shared box-net
|
# key for a network or a security flag, on purpose — the shared box-net
|
||||||
# profile is the placement contract and no template can weaken it.
|
# profile is the placement contract and no template can weaken it.
|
||||||
|
|
@ -14,4 +18,4 @@ BOX_USER="claude"
|
||||||
BOX_CPU="4"
|
BOX_CPU="4"
|
||||||
BOX_MEMORY="8GiB"
|
BOX_MEMORY="8GiB"
|
||||||
BOX_DISK="60GiB"
|
BOX_DISK="60GiB"
|
||||||
BOX_BOOTSTRAP_ROLE="claude"
|
BOX_BOOTSTRAP_ROLE="claude-box"
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
# A thin, creds-free seed (#81): the tenant user, tmux (#65), and rig —
|
# A thin, creds-free seed (#81): the tenant user, tmux (#65), and rig —
|
||||||
# nothing that joins a tailnet or admits credentials, no agent CLI, no
|
# nothing that joins a tailnet or admits credentials, no agent CLI, no
|
||||||
# docker, no context-file heredoc. Everything this box becomes comes from
|
# docker, no context-file heredoc. Everything this box becomes comes from
|
||||||
# 'rig bootstrap claude' (heavy-duty/rig#31), which box auto-runs after
|
# 'rig bootstrap claude-box' (heavy-duty/rig#31), which box auto-runs after
|
||||||
# mint; the agent-context file — including the #80 guard (never run
|
# mint; the agent-context file — including the #80 guard (never run
|
||||||
# 'box setup-host' or the drill inside a box) — is rendered by that role,
|
# 'box setup-host' or the drill inside a box) — is rendered by that role,
|
||||||
# once, instead of being copy-pasted per template.
|
# once, instead of being copy-pasted per template.
|
||||||
|
|
@ -21,7 +21,7 @@ packages:
|
||||||
- ca-certificates
|
- ca-certificates
|
||||||
runcmd:
|
runcmd:
|
||||||
# Preinstall rig so the box can converge — and re-converge — via
|
# Preinstall rig so the box can converge — and re-converge — via
|
||||||
# 'rig bootstrap claude'. @RIG_REPO@/@RIG_REF@ are the pin point (#81):
|
# 'rig bootstrap claude-box'. @RIG_REPO@/@RIG_REF@ are the pin point (#81):
|
||||||
# box substitutes them at mint from the RIG_REPO/RIG_REF environment
|
# box substitutes them at mint from the RIG_REPO/RIG_REF environment
|
||||||
# (default heavy-duty/rig @ main — unpinned, tracking main, the same
|
# (default heavy-duty/rig @ main — unpinned, tracking main, the same
|
||||||
# honest edge as rig's own unpinned box install, until rig#32 ships a
|
# honest edge as rig's own unpinned box install, until rig#32 ships a
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
# The codex template — a thin, creds-free seed (#81): Debian 13, the
|
# The codex-box template — a thin, creds-free seed (#81): Debian 13, the
|
||||||
# 'codex' user, tmux and rig. What the box BECOMES — the OpenAI Codex CLI,
|
# 'codex' user, tmux and rig. What the box BECOMES — the OpenAI Codex CLI,
|
||||||
# docker, node, the agent-context file with its #80 guard — is rig's job:
|
# docker, node, the agent-context file with its #80 guard — is rig's job:
|
||||||
# box auto-runs 'rig bootstrap codex' after mint (heavy-duty/rig#31).
|
# box auto-runs 'rig bootstrap codex-box' after mint (heavy-duty/rig#31).
|
||||||
|
# The template is named for the role it converges, suffix and all
|
||||||
|
# (heavy-duty/rig#76): rig's roles carry a family suffix — '-server' for
|
||||||
|
# fleet machines, '-box' for box tenants — and a seed that named the bare
|
||||||
|
# 'codex' would ask a post-rename rig for a role that no longer exists.
|
||||||
# KEY="value" only. Parsed against an allowlist, never sourced; there is no
|
# KEY="value" only. Parsed against an allowlist, never sourced; there is no
|
||||||
# key for a network or a security flag, on purpose — the shared box-net
|
# key for a network or a security flag, on purpose — the shared box-net
|
||||||
# profile is the placement contract and no template can weaken it.
|
# profile is the placement contract and no template can weaken it.
|
||||||
|
|
@ -14,4 +18,4 @@ BOX_USER="codex"
|
||||||
BOX_CPU="4"
|
BOX_CPU="4"
|
||||||
BOX_MEMORY="8GiB"
|
BOX_MEMORY="8GiB"
|
||||||
BOX_DISK="60GiB"
|
BOX_DISK="60GiB"
|
||||||
BOX_BOOTSTRAP_ROLE="codex"
|
BOX_BOOTSTRAP_ROLE="codex-box"
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
# A thin, creds-free seed (#81): the tenant user, tmux (#65), and rig —
|
# A thin, creds-free seed (#81): the tenant user, tmux (#65), and rig —
|
||||||
# nothing that joins a tailnet or admits credentials, no agent CLI, no
|
# nothing that joins a tailnet or admits credentials, no agent CLI, no
|
||||||
# docker, no context-file heredoc. Everything this box becomes comes from
|
# docker, no context-file heredoc. Everything this box becomes comes from
|
||||||
# 'rig bootstrap codex' (heavy-duty/rig#31), which box auto-runs after
|
# 'rig bootstrap codex-box' (heavy-duty/rig#31), which box auto-runs after
|
||||||
# mint; the agent-context file — including the #80 guard (never run
|
# mint; the agent-context file — including the #80 guard (never run
|
||||||
# 'box setup-host' or the drill inside a box) — is rendered by that role,
|
# 'box setup-host' or the drill inside a box) — is rendered by that role,
|
||||||
# once, instead of being copy-pasted per template.
|
# once, instead of being copy-pasted per template.
|
||||||
|
|
@ -21,7 +21,7 @@ packages:
|
||||||
- ca-certificates
|
- ca-certificates
|
||||||
runcmd:
|
runcmd:
|
||||||
# Preinstall rig so the box can converge — and re-converge — via
|
# Preinstall rig so the box can converge — and re-converge — via
|
||||||
# 'rig bootstrap codex'. @RIG_REPO@/@RIG_REF@ are the pin point (#81):
|
# 'rig bootstrap codex-box'. @RIG_REPO@/@RIG_REF@ are the pin point (#81):
|
||||||
# box substitutes them at mint from the RIG_REPO/RIG_REF environment
|
# box substitutes them at mint from the RIG_REPO/RIG_REF environment
|
||||||
# (default heavy-duty/rig @ main — unpinned, tracking main, the same
|
# (default heavy-duty/rig @ main — unpinned, tracking main, the same
|
||||||
# honest edge as rig's own unpinned box install, until rig#32 ships a
|
# honest edge as rig's own unpinned box install, until rig#32 ships a
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
# The grok template — a thin, creds-free seed (#81): Debian 13, the
|
# The grok-box template — a thin, creds-free seed (#81): Debian 13, the
|
||||||
# 'grok' user, tmux and rig. What the box BECOMES — the xAI Grok CLI,
|
# 'grok' user, tmux and rig. What the box BECOMES — the xAI Grok CLI,
|
||||||
# docker, the agent-context file with its #80 guard — is rig's job:
|
# docker, the agent-context file with its #80 guard — is rig's job:
|
||||||
# box auto-runs 'rig bootstrap grok' after mint (heavy-duty/rig#31).
|
# box auto-runs 'rig bootstrap grok-box' after mint (heavy-duty/rig#31).
|
||||||
|
# The template is named for the role it converges, suffix and all
|
||||||
|
# (heavy-duty/rig#76): rig's roles carry a family suffix — '-server' for
|
||||||
|
# fleet machines, '-box' for box tenants — and a seed that named the bare
|
||||||
|
# 'grok' would ask a post-rename rig for a role that no longer exists.
|
||||||
# KEY="value" only. Parsed against an allowlist, never sourced; there is no
|
# KEY="value" only. Parsed against an allowlist, never sourced; there is no
|
||||||
# key for a network or a security flag, on purpose — the shared box-net
|
# key for a network or a security flag, on purpose — the shared box-net
|
||||||
# profile is the placement contract and no template can weaken it.
|
# profile is the placement contract and no template can weaken it.
|
||||||
|
|
@ -14,4 +18,4 @@ BOX_USER="grok"
|
||||||
BOX_CPU="4"
|
BOX_CPU="4"
|
||||||
BOX_MEMORY="8GiB"
|
BOX_MEMORY="8GiB"
|
||||||
BOX_DISK="60GiB"
|
BOX_DISK="60GiB"
|
||||||
BOX_BOOTSTRAP_ROLE="grok"
|
BOX_BOOTSTRAP_ROLE="grok-box"
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
# A thin, creds-free seed (#81): the tenant user, tmux (#65), and rig —
|
# A thin, creds-free seed (#81): the tenant user, tmux (#65), and rig —
|
||||||
# nothing that joins a tailnet or admits credentials, no agent CLI, no
|
# nothing that joins a tailnet or admits credentials, no agent CLI, no
|
||||||
# docker, no context-file heredoc. Everything this box becomes comes from
|
# docker, no context-file heredoc. Everything this box becomes comes from
|
||||||
# 'rig bootstrap grok' (heavy-duty/rig#31), which box auto-runs after
|
# 'rig bootstrap grok-box' (heavy-duty/rig#31), which box auto-runs after
|
||||||
# mint; the agent-context file — including the #80 guard (never run
|
# mint; the agent-context file — including the #80 guard (never run
|
||||||
# 'box setup-host' or the drill inside a box) — is rendered by that role,
|
# 'box setup-host' or the drill inside a box) — is rendered by that role,
|
||||||
# once, instead of being copy-pasted per template.
|
# once, instead of being copy-pasted per template.
|
||||||
|
|
@ -21,7 +21,7 @@ packages:
|
||||||
- ca-certificates
|
- ca-certificates
|
||||||
runcmd:
|
runcmd:
|
||||||
# Preinstall rig so the box can converge — and re-converge — via
|
# Preinstall rig so the box can converge — and re-converge — via
|
||||||
# 'rig bootstrap grok'. @RIG_REPO@/@RIG_REF@ are the pin point (#81):
|
# 'rig bootstrap grok-box'. @RIG_REPO@/@RIG_REF@ are the pin point (#81):
|
||||||
# box substitutes them at mint from the RIG_REPO/RIG_REF environment
|
# box substitutes them at mint from the RIG_REPO/RIG_REF environment
|
||||||
# (default heavy-duty/rig @ main — unpinned, tracking main, the same
|
# (default heavy-duty/rig @ main — unpinned, tracking main, the same
|
||||||
# honest edge as rig's own unpinned box install, until rig#32 ships a
|
# honest edge as rig's own unpinned box install, until rig#32 ships a
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
# The staging template — a thin, creds-free, server-class seed (#81, the
|
# The staging-box template — a thin, creds-free, server-class seed (#81, the
|
||||||
# re-cut of #69's layering): Debian 13, the 'ops' user, tmux and rig. The
|
# re-cut of #69's layering): Debian 13, the 'ops' user, tmux and rig. The
|
||||||
# server posture — docker, sshd hardening — is rig's job: box auto-runs
|
# server posture — docker, sshd hardening — is rig's job: box auto-runs
|
||||||
# 'rig bootstrap staging' after mint (heavy-duty/rig#31). The tailnet
|
# 'rig bootstrap staging-box' after mint (heavy-duty/rig#31). The template is
|
||||||
|
# named for the role it converges, suffix and all (heavy-duty/rig#76): rig's
|
||||||
|
# roles carry a family suffix — '-server' for fleet machines, '-box' for box
|
||||||
|
# tenants — and a seed that named the bare 'staging' would ask a post-rename
|
||||||
|
# rig for a role that no longer exists. Server-CLASS, not a fleet machine:
|
||||||
|
# this is still a box tenant, so it takes '-box', not '-server'. The tailnet
|
||||||
# workload join holds a key and therefore STAYS operator-run:
|
# workload join holds a key and therefore STAYS operator-run:
|
||||||
# box shell <name> # then: sudo rig bootstrap workload --hostname <name>
|
# box shell <name> # then: sudo rig bootstrap workload --hostname <name>
|
||||||
# KEY="value" only. Parsed against an allowlist, never sourced; there is no
|
# KEY="value" only. Parsed against an allowlist, never sourced; there is no
|
||||||
|
|
@ -21,4 +26,4 @@ BOX_MEMORY="8GiB"
|
||||||
BOX_DISK="60GiB"
|
BOX_DISK="60GiB"
|
||||||
BOX_REQUIRE_VM="1"
|
BOX_REQUIRE_VM="1"
|
||||||
BOX_AUTOSTART="1"
|
BOX_AUTOSTART="1"
|
||||||
BOX_BOOTSTRAP_ROLE="staging"
|
BOX_BOOTSTRAP_ROLE="staging-box"
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
# A thin, creds-free, server-class seed (#81): the 'ops' user, tmux (#65),
|
# A thin, creds-free, server-class seed (#81): the 'ops' user, tmux (#65),
|
||||||
# and rig — nothing that joins a tailnet or admits credentials, no docker,
|
# and rig — nothing that joins a tailnet or admits credentials, no docker,
|
||||||
# no sshd config, no keys. The server posture comes from
|
# no sshd config, no keys. The server posture comes from
|
||||||
# 'rig bootstrap staging' (heavy-duty/rig#31), which box auto-runs after
|
# 'rig bootstrap staging-box' (heavy-duty/rig#31), which box auto-runs after
|
||||||
# mint; the tailnet workload join holds a pre-auth key and stays
|
# mint; the tailnet workload join holds a pre-auth key and stays
|
||||||
# operator-run ('box shell' → 'sudo rig bootstrap workload'), exactly as
|
# operator-run ('box shell' → 'sudo rig bootstrap workload'), exactly as
|
||||||
# #69 designed it — box never sees the key.
|
# #69 designed it — box never sees the key.
|
||||||
|
|
@ -22,7 +22,7 @@ packages:
|
||||||
- ca-certificates
|
- ca-certificates
|
||||||
runcmd:
|
runcmd:
|
||||||
# Preinstall rig so the box can converge — and re-converge — via
|
# Preinstall rig so the box can converge — and re-converge — via
|
||||||
# 'rig bootstrap staging'. @RIG_REPO@/@RIG_REF@ are the pin point (#81):
|
# 'rig bootstrap staging-box'. @RIG_REPO@/@RIG_REF@ are the pin point (#81):
|
||||||
# box substitutes them at mint from the RIG_REPO/RIG_REF environment
|
# box substitutes them at mint from the RIG_REPO/RIG_REF environment
|
||||||
# (default heavy-duty/rig @ main — unpinned, tracking main, the same
|
# (default heavy-duty/rig @ main — unpinned, tracking main, the same
|
||||||
# honest edge as rig's own unpinned box install, until rig#32 ships a
|
# honest edge as rig's own unpinned box install, until rig#32 ships a
|
||||||
26
test/cli.sh
26
test/cli.sh
|
|
@ -310,16 +310,22 @@ done
|
||||||
# is its trust boundary (its guest runs docker, via rig) and a server returns
|
# is its trust boundary (its guest runs docker, via rig) and a server returns
|
||||||
# from a host reboot without an operator. Pinned to the FILE so neither can
|
# from a host reboot without an operator. Pinned to the FILE so neither can
|
||||||
# quietly vanish in a rewrite.
|
# quietly vanish in a rewrite.
|
||||||
check "staging: demands VM mode (BOX_REQUIRE_VM=1)" 0 "" \
|
check "staging-box: demands VM mode (BOX_REQUIRE_VM=1)" 0 "" \
|
||||||
grep -qx 'BOX_REQUIRE_VM="1"' "$ROOT/templates/staging/box.env"
|
grep -qx 'BOX_REQUIRE_VM="1"' "$ROOT/templates/staging-box/box.env"
|
||||||
check "staging: demands autostart (BOX_AUTOSTART=1)" 0 "" \
|
check "staging-box: demands autostart (BOX_AUTOSTART=1)" 0 "" \
|
||||||
grep -qx 'BOX_AUTOSTART="1"' "$ROOT/templates/staging/box.env"
|
grep -qx 'BOX_AUTOSTART="1"' "$ROOT/templates/staging-box/box.env"
|
||||||
check "staging: the tenant role is 'staging'" 0 "ROLE=staging" tpl "$ROOT" staging
|
check "staging-box: the tenant role is 'staging-box'" 0 "ROLE=staging-box" tpl "$ROOT" staging-box
|
||||||
check "staging: the seed user is rig's default for the role ('ops')" 0 "USER=ops" tpl "$ROOT" staging
|
check "staging-box: the seed user is rig's default for the role ('ops')" 0 "USER=ops" tpl "$ROOT" staging-box
|
||||||
# The agent tenants: role = user = template name, rig's default mapping.
|
# The agent tenants. Two names, not one: the TEMPLATE is named for the rig role
|
||||||
for t in claude codex grok; do
|
# it converges — suffix and all, since rig's roles carry a family suffix
|
||||||
check "$t: role and user are '$t' (rig's default tenant mapping)" 0 "USER=$t REQUIRE_VM= AUTOSTART= ROLE=$t" \
|
# ('-box' for box tenants, '-server' for fleet machines, rig#76) — while the
|
||||||
tpl "$ROOT" "$t"
|
# seed USER stays the bare agent name, because that is the user rig's role
|
||||||
|
# converges and the one 'box shell' lands in. The pairing is the whole point of
|
||||||
|
# pinning it here: a rename that moves one and forgets the other mints a box
|
||||||
|
# whose role dies looking for a user that was never created.
|
||||||
|
for u in claude codex grok; do
|
||||||
|
check "$u-box: role is '$u-box', seed user is '$u' (rig's tenant mapping)" \
|
||||||
|
0 "USER=$u REQUIRE_VM= AUTOSTART= ROLE=$u-box" tpl "$ROOT" "$u-box"
|
||||||
done
|
done
|
||||||
# blank stays a box with NOBODY home: no rig, no role — same isolation, no
|
# blank stays a box with NOBODY home: no rig, no role — same isolation, no
|
||||||
# tooling, and nothing auto-runs in it.
|
# tooling, and nothing auto-runs in it.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue