Skip to content

Secrets & Vault Paths

Reference for secrets management and Vault path organization.

secret/
└── fzymgc-house/
├── cluster/ # Kubernetes service secrets
│ ├── keycloak # Keycloak admin credentials
│ ├── argocd/ # ArgoCD configuration
│ ├── grafana # Grafana admin/OIDC
│ ├── vault/ # Vault configuration
│ ├── temporal/ # Temporal worker secrets
│ ├── discord/ # Discord bot credentials
│ ├── workers/ # Temporal workflow secrets (HMAC keys, etc.)
│ ├── mealie # Mealie secrets
│ ├── nats # NATS NKey credentials
│ ├── mosquitto # Mosquitto MQTT credentials
│ ├── github # GitHub tokens
│ ├── cloudflared/ # Tunnel credentials
│ ├── tailscale/ # Tailscale operator OAuth
│ ├── alloy # Alloy external collector auth
│ ├── clickstack # ClickStack (ClickHouse + HyperDX + MongoDB + OTel)
│ ├── merlin # Merlin (OpenClaw) gateway credentials
│ ├── dolt # Dolt SQL server credentials
│ └── postgres/ # Database credentials
│ └── users/ # Per-app DB users
├── infrastructure/ # Infrastructure credentials
│ ├── cloudflare/ # Cloudflare API tokens
│ ├── hcp/ # HCP Terraform credentials
│ └── bmc/ # BMC credentials per node
└── applications/ # Application-specific secrets
PathPurposeKeys
secret/fzymgc-house/cluster/smtpShared Mailgun SMTP transport — DEPRECATED, being retired. Keycloak migrated to Cloudflare Email Sending (hl-zih3); Authentik (its last consumer) has been fully decommissioned, so this path is pending final deletion.host, port, username, password, use_tls
secret/fzymgc-house/cluster/keycloakKeycloak bootstrap admin + realm admin (Terraform provider auth) + outbound email (Cloudflare Email Sending, hl-zih3) + GitHub social login (hl-d0md)admin_username, admin_password (Keycloak bootstrap admin, consumed by the keycloak deployment ExternalSecret), terraform_username, terraform_password (admin-cli auth for the keycloak Terraform provider), email_from (per-app sender on the onboarded domain — auth@hl.fzymgc.house), cf_email_token (Cloudflare API token with “Email Sending: Edit” — used as the SMTP submission password; manually seeded, see docs/operations/outbound-email.md), github_client_id, github_client_secret (GitHub OAuth App — manually created, see docs/engineering/specs/2026-07-02-keycloak-email-github-login-design.md). Note: the old email_password key was a stale, unreferenced remnant and is removed with hl-zih3 (the Mailgun password lived on cluster/smtp, never here).
secret/fzymgc-house/cluster/octopusOctopus self-hosted PR reviewgithub_app_id, github_app_private_key, github_webhook_secret, github_state_secret, github_client_id, github_client_secret, better_auth_secret, octopus_data_key, admin_emails, openai_api_key (agentgateway VK)
secret/fzymgc-house/cluster/foveafovea AI code review (hl-3w5i)openai_api_key (agentgateway VK — the vk_fovea client copy). Also adds vk_fovea to the cluster/agentgateway accept-list path. qdrant_api_key (Qdrant auth for fovea audit auditQdrantKey + qdrant-fovea QDRANT__SERVICE__API_KEY; hl-uh07.10).
secret/fzymgc-house/cluster/engram-uiengram Connect web-UI (operator-seeded; OIDC creds moved to engram-ui/oidc, written by tf/keycloak/engram_ui.tf — hl-106s)ui_cookie_key
secret/fzymgc-house/cluster/argocdArgoCD configadmin_password, github_token, oidc_secret, webhook.github.secret
secret/fzymgc-house/cluster/grafanaGrafana secretsadmin_password, oidc_client_id, oidc_client_secret
secret/fzymgc-house/cluster/vault/*Vault configoidc_client_id, oidc_client_secret
secret/fzymgc-house/cluster/temporal/*Temporal worker secretsVarious per-workflow
secret/fzymgc-house/cluster/temporal/githubGitHub App for repo cloningapp_id, installation_id, private_key
secret/fzymgc-house/cluster/workers/drift-detectionDrift detection workflowdiscord-webhook-hmac-key
secret/fzymgc-house/cluster/discord/botDiscord bottoken
secret/fzymgc-house/cluster/mealieMealie configoidc_client_id, oidc_client_secret
secret/fzymgc-house/cluster/natsNATS NKey authoperator_jwt, operator_public, sys_account_seed, sys_account_public, sys_account_jwt, services_account_seed, services_account_public, services_account_jwt, iot_account_seed, iot_account_public, iot_account_jwt
secret/fzymgc-house/cluster/mosquittoMosquitto MQTT authpasswd (pre-hashed output from mosquitto_passwd), bridge_username (any non-empty), bridge_password (IOT user bearer JWT for NATS MQTT)
secret/fzymgc-house/cluster/githubGitHub integrationapp_id, app_private_key, webhook_secret
secret/fzymgc-house/cluster/cloudflared/*Tunnel credstunnel_token, tunnel_id
secret/fzymgc-house/cluster/tailscale/oauthTailscale operator OAuthclientId, clientSecret
secret/fzymgc-house/cluster/alloyAlloy external collector authexternal_token
secret/fzymgc-house/cluster/clickstackClickStack secretsadmin_password, mongo_admin_password, mongo_replicaset_keyfile, hyperdx_bootstrap_secret, hyperdx_oidc_client_id, hyperdx_oidc_client_secret (written by tf/keycloak/clickstack.tf), otel_ingest_api_key (HyperDX team key — the real OTLP ingest bearer), otel_ingest_token (legacy/vestigial — does not authenticate OTLP). Reused by headroom: both headroom-apps and headroom-agents consume otel_ingest_api_key from this same path via their headroom-otlp-headers ExternalSecret — no new Vault path is created for headroom.
secret/fzymgc-house/cluster/firewalla-mcpFirewalla MSP MCP server (hl-vbvu.1)msp_id (<domain>.firewalla.net), token (MSP personal access token), box_id. Also adds vk_firewalla + firewalla_mcp_auth_token to the cluster/agentgateway path.
secret/fzymgc-house/cluster/merlinMerlin (OpenClaw) gatewaygateway-token, claude-ai-session-key, gh-token, synthetic-api-key, openai-api-key, elevenlabs-api-key, openrouter-api-key
secret/fzymgc-house/cluster/doltDolt SQL server credentialsroot_password, agent_user, agent_password, beads_user, beads_password
secret/fzymgc-house/cluster/postgres/users/*DB usersusername, password
secret/fzymgc-house/cluster/pushoverPushover shared user keyuser_key
secret/fzymgc-house/cluster/pushover/app/cluster-infraPushover API token — infra domaintoken
secret/fzymgc-house/cluster/pushover/app/cluster-dataPushover API token — data domaintoken
secret/fzymgc-house/cluster/pushover/app/cluster-appsPushover API token — apps domaintoken
secret/fzymgc-house/cluster/pushover/app/cluster-edgePushover API token — edge domaintoken

Keycloak-provisioned OIDC credentials live at secret/fzymgc-house/cluster/<app>/oidc (written by tf/keycloak with plain data_json — fully diffable). The bare cluster/<app> paths are operator-only: Terraform never writes them, so vault kv put-style whole-version replaces by operators can no longer clobber TF-written fields (and vice versa). Apps: mealie, argocd, miniflux, karakeep, clickstack, engram-ui, cloudflare-access. See ADR hl-u103 and docs/engineering/specs/2026-07-03-vault-kv-deprecation-migration-design.md.

PathPurposeKeys
secret/fzymgc-house/infrastructure/cloudflare/bootstrap-tokenTerraform tokentoken
secret/fzymgc-house/infrastructure/cloudflare/discord-webhookNotificationsurl
secret/fzymgc-house/infrastructure/cloudflare/hcp-terraform-hmacWebhook authsecret
secret/fzymgc-house/infrastructure/cloudflare/hcp-terraform-workerWorker authtoken
secret/fzymgc-house/infrastructure/hcpHCP credentialsclient_id, client_secret
secret/fzymgc-house/infrastructure/bmc/*Node BMC credsusername, password
secret/fzymgc-house/infrastructure/router/kopia-r2Router Kopia backup to R2username (R2 access key), password (R2 secret key), repo_password (Kopia encryption)
secret/fzymgc-house/infrastructure/nas/kopia-b2NAS Kopia backup to Backblaze B2b2_key_id, b2_application_key (B2 S3 creds), repo_password (Kopia encryption; also held offline in 1Password), b2_region, b2_bucket
secret/fzymgc-house/infrastructure/nas/cloudflare-emailNAS outbound email (Cloudflare Email Sending, hl-xz9j) — the TrueNAS native alert transport (SMART/scrub/pool-health). Minted + written by tf/cloudflare/nas_email.tf; read by the nas-mail Ansible role.cf_email_token (per-app Cloudflare API token with “Email Sending: Edit”, used as the SMTP submission password), email_from (nas@hl.fzymgc.house — onboarded-domain sender). See docs/operations/outbound-email.md.
secret/fzymgc-house/infrastructure/nodes/cloudflare-emailCluster-nodes outbound email (Cloudflare Email Sending, hl-zejv.2) — the Turing Pi postfix system-mail relay (unattended-upgrades/cron). Minted + written by tf/cloudflare/nodes_email.tf; read control-node-side by the tp2-bootstrap-node role.cf_email_token (per-app Cloudflare API token with “Email Sending: Edit”, the SMTP submission password), email_from (nodes@hl.fzymgc.house — onboarded-domain sender). See docs/operations/outbound-email.md.
secret/fzymgc-house/infrastructure/router/dhcpv6Router DHCPv6 DUIDduid (colon-separated hex bytes for IPv6 prefix persistence)
PolicyPathsConsumers
external-secrets-operatorsecret/data/* (read)External Secrets Operator
fzymgc-cluster-secret-readersecret/data/* (read)General cluster read access
arc-runnerssecret/data/fzymgc-house/cluster/githubGitHub Actions runners
temporal-workersecret/data/fzymgc-house/cluster/temporal/*, secret/data/fzymgc-house/cluster/discord/*, secret/data/fzymgc-house/cluster/github/*, secret/data/fzymgc-house/cluster/cloudflare/r2/*, secret/data/fzymgc-house/cluster/workers/*Temporal workers
temporal-worker-terraformsecret/data/fzymgc-house/cluster/hcp-terraform, secret/data/fzymgc-house/cluster/discord/cluster-notifications-app, secret/data/fzymgc-house/cluster/workers/drift-detection, secret/data/fzymgc-house/cluster/temporal/githubTerraform drift detection & GuardedApply workflow
terraform-router-hosts-adminfzymgc-house/v1/ica1/v1/issue/router-hosts-client, fzymgc-house/v1/ica1/v1/cert/ca, fzymgc-house/v1/ica1/v1/ca_chain, sys/mounts/fzymgc-house/v1/ica1/v1GuardedApplyWorkflow PKI cert renewal
terraform-hcp-terraform-localsecret/data/fzymgc-house/infrastructure/cloudflare/hcp-terraform-worker, secret/data/fzymgc-house/infrastructure/cloudflare/hcp-terraform-hmac, secret/data/fzymgc-house/infrastructure/pki/fzymgc-ica1-caGuardedApplyWorkflow hcp-terraform module
alloy-agentsecret/data/fzymgc-house/cluster/alloyFirewalla Alloy collector
cert-managerpki/fzymgc-house/*cert-manager PKI
mealiesecret/data/fzymgc-house/cluster/mealie, secret/data/fzymgc-house/cluster/postgres/users/main-mealieMealie app
natssecret/data/fzymgc-house/cluster/natsNATS server
merlinsecret/data/fzymgc-house/cluster/merlinMerlin (OpenClaw) gateway service
github-actionssecret/data/fzymgc-house/cluster/githubCI/CD workflows
hcp-terraformMultiple cluster pathsTerraform workspaces
infrastructure-developersecret/data/fzymgc-house/infrastructure/*, secret/data/fzymgc-house/* (read)Human operators
nas-kopiasecret/data/fzymgc-house/infrastructure/nas/kopia-b2 (read)NAS Kopia→B2 backup role (interior sandbox)
otel-collector-nasfzymgc-house/v1/ica1/v1/issue/otel-collector-nas-client, fzymgc-house/v1/ica1/v1/sign/otel-collector-nas-client, fzymgc-house/v1/ica1/v1/cert/ca, fzymgc-house/v1/ica1/v1/ca_chain, secret/data/fzymgc-house/cluster/clickstack (read).200 TrueNAS nas-otel-collector (control-node cert issuance + ingest token)
otel-collector-nas-supportfzymgc-house/v1/ica1/v1/issue/otel-collector-nas-support-client, fzymgc-house/v1/ica1/v1/sign/otel-collector-nas-support-client, fzymgc-house/v1/ica1/v1/cert/ca, fzymgc-house/v1/ica1/v1/ca_chain, secret/data/fzymgc-house/cluster/clickstack (read, reused — no new subpath).202 nas-support nas-support-otel-collector (control-node cert issuance + ingest token)
adminsecret/* (full)Administrators
MethodMountPurpose
Kuberneteskubernetes/Service account auth
OIDCoidc/Human SSO via Keycloak
AppRoleapprole/Automation/CI
JWTjwt/HCP Terraform

Per-host clientAuth identities on the ICA1 mount (fzymgc-house/v1/ica1/v1), issued from the control node at deploy time and used to authenticate OTel collectors to otel-gateway.fzymgc.house (RequireAndVerifyClientCert). Each host gets a distinct role + CN for clean revocation/audit.

PKI roleCert CNMountEKUKeyTTLConsumer
otel-collector-nas-clientotelcol-nas.fzymgc.housefzymgc-house/v1/ica1/v1clientAuthECDSA P-256720h.200 TrueNAS nas-otel-collector
otel-collector-nas-support-clientotelcol-nas-support.fzymgc.housefzymgc-house/v1/ica1/v1clientAuthECDSA P-256720h.202 nas-support nas-support-otel-collector

Both collectors read the same ClickStack ingest token (secret/data/fzymgc-house/cluster/clickstack, property otel_ingest_api_key) — the .202 policy reuses this existing path rather than creating a new secret subpath.

apiVersion: external-secrets.io/v1
kind: ClusterSecretStore
metadata:
name: vault
spec:
provider:
vault:
server: "https://vault-internal.vault:8200"
path: "secret"
version: "v2"
auth:
kubernetes:
mountPath: "kubernetes"
role: "external-secrets"
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: grafana-admin
namespace: grafana
spec:
secretStoreRef:
name: vault
kind: ClusterSecretStore
target:
name: grafana-admin-secret
data:
- secretKey: admin-password
remoteRef:
key: fzymgc-house/cluster/grafana
property: admin_password
Terminal window
# Login to Vault
export VAULT_ADDR=https://vault.fzymgc.house
vault login -method=oidc
# Create secret
vault kv put secret/fzymgc-house/cluster/new-service \
api_key="value" \
secret_key="value"
# Verify
vault kv get secret/fzymgc-house/cluster/new-service
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: new-service-secrets
namespace: new-service
spec:
secretStoreRef:
name: vault
kind: ClusterSecretStore
target:
name: new-service-secrets
data:
- secretKey: API_KEY
remoteRef:
key: fzymgc-house/cluster/new-service
property: api_key
- secretKey: SECRET_KEY
remoteRef:
key: fzymgc-house/cluster/new-service
property: secret_key

If using a new path pattern, update the relevant policy in tf/vault/:

resource "vault_policy" "new-service" {
name = "new-service"
policy = <<EOT
# Allow service to read its secrets from Vault
path "secret/data/fzymgc-house/cluster/new-service" {
capabilities = ["read"]
}
# Required for ExternalSecrets to verify secret existence
path "secret/metadata/fzymgc-house/cluster/new-service" {
capabilities = ["read"]
}
EOT
}
TypePatternExample
Service secretssecret/fzymgc-house/cluster/<service>secret/fzymgc-house/cluster/grafana
Sub-service secretssecret/fzymgc-house/cluster/<service>/<component>secret/fzymgc-house/cluster/argocd/github
Database userssecret/fzymgc-house/cluster/postgres/users/<db>-<user>secret/fzymgc-house/cluster/postgres/users/main-mealie
Infrastructuresecret/fzymgc-house/infrastructure/<provider>secret/fzymgc-house/infrastructure/cloudflare
Per-node secretssecret/fzymgc-house/infrastructure/<type>/<node>secret/fzymgc-house/infrastructure/bmc/tpi-alpha-1
Terminal window
# Update secret value
vault kv put secret/fzymgc-house/cluster/service key=new-value
# Restart dependent pods
kubectl rollout restart deployment/service -n namespace

ExternalSecrets refreshes secrets based on refreshInterval:

spec:
refreshInterval: 1h # Check for updates hourly
Terminal window
# Check Vault path exists
vault kv get secret/fzymgc-house/cluster/service
# Check ExternalSecret status
kubectl get externalsecret -n namespace
kubectl describe externalsecret name -n namespace
# Check synced Kubernetes secret
kubectl get secret name -n namespace -o yaml
IssueCauseSolution
SecretSyncedErrorWrong path or missing permissionsVerify Vault path and policy
Secret not updatingrefreshInterval not elapsedWait or trigger manual refresh
Permission deniedMissing policy bindingUpdate Kubernetes auth role

See Vault Operations for detailed operational procedures.