From 630c5e0ae5ca74055c60806c615977a71d81a90d Mon Sep 17 00:00:00 2001 From: fkrebs Date: Thu, 21 May 2026 07:34:32 +0200 Subject: [PATCH] docs: add secrets-manager design doc; fix mkdocs nav --- services/secrets-manager.md | 168 ++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 services/secrets-manager.md diff --git a/services/secrets-manager.md b/services/secrets-manager.md new file mode 100644 index 0000000..7c2131e --- /dev/null +++ b/services/secrets-manager.md @@ -0,0 +1,168 @@ +# Secrets Manager — Design & Integration + +## Problem statement + +Secrets are currently scattered across: + +| Location | Count | Risk | +|---|---|---| +| `/opt/stacks/ai/.env` on CT 104 | ~30 keys | Readable by any root-equivalent process; not versioned | +| Coder `main.tf` (hardcoded env vars) | 6 | Committed to Gitea; visible in template history | +| Zoraxy proxy configs | 0 (plain routes) | Low | +| HA `secrets.yaml` on HAOS VM 100 | unknown | Not backed up centrally | +| `/root/garage-chat-artifacts.creds` | 1 | `0600`, but on Proxmox host root | +| Browser/Vaultwarden (manual) | Many | Human-only access | + +Goal: single secret store that agents, Docker services, and Coder workspaces can all read programmatically, with OIDC-gated access via Pocket-ID. + +--- + +## Candidate solutions + +### 1. Infisical (recommended) + +Open-source HashiCorp Vault alternative. Docker-compose deployable. Native integrations for: + +- Docker secrets injection (Infisical agent sidecar) +- Kubernetes/Coder workspace env injection +- REST API + OIDC machine identities +- OIDC SSO (can federate with Pocket-ID) +- Web UI + +**Deployment**: separate LXC (recommended — see rationale below). Postgres backend → candidate for CT 113 consolidation once second NVMe lands. + +**Port**: 8080 internally; no external exposure needed (LAN-only MCP sidecar pattern). + +--- + +### 2. HashiCorp Vault (OSS) + +Industry standard. Steeper ops overhead (unsealing, audit logs, lease renewal). Overkill for a homelab unless you need HSM-grade guarantees. + +--- + +### 3. Doppler (SaaS) + +Managed; free tier; native CLI and Docker integration. Outbound dependency; secrets leave the homelab. **Not suitable** given the DLR/LUMEN data handling doctrine. + +--- + +### 4. Stay with Vaultwarden + manual OIDC + +Already deployed. Works for human access. No programmatic injection without writing custom code. Dead end for agent/pipeline automation. + +--- + +## Recommendation: Infisical on a dedicated LXC + +### Why a separate LXC? + +1. **Blast radius isolation** — if the CT 104 Docker stack is compromised, the secret store is not on the same attack surface. +2. **Minimal footprint** — Infisical + Postgres is the only workload; nothing else can mess with the process space. +3. **Simpler audit** — outbound connections from CT 104 are numerous; a dedicated secrets LXC should have near-zero egress. +4. **HA restart independence** — CT 104 restarts (image gen, GPU passthrough experiments) don't affect secret availability. + +Suggested: **CT 112** (next available), 2 vCPU / 2 GB RAM, 8 GB disk on local-zfs. + +--- + +## Architecture + +```mermaid +flowchart TD + subgraph CT112["CT 112 — secrets"] + infisical["Infisical Server\n:8080"] + pg_sec["Postgres\n(infisical DB)"] + infisical --- pg_sec + end + + subgraph CT104["CT 104 — Docker host"] + agent["Infisical Agent\n(sidecar per stack)"] + env_file[".env (templated)\nrendered at startup"] + agent -->|pull on start| infisical + agent --> env_file + end + + subgraph CT111["CT 111 — Coder"] + coder["Coder server"] + ws["Workspace containers\n(env injected at provision)"] + coder -->|agent token| infisical + coder --> ws + end + + subgraph CT110["CT 110 — Pocket-ID"] + oidc["OIDC IdP"] + end + + oidc -->|machine identity| infisical + oidc -->|user SSO| infisical +``` + +--- + +## Setup plan + +### Phase 1 — Deploy Infisical on CT 112 + +```bash +# On Proxmox host +pvesh create /nodes/nuc/lxc \ + --ostemplate local:vztmpl/debian-12-standard_12.7-1_amd64.tar.zst \ + --vmid 112 --hostname secrets --memory 2048 --cores 2 \ + --rootfs local-zfs:8 --net0 name=eth0,bridge=vmbr0,ip=dhcp + +# Inside CT 112 +apt-get install -y docker.io docker-compose-plugin +# Deploy from https://github.com/Infisical/infisical (official compose) +``` + +Infisical requires a Redis instance alongside Postgres. The official `docker-compose.yml` bundles both. + +### Phase 2 — Migrate CT 104 secrets + +1. Create an Infisical project `homelab/ct104` +2. Import existing `.env` keys via Infisical CLI: `infisical import --env prod --path /homelab/ct104 < .env` +3. Add Infisical agent to each compose stack as a sidecar that renders `.env` from templates at container start + +### Phase 3 — Coder workspace injection + +Infisical has a native Coder integration (via machine identity token). Replace hardcoded env vars in `main.tf` with: +```hcl +data "external" "secrets" { + program = ["infisical", "export", "--env", "prod", "--path", "/coder/workspaces", "--format", "dotenv-export"] +} +``` + +Or use the Infisical agent installed in the workspace image. + +### Phase 4 — OIDC SSO via Pocket-ID + +Infisical supports OIDC SSO under Settings → Authentication → OIDC. Register a new client in Pocket-ID with callback `https://secrets.nuclide.systems/api/v1/sso/oidc/callback` (or LAN-only URL). + +--- + +## Prioritisation + +| Item | Effort | Value | +|---|---|---| +| Create CT 112, deploy Infisical | 1h | High — removes .env sprawl | +| Migrate CT 104 .env | 30min | High | +| Coder template injection | 1h | Medium — workspaces currently work | +| HA secrets.yaml → Infisical | 30min (HA add-on) | Medium | +| OIDC SSO via Pocket-ID | 30min | Low (convenience) | + +--- + +## Short-term mitigation (before CT 112 is built) + +1. Remove secrets from Coder `main.tf` that appear in Gitea history — use Coder template variables or env injection instead. +2. Keep `/opt/stacks/ai/.env` mode `0600`; ensure it is in `.gitignore` for any repo that mounts that directory. +3. Use Vaultwarden as the authoritative human copy; rotate any key that has appeared in Claude Code context (see `audit-claude-code-meta.md`). + +--- + +## Related + +- [[postgres-consolidation]] — CT 113 will consolidate Postgres instances including Infisical's DB +- [[feedback_zoraxy_confirm]] — Zoraxy route for `secrets.nuclide.systems` will need operator approval when CT 112 is ready +- `security/audit-claude-code-meta.md` — lists secrets that transited Claude API this session