- CT 111 (dev): Gitea + Coder + act-runner migrated to CT 104 - Gitea uses Redis for queue/cache/session (idmapped NFS LevelDB workaround) - Zoraxy routes dev/git updated to 192.168.1.40 - AdGuard dev.nuclide.lan updated to 192.168.1.40 - CT 112 (secrets): Infisical migrated to CT 109 - DB dump restored; SITE_URL updated to 192.168.1.8:8200 - AdGuard secrets.nuclide.lan updated to 192.168.1.8 - Proton Mail Bridge deployed on CT 104 (SMTP :1025, IMAP :1143) - Homepage updated: Dev group → ct104, Infisical → my-local, Background group added - portmap, ct-inventory, zoraxy, dev-environment, secrets-manager all updated Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
6.2 KiB
Secrets Manager — Infisical on CT 109
Status: deployed 2026-05-22; migrated CT 112 → CT 109 on 2026-05-26. Running at http://192.168.1.8:8200 (http://secrets.nuclide.lan:8200). LAN-only, no Zoraxy route — secrets must not be internet-exposed.
Stack: infisical/infisical:latest-postgres + Postgres 16 + Redis 7, all on CT 109 (ops, 192.168.1.8). Compose at /opt/stacks/infisical/ on CT 109. CT 112 ("secrets") is decommissioned; LXC pending removal.
Problem statement
Secrets are currently scattered across:
| Location | Count | Risk |
|---|---|---|
/opt/stacks/ai/.env on CT 104 |
~55 keys | Not versioned; duplicated across stacks |
Per-stack .env files CT 104 |
~30 keys | Several duplicated (WALG keys, IMMICH_API_KEY, etc.) |
CT 101, 111, 113 .env files |
~30 keys | No central rotation story |
Coder main.tf (hardcoded env vars) |
6 | Committed to Gitea; visible in template history |
HA secrets.yaml on HAOS VM 100 |
unknown | Not backed up centrally |
Goal: single LAN-only secret store that agents, Docker services, and Coder workspaces pull from programmatically. ~85 unique secrets identified in sweep (2026-05-22).
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?
- Blast radius isolation — if the CT 104 Docker stack is compromised, the secret store is not on the same attack surface.
- Minimal footprint — Infisical + Postgres is the only workload; nothing else can mess with the process space.
- Simpler audit — outbound connections from CT 104 are numerous; a dedicated secrets LXC should have near-zero egress.
- 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
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
# 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
- Create an Infisical project
homelab/ct104 - Import existing
.envkeys via Infisical CLI:infisical import --env prod --path /homelab/ct104 < .env - Add Infisical agent to each compose stack as a sidecar that renders
.envfrom 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:
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)
- Remove secrets from Coder
main.tfthat appear in Gitea history — use Coder template variables or env injection instead. - Keep
/opt/stacks/ai/.envmode0600; ensure it is in.gitignorefor any repo that mounts that directory. - 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.systemswill need operator approval when CT 112 is ready security/audit-claude-code-meta.md— lists secrets that transited Claude API this session