Saved prompts: W2, OLLAMA-1, BOOT-1, S1, AS0, AS1, JH-1, V0, V1, VS-1. DECISIONS.md 2026-09-27 entry (sudo-bridge retired, Jenkins deploys via agent-sudo deploy_service, Chatterbox-Turbo, vault-sandbox auto-unseal). Voice A1/A2 superseded. Redacted two plaintext secrets in agent-builder context (still in history; rotation tracked under #192). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6.6 KiB
VS-1 BUILD-PREP — give server-01's vault-sandbox the SAME auto-unseal as primary Vault — write files, install NOTHING
Written 2026-09-27 (infrastructure general questions conversation). Owner decision 2026-09-27 (DECISIONS.md, item 9): "sandbox vault should have the same auto unseal functionality primary vault does and if it doesn't then it needs to be copied over." Related: personal_projects #270 (sandbox stack unreachable — boot-order bug, see BOOT-1) and #219 (BOOT-1 marks vault-sandbox CHECK_ONLY because a restart seals it; once this lands, that can change). Needs server-01 reachable. Safe alongside anything that does not restart vault-sandbox.
You are a bounded background BUILD-PREP agent. Budget: --max-turns 25. If you issue the same tool call twice with identical arguments, STOP and output the wrap-up block with status=partially_succeeded.
HARD RULES
- WRITE FILES ONLY + read-only discovery. Do NOT restart/stop/start any container (especially vault-sandbox — a restart seals it), do NOT run
vault operator unseal, do NOT install units, no sudo, no git add/commit/push, no Postgres writes. - NEVER read, print or copy an unseal key or root token — not from files, Bitwarden, Vault or history. You may report that a key source EXISTS (item/path name, field names, count of keys) and nothing more. Do not
catany*unseal*keys*file; usels -la/statonly. - server-01 via
ssh -o BatchMode=yes administrator@192.168.1.90 '<cmd>'.docker inspectonly State/Image/Labels/Mounts/PortBindings/RestartPolicy — NEVER.Config.Env. - If a hook blocks something, stop with a partial wrap-up.
PRIMARY'S MECHANISM (verified 2026-09-27 — this is the pattern to copy)
/usr/local/bin/vault-unseal.sh(root 0755): waits ≤120 s for a running container matching^vault-, and ifdocker exec <c> vault statusshowsSealed true, reads keys line-by-line from a root-only file (/etc/vault-unseal-keys, root:root 0400, 3 keys for a 3-of-5 threshold;#/blank lines skipped) and runsdocker exec <c> vault operator unseal <key>per key (output to /dev/null)./usr/local/bin/vault-watch-unseal.sh(root 0755):docker events --filter 'name=vault-' --filter 'event=start' --format '{{.Actor.Attributes.name}}'→ on each start, sleep 8, run vault-unseal.sh. Handles container restarts/recreates, not just daemon restarts.- Units:
vault-watch-unseal.service(Type=simple, Restart=always, RestartSec=5, After/Requires docker.service, WantedBy multi-user) — ACTIVE;vault-unseal.service(oneshot, After docker) — currently FAILED on primary (note it in the report; do not fix primary). - Known weakness to NOT copy blindly: the key is passed as a positional argument to
vault operator unseal(visible in the host process list for the moment it runs). Improve it for the sandbox copy: feed the key on stdin (printf '%s\n' "$KEY" | docker exec -i <c> vault operator unseal -— verify the-stdin form invault operator unseal -hinside the vault-sandbox container, read-only).
TASKS
- Discover on server-01 (read-only): does any unseal automation already exist there? (
systemctl list-units --all | grep -i unseal,ls -la /usr/local/bin/*unseal* /etc/*unseal* 2>&1, root crontab is not readable — say so). vault-sandbox: container name, image/version, compose working dir (label), seal type (docker exec <c> vault status -format=json→ print ONLYsealed,initialized,t,n,type,versionfields), Vault address it listens on, restart policy. - Find where the sandbox unseal keys live — by NAME only: search memory (
/home/administrator/.claude/projects/-opt-appdata-docker/memory/, especiallysession_summary_n8n_sandbox_deploy.md,playbook_vault_token_rotation.md,project_hashicorp_vault.md,feedback_sandbox_isolation.md) and context files for where the 2026-06-16 sandbox init stored them (a Bitwarden item? a primary-Vault path? a file on server-01?). Report item/path + field names + key count + threshold. If unknown → UNVERIFIED and say the owner must locate them. - Write the adapted files into the primary repo dir
/opt/appdata/docker/vault-sandbox-autounseal/:vault-sandbox-unseal.sh— same logic as primary's, but container match^vault-sandbox-, key file/etc/vault-sandbox-unseal-keys, key fed via stdin, logs to the journal, exits non-zero if still sealed after applying keys.vault-sandbox-watch-unseal.sh— docker events filter that matches ONLY the sandbox container (verify the eventsnamefilter semantics — substring vs exact — from Docker docs, and use a filter + in-loop name check so it can never fire on some other vault).vault-sandbox-watch-unseal.service(same shape as primary's watch unit) and a oneshotvault-sandbox-unseal.servicerun at boot After=docker.service (covers "container already up before the watcher started").README.md: owner steps — (a) create/etc/vault-sandbox-unseal-keysroot:root 0400 from the key source found in task 2 WITHOUT the key touching shell history or the screen (e.g.sudo install -m 0400 /dev/null /etc/vault-sandbox-unseal-keys && sudo nano /etc/vault-sandbox-unseal-keysand paste from the password manager), (b) install scripts + units,daemon-reload,enable --nowthe watcher and the oneshot, (c) TEST:docker restart <vault-sandbox>thenjournalctl -u vault-sandbox-watch-unseal -n 20shows "unsealed" andvault statussealed=false, (d) then tell the main session so BOOT-1's server-01host.envcan drop vault-sandbox from CHECK_ONLY, (e) rollback.
- Validate:
bash -nboth scripts;systemd-analyze verifyon temp copies of the units.
SCOPE ALLOWLIST: /opt/appdata/docker/vault-sandbox-autounseal/ (new, incl. .claude/context.md from /home/administrator/.claude/projects/-opt-appdata-docker/memory/playbook_project_context_template.md). Nothing else.
PERSIST BEFORE YOU FINISH
- Append "## VS-1 prep — (background agent)" to
/opt/appdata/docker/vault-sandbox-autounseal/.claude/context.md. - Run: python3 /opt/appdata/docker/.claude/scripts/embed_memory_dir.py --only-recent 5
- FINAL message = wrap-up JSON only, always: {"status":"succeeded|partially_succeeded|failed","project":"vault-sandbox auto-unseal (#270/#219)","phase":"VS-1 prep","actions_taken":[],"actions_failed":[],"files_touched":[],"containers_restarted":[],"server01_existing_unseal":"none|partial|present","vault_sandbox":{"container":"","version":"","sealed":true,"initialized":true,"threshold":"t-of-n","seal_type":""},"key_source":{"where":"","fields":[],"count":0,"verified":false},"stdin_unseal_supported":true,"validation":{"bash_n":"","systemd_verify":""},"unverified_claims":[],"next_step":"","notes":""}