secret-distribution: verify against live-checked KB, fix diagram, add real evidence
Source Trilium note (Secret Distribution Model) was live-verified and stamped this session - Certificate Flow, App Secret Flow, Configuration Distribution Flow, and the technitium_api_token Vault-KV exception all confirmed against the real hosts, not just trusted from the KB. Replaced the Mermaid diagram, which incorrectly showed the Configuration Distribution Flow feeding into Vault directly, with a corrected version: that flow is a control-plane gate on what Vault Agent renders, not a peer data flow. Added a real Vault Agent log excerpt proving the full redeploy chain (restart -> render -> reload_command -> container recreated) actually happens, and restored the technitium_api_token exception that was in the source note but missing from this doc.
This commit is contained in:
3 files changed
+12
-11
No files matched your search
@@ -3,17 +3,7 @@
|
||||
> [!NOTE]
|
||||
> [`docs/secrets-and-pki.md`](secrets-and-pki.md) covers *what* Vault is and *why* it exists. This doc covers something different and, arguably, harder to get right: the actual contract for how a secret value moves from being written into Vault to being consumed by a running container — and why that contract is deliberately split into four separate flows instead of one universal one.
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Op["Operator"] -->|1: writes cert/secret request| Vault["Vault"]
|
||||
Vault -->|2: Certificate Flow| Cert["Short-lived cert<br/>rendered to disk"]
|
||||
Vault -->|3: App Secret Flow| Sec["Rendered secret file<br/>0600, gitignored"]
|
||||
Repo["Provisioning repo"] -->|4: Config Distribution Flow| Vault
|
||||
Op2["Operator"] -.5: Administrative Secret Flow<br/>separate system entirely.-> EncFile["ansible-vault encrypted file<br/>in the repo itself"]
|
||||
|
||||
Cert --> Container["Container reads<br/>local disk only"]
|
||||
Sec --> Container
|
||||
```
|
||||

|
||||
|
||||
## Why four flows instead of one
|
||||
|
||||
@@ -51,6 +41,10 @@ The obvious simpler design is one universal "secret goes in, secret comes out" p
|
||||
> [!IMPORTANT]
|
||||
> This is the flow with the sharpest failure mode in the whole model: a missing or malformed template referenced by a host's own config crashes that host's **entire** Vault Agent process — every other secret/cert that host was already rendering stops updating too, not just the one broken template. A single YAML typo in one app's template inventory can silently freeze every other app's secret rotation on that same host. This is why a config redeploy always requires confirming the underlying git change actually landed first, not just that the deploy command returned success.
|
||||
|
||||
That redeploy-and-restart sequence isn't just a claim — here's a real one, start to finish: Vault Agent restarts, authenticates, renders a fresh `.env.secrets`, and its `reload_command` fires `docker compose up -d`, which recreates and restarts the actual container:
|
||||
|
||||

|
||||
|
||||
**Shared-secret variant:** not every template is host-scoped — one credential needed by every docker host for its own registry pushes (see [`docs/registry-and-build.md`](registry-and-build.md)) is templated from a single shared path rather than a per-host one. Same mechanics, just a shared source instead of a private one — and it relies on every host's policy already granting read access to that shared path, the same "shared + private" pattern described in [`docs/secrets-and-pki.md`](secrets-and-pki.md)'s access model.
|
||||
|
||||
## 4️⃣ Administrative Secret Flow — a deliberately separate, simpler system
|
||||
@@ -64,5 +58,8 @@ The obvious simpler design is one universal "secret goes in, secret comes out" p
|
||||
> [!TIP]
|
||||
> **Why two systems, not one — the actual reasoning, not just the rule**: Vault KV is built for runtime/service/pipeline secrets a running container needs continuously and automatically. `ansible-vault` is built for secrets used by tooling that *operates on* the fleet rather than secrets *consumed by* the fleet's own running services — a Gitea admin token used only during a playbook run, for instance, doesn't need automatic rotation, per-host scoping, or a rendered file sitting on disk permanently. Building that into Vault's model would have meant either weakening Vault's per-host isolation for a use case that doesn't need it, or adding a whole parallel "admin secrets" concept inside Vault itself. Using the tool already built for exactly this case (`ansible-vault`, already part of the Ansible toolchain from [`docs/iac-pipeline.md`](iac-pipeline.md)) was less work and a better fit than extending Vault to do a second, different job.
|
||||
|
||||
> [!NOTE]
|
||||
> **One exception to this split, flagged rather than smoothed over**: Technitium's API token moved out of `ansible-vault` into live Vault KV (fetched via a `community.hashi_vault.vault_kv2_get` lookup at playbook-run time) even though it's consumed by an ansible-playbook, not a running service — exactly the case the law above says belongs in `ansible-vault` instead. The admin/runtime split is the general rule here, not an absolute one, and this is the one place it doesn't cleanly apply.
|
||||
|
||||
---
|
||||
Related: [`docs/secrets-and-pki.md`](secrets-and-pki.md), [`docs/iac-pipeline.md`](iac-pipeline.md), [`docs/registry-and-build.md`](registry-and-build.md)
|
||||
Reference in new issue
Block a user