feat(seed): route seeded provider keys to provider.env for zero-touch boot
The live seed importer merged the active agent's provider keys into the operator ~/.env, but colibri_daemon reads /usr/local/etc/colibri/provider.env (rc.conf colibri_daemon_provider_env). So a personalized seed carrying real provider keys never reached the daemon and no agent auto-spawned. Route the active agent's non-BW_* keys into provider.env (0600 root) in addition to ~/.env. The importer runs as root BEFORE LOGIN and colibri_daemon REQUIREs LOGIN, so the daemon starts after the keys land and auto-spawns the agent on first boot — no Join Hive click, no Vaultwarden round-trip, no typing. This makes a personalized seed the zero-touch onboarding primitive: the image stays generic/publishable, the FAT32 seed is the (offline) personalization layer. BW_* still route to vault-bootstrap.env for the vault-fetch path. Docs: seed README, START-HERE, and ONBOARDING-SIMPLIFICATION updated to describe the direct-keys path (supersedes the xdg-autostart plan). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
343ba35536
commit
ba2f09f290
4 changed files with 61 additions and 18 deletions
|
|
@ -42,23 +42,35 @@ just double-clicks "Join Hive" and the fetch runs automatically.
|
|||
| Join Hive | `live/operator-session/clawdie-join-hive.sh` | Desktop launcher: checks for creds → prompts or auto-fetches |
|
||||
| Seed README | `live/operator-session/clawdie-live-seed.README.txt` | Operator-facing seed partition instructions |
|
||||
|
||||
## Remaining work: delete the click
|
||||
## Zero-touch: direct keys on the seed (implemented)
|
||||
|
||||
The seed partition path reduces onboarding to ONE double-click. Making it
|
||||
zero-touch requires:
|
||||
The click only existed to trigger the Vaultwarden round-trip. For a
|
||||
personalized stick that already holds the real provider keys, that round-trip
|
||||
is unnecessary — and the boot ordering already favors zero-touch:
|
||||
|
||||
1. **xdg autostart entry** — on first login, if BW\_\* creds are present in
|
||||
provider.env AND `colibri_daemon` is not yet fully provisioned, auto-run
|
||||
`clawdie-vault-fetch --write-env <provider.env>` and restart the daemon.
|
||||
- `clawdie_live_seed` runs as root, `BEFORE: LOGIN`.
|
||||
- `colibri_daemon` runs `REQUIRE: LOGIN` — strictly after.
|
||||
|
||||
2. **First-boot guard** — run once per boot only (not on every login). A
|
||||
sentinel file (`/var/db/clawdie/vault-fetched`) prevents re-triggering.
|
||||
So the importer now merges the active agent's direct provider keys (everything
|
||||
except `BW_*`) into the daemon's `provider.env` as well as the operator's
|
||||
`~/.env`. The daemon starts afterward, finds `DEEPSEEK_API_KEY`, and
|
||||
auto-spawns the agent (`COLIBRI_AUTOSPAWN_PI=YES`) — no click, no vault
|
||||
round-trip, no typing. `BW_*` still route to `~/.config/vault-bootstrap.env`
|
||||
for operators who prefer the vault-fetch path.
|
||||
|
||||
3. **START-HERE.txt update** — remove the "add your 3 BW secrets" section
|
||||
when the seed partition is present. Show a confirmation instead:
|
||||
"Secrets loaded from seed partition. Colibri is starting."
|
||||
This makes the **personalized seed** the onboarding primitive:
|
||||
|
||||
Estimated: ~30 lines of shell.
|
||||
- The image stays generic and publishable; secrets are never baked in.
|
||||
- The seed (FAT32 `CLAWDIESEED`) is the personalization layer and stays
|
||||
physical/offline — `env` (direct keys + optional `TAILSCALE_AUTH_KEY`),
|
||||
`harness.toml`, `soul/`, `ssh/authorized_keys`, optional `/shred` to wipe
|
||||
keys off the stick after first import.
|
||||
- The seed can be generated by an agent (e.g. Hermes) that already holds the
|
||||
soul and key material, written straight onto the mounted partition.
|
||||
|
||||
This supersedes the earlier xdg-autostart "delete the click" plan: it removes
|
||||
the click for free without a first-login sentinel or a network dependency at
|
||||
first boot.
|
||||
|
||||
## Related: one-secret path (future)
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,11 @@ LIVE SEED
|
|||
Seed partition label:
|
||||
CLAWDIESEED
|
||||
|
||||
If this stick was seeded with provider keys, there is nothing to do: the
|
||||
agent's keys were loaded before the daemon started, so Colibri auto-spawns
|
||||
the agent on boot. Check with:
|
||||
colibri status
|
||||
|
||||
Readable operator guide:
|
||||
/usr/local/share/clawdie-iso/seed/README.txt
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,12 @@ SEED_VALID_HARNESSES="pi zot local"
|
|||
# Vaultwarden bootstrap creds are routed out of .env into this file (relative to
|
||||
# the agent home) so clawdie-vault-fetch can consume them.
|
||||
SEED_VAULT_BOOTSTRAP_REL=".config/vault-bootstrap.env"
|
||||
# colibri_daemon reads provider keys from this file (rc.conf
|
||||
# colibri_daemon_provider_env), NOT the operator's ~/.env. The active agent's
|
||||
# direct provider keys are merged here too so the daemon auto-spawns at boot
|
||||
# from a seeded stick with no operator action (zero-touch provisioning). The
|
||||
# importer runs as root before LOGIN, so it can write this root-owned file.
|
||||
SEED_PROVIDER_ENV="${SEED_PROVIDER_ENV:-/usr/local/etc/colibri/provider.env}"
|
||||
|
||||
_seed_log() {
|
||||
printf '%s %s\n' "$(date '+%Y-%m-%dT%H:%M:%S')" "$1" >>"${SEED_LOG}" 2>/dev/null || true
|
||||
|
|
@ -261,6 +267,14 @@ _seed_activate_agent() {
|
|||
if [ -f "${_dir}/env" ]; then
|
||||
_seed_split_env "${_dir}/env" "${_stage}"
|
||||
_seed_merge_env "${_stage}/.app.env" "${_home}/.env" "${_user}"
|
||||
# Feed the daemon too: colibri_daemon reads provider.env, not ~/.env.
|
||||
# Routing the active agent's provider keys here lets a seeded stick boot
|
||||
# straight into an auto-spawned agent — no Join Hive click, no vault
|
||||
# round-trip. Lands root-owned 0600 (the importer is root, pre-LOGIN).
|
||||
if [ -s "${_stage}/.app.env" ]; then
|
||||
_seed_merge_env "${_stage}/.app.env" "${SEED_PROVIDER_ENV}" root
|
||||
_seed_log "merged active-agent provider keys -> ${SEED_PROVIDER_ENV}"
|
||||
fi
|
||||
if [ -s "${_stage}/.boot.env" ]; then
|
||||
_seed_merge_env "${_stage}/.boot.env" "${_home}/${SEED_VAULT_BOOTSTRAP_REL}" "${_user}"
|
||||
_seed_log "routed Vaultwarden bootstrap creds -> ${_home}/${SEED_VAULT_BOOTSTRAP_REL}"
|
||||
|
|
|
|||
|
|
@ -40,14 +40,26 @@ LAYER 2 — PER-AGENT DIRECTORIES
|
|||
Create one directory per agent. THE DIRECTORY NAME IS THE AGENT NAME.
|
||||
Inside it, any of these are honored:
|
||||
|
||||
/<agent>/env Plaintext KEY=VALUE lines. Merged into the
|
||||
agent's .env (mode 0600). Keys you list
|
||||
/<agent>/env Plaintext KEY=VALUE lines. Keys you list
|
||||
replace existing values; keys you omit are
|
||||
preserved. Blank/`#` lines are ignored.
|
||||
Typical contents: provider API keys
|
||||
(ANTHROPIC_API_KEY=..., ZAI_API_KEY=...),
|
||||
or the Vaultwarden bootstrap
|
||||
(BW_CLIENTID/BW_CLIENTSECRET/BW_PASSWORD).
|
||||
Routing for the ACTIVE agent:
|
||||
- Provider API keys and toggles
|
||||
(DEEPSEEK_API_KEY=..., OPENROUTER_API_KEY=...,
|
||||
COLIBRI_AUTOSPAWN_PI=YES, ...) are merged
|
||||
into BOTH the agent's ~/.env AND the daemon's
|
||||
/usr/local/etc/colibri/provider.env (mode
|
||||
0600). Because the importer runs before the
|
||||
daemon starts, a seeded provider key makes
|
||||
colibri_daemon auto-spawn the agent on first
|
||||
boot with NO operator action — fully
|
||||
zero-touch. No Vaultwarden round-trip needed.
|
||||
- Vaultwarden bootstrap creds
|
||||
(BW_CLIENTID/BW_CLIENTSECRET/BW_PASSWORD) are
|
||||
routed to ~/.config/vault-bootstrap.env for
|
||||
clawdie-vault-fetch — use these only if you
|
||||
want the vault-fetch path instead of direct
|
||||
keys.
|
||||
The Vaultwarden endpoint is baked into the
|
||||
image; do not put it on the seed unless you
|
||||
are deliberately overriding it.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue