Files
claude-projects/claude-config/config/prompts/infra/VS-1_vault_sandbox_autounseal_prep.md
T
Backtalk6858 d9419109a5 docs(claude-config): 2026-09-27 preflight prompts, owner decisions, redactions
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>
2026-09-28 12:46:31 -05:00

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 cat any *unseal*keys* file; use ls -la / stat only.
  • server-01 via ssh -o BatchMode=yes administrator@192.168.1.90 '<cmd>'. docker inspect only 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 if docker exec <c> vault status shows Sealed 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 runs docker 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 in vault operator unseal -h inside the vault-sandbox container, read-only).

TASKS

  1. 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 ONLY sealed, initialized, t, n, type, version fields), Vault address it listens on, restart policy.
  2. Find where the sandbox unseal keys live — by NAME only: search memory (/home/administrator/.claude/projects/-opt-appdata-docker/memory/, especially session_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.
  3. 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 events name filter 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 oneshot vault-sandbox-unseal.service run at boot After=docker.service (covers "container already up before the watcher started").
    • README.md: owner steps — (a) create /etc/vault-sandbox-unseal-keys root: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-keys and paste from the password manager), (b) install scripts + units, daemon-reload, enable --now the watcher and the oneshot, (c) TEST: docker restart <vault-sandbox> then journalctl -u vault-sandbox-watch-unseal -n 20 shows "unsealed" and vault status sealed=false, (d) then tell the main session so BOOT-1's server-01 host.env can drop vault-sandbox from CHECK_ONLY, (e) rollback.
  4. Validate: bash -n both scripts; systemd-analyze verify on 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":""}