secrets
Secrets Management
Four mechanisms exist for provisioning secrets. See reference.md for the mechanism comparison table and annotation reference.
Decision Tree
App needs a secret?
│
├─ Can it be randomly generated? (password, API key, token)
│ │
│ ├─ Does it need to survive cluster rebuilds?
│ │ ├─ YES (e.g., encryption key seed, LDAP key)
│ │ │ └─ Use app-secrets Terragrunt module + ExternalSecret
│ │ └─ NO (e.g., session secret, internal API key)
│ │ └─ Use secret-generator annotation
│ │
│ └─ Is it a database credential?
│ └─ Use secret-generator with type: kubernetes.io/basic-auth
│
├─ Must match an external value? (OAuth, cloud API, webhook URL)
│ └─ Use ExternalSecret → AWS SSM
│
├─ Shared across namespaces? (DB superuser, Dragonfly password)
│ └─ Use kubernetes-replicator annotations
│
└─ Unclear?
└─ AskUserQuestion: "Can this secret be randomly generated,
or must it match a specific external value?"
Mechanism 1: secret-generator (Ephemeral, In-Cluster)
The mittwald/kubernetes-secret-generator controller watches for annotated Secrets and
auto-populates them with random values. Preferred for secrets that do not need to persist
across cluster rebuilds.
Template: see reference.md
Mechanism 2: ExternalSecret (Persistent, from AWS SSM)
ESO pulls values from AWS SSM Parameter Store via the aws-ssm ClusterSecretStore at
kubernetes/platform/config/secrets/cluster-secret-store.yaml (region: us-east-2).
SSM path convention: /homelab/kubernetes/${cluster_name}/<app-or-secret-name>
Template: see reference.md
Mechanism 3: app-secrets Terragrunt Module (Generated + Persistent)
For secrets that must be randomly generated AND survive cluster rebuilds. OpenTofu generates random values and stores them as a JSON SecureString in AWS SSM. An ExternalSecret then pulls individual keys.
lifecycle.prevent_destroy = true protects the SSM parameter. lifecycle.ignore_changes = [value]
prevents re-generating on subsequent applies. Local backup written to ~/.secrets/homelab/<app>-secrets.json.
Workflow: create unit → add to stack → apply → create ExternalSecret using the multi-key JSON
pattern from Mechanism 2. Real example: infrastructure/units/lldap-secrets/terragrunt.hcl.
Template: see reference.md
Mechanism 4: kubernetes-replicator (Cross-Namespace)
Copies Secrets from one namespace to another. Used when a shared resource generates a secret
that consumer namespaces need. Add replication annotations to the source Secret, then create
an empty consumer Secret referencing it. Add both files to their respective kustomization.yaml.
Template: see reference.md
Three-Tier Pattern (Exemplar: Authelia)
kubernetes/clusters/live/config/authelia-prereqs/ demonstrates all three types together:
| File | Mechanism | Purpose |
|---|---|---|
lldap-secrets.yaml |
ExternalSecret (app-secrets module) | Persistent LLDAP encryption keys |
authelia-db-credentials.yaml |
secret-generator | Ephemeral DB password |
cnpg-superuser-replica.yaml |
kubernetes-replicator | Replicated from database namespace |
dragonfly-secret-replication.yaml |
kubernetes-replicator | Replicated from database namespace |
Debugging
Run scripts/check-secret-sync.sh <name> <namespace> for the full status check sequence.
To verify an SSM parameter exists:
aws ssm get-parameter --name "/homelab/kubernetes/<cluster>/<secret>" --with-decryption
See reference.md for common failure causes and alert definitions.
Cross-References
| Document | Relevance |
|---|---|
| kubernetes/platform/CLAUDE.md | Secrets management overview, SSM parameters for bootstrap |
| deploy-app skill | Secrets decision tree for new deployments |
| cnpg-database skill | Database credential chain |
| terragrunt skill | Infrastructure operations for app-secrets module |
More from ionfury/homelab
prometheus
Query Prometheus API for cluster metrics, alerts, and observability data. Use when investigating cluster health, performance issues, resource utilization, or alert status. Triggers on questions like "what's the CPU usage", "show me firing alerts", "check memory pressure", "query prometheus for", or any PromQL-related requests.
66taskfiles
|
63opentofu-modules
|
59terragrunt
|
59k8s
|
46cnpg-database
|
37