From 1d6ce0e51af45f64bf90bad0aedd4e660b5972cc Mon Sep 17 00:00:00 2001 From: claude-hdb <278054522+claude-hdb@users.noreply.github.com> Date: Fri, 17 Jul 2026 15:52:59 +0000 Subject: [PATCH] =?UTF-8?q?feat(templates):=20staging=20=E2=80=94=20server?= =?UTF-8?q?-class=20VM,=20docker=20+=20rig,=20creds-free?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Debian 13 cloud image, user 'ops', build-sized resources (the control plane builds on the target), BOX_REQUIRE_VM + BOX_AUTOSTART. cloud-init installs docker, rig and tmux and stops: tailscale, openssh-server and every credential are deliberately absent — rig installs and hardens those at bootstrap time ('box shell' → 'sudo rig bootstrap workload'), and box never sees the auth key. No agent, no agent-context file: a server, not an agent devbox. tmux rides along because 'box tmux' is a contract every template honors (#65), staging included. Co-Authored-By: Claude Opus 4.8 Co-Authored-By: Claude Fable 5 --- templates/staging/box.env | 18 ++++++++++++++++++ templates/staging/user-data.yaml | 31 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 templates/staging/box.env create mode 100644 templates/staging/user-data.yaml diff --git a/templates/staging/box.env b/templates/staging/box.env new file mode 100644 index 0000000..fb97219 --- /dev/null +++ b/templates/staging/box.env @@ -0,0 +1,18 @@ +# The staging template — a server-class box: docker + rig, no agent, no creds. +# 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 +# profile is the placement contract and no template can weaken it. +# BOX_USER must match the user user-data.yaml creates. +# +# BOX_REQUIRE_VM: no container fallback — the VM is the staging trust +# boundary, and the guest runs docker. BOX_AUTOSTART: a staging server must +# come back on its own after a host reboot. Resources are build-sized: the +# control plane builds on the target. +BOX_DESCRIPTION="Server-class staging VM: docker + rig preinstalled; converge with 'rig bootstrap workload' inside, then register in the control plane" +BOX_IMAGE="images:debian/13/cloud" +BOX_USER="ops" +BOX_CPU="4" +BOX_MEMORY="8GiB" +BOX_DISK="100GiB" +BOX_REQUIRE_VM="1" +BOX_AUTOSTART="1" diff --git a/templates/staging/user-data.yaml b/templates/staging/user-data.yaml new file mode 100644 index 0000000..60f37f3 --- /dev/null +++ b/templates/staging/user-data.yaml @@ -0,0 +1,31 @@ +#cloud-config +# The staging template — a server, not an agent devbox: no agent, no +# agent-context file, and (as everywhere in box) no credentials. Docker and +# rig are preinstalled and that is all. Tailscale, openssh-server and every +# credential are deliberately ABSENT: rig installs and hardens sshd and joins +# the tailnet at bootstrap time ('box shell' → 'sudo rig bootstrap workload'), +# holding the auth key in process memory — box never sees it. +# BOX_USER in box.env must match the user created here — the file is passed +# to Incus verbatim. +users: + - name: ops + shell: /bin/bash + sudo: "ALL=(ALL) NOPASSWD:ALL" + lock_passwd: true +package_update: true +packages: + - curl + - ca-certificates + # tmux is the one agent-adjacent tool a server box still carries: 'box tmux' + # runs 'tmux new-session' INSIDE the box on EVERY template (#65) — the + # operator babysits 'rig bootstrap workload' through it — and test/cli.sh + # asserts it for every template directory, this one included. + - tmux +runcmd: + - curl -fsSL https://get.docker.com | sh + - usermod -aG docker ops + # rig runs as root, so install it as root: its installer lands the tree in + # $HOME/.local/share/rig and symlinks /usr/local/bin/rig. HOME is pinned + # because cloud-init's runcmd does not guarantee one, and the installer + # derives its install dir from it. + - HOME=/root bash -c 'curl -fsSL https://raw.githubusercontent.com/heavy-duty/rig/main/install.sh | bash'