Skip to content

Secrets management (ExternalSecrets / Vault)

By default the chart is happy to generate or accept plaintext secret material through values.yaml. For production installs you'll usually want none of that ever landing in a values file or a Helm release's stored manifest — this page covers the chart's escape hatches and how to wire them up to external-secrets.io or HashiCorp Vault.

The five existingSecret slots

Every secret the chart handles has an existingSecret-style override. Set it and the chart skips generating its own Secret entirely — it just reads the Secret (and, where relevant, key) you point it at.

Chart valueDefault keyConsuming template(s)
postgres.passwordSecretpassword (postgres.passwordSecretKey)api-deployment.yaml, scanner-deployment.yaml, CNPG Cluster
s3.existingSecretaccessKey / secretKey (s3.existingSecretAccessKeyKey / existingSecretSecretKeyKey)api-deployment.yaml, scanner-deployment.yaml
saml.existingSecrettls.crt / tls.keymust be a kubernetes.io/tls Secretapi-deployment.yaml (mounted, not env)
signing.existingSecretmaster_keyapi-deployment.yaml (only when signing.enabled: true)
auth.sessionExistingSecretsession_secret (auth.sessionExistingSecretKey)api-deployment.yaml, scanner-deployment.yaml

Leave any of these empty and the chart falls back to its historical behaviour: generate a Secret on first install (random value or values-supplied plaintext), keep it stable across upgrades via Helm's lookup. Nothing changes for installs that don't opt in.

There's no license.existingSecret — a license key isn't chart state at all. It's uploaded at runtime through the admin UI, so it's simply not a secret the chart materialises or needs an external source for.

All five templates that render a chart-owned Secret — pg-secret.yaml, s3-secret.yaml, saml-secret.yaml, signing-secret.yaml, session-secret.yaml — are skipped outright when the matching existingSecret value is set, so no chart-managed Secret object is even created alongside the external one.

Why env-var consumption matters for which tool fits

Every one of these Secrets is read via secretKeyRef in the API and scanner Deployments (SAML's keypair is the one exception — it's volume-mounted as a TLS pair). That means any mechanism that ends up producing a real Kubernetes Secret object with the expected key names works — the chart doesn't care how that object got there.

A file-injecting sidecar (the classic Vault Agent Injector pattern, vault.hashicorp.com/agent-inject annotations that write secrets into a shared emptyDir as files) does not fit this model on its own — there's no Kubernetes Secret object for secretKeyRef to reference, and this chart's Deployments don't source env vars from a file. If your Vault setup uses Agent Injector elsewhere, don't try to point it at these Deployments directly; use one of the two options below instead, both of which materialise an actual Secret object.

Option 1: External Secrets Operator (ESO)

charts/orbitalreg/examples/external-secrets-eso.yaml is a ready-to-adapt reference: five ExternalSecret CRs, one per slot above, each targeting the exact Secret name and key(s) the matching values.yaml override expects.

bash
kubectl -n orbitalreg apply -f charts/orbitalreg/examples/external-secrets-eso.yaml

It assumes a SecretStore/ClusterSecretStore named orbitalreg-backend already exists. ESO supports many backends behind that same CR shape — AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, and Vault (spec.provider.vault). Pointing the SecretStore at Vault is the recommended way to get Vault-backed secrets into this chart: ESO's Vault provider authenticates to Vault (Kubernetes auth method, AppRole, etc.), reads the KV path in remoteRef.key, and writes the resulting Secret — no Deployment changes needed on this chart's side.

yaml
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
  name: orbitalreg-backend
spec:
  provider:
    vault:
      server: "https://vault.example.internal:8200"
      path: "secret"
      version: v2
      auth:
        kubernetes:
          mountPath: kubernetes
          role: orbitalreg
          serviceAccountRef:
            name: orbitalreg-api

Once that SecretStore resolves, the example file's five ExternalSecret CRs apply unchanged — only remoteRef.key needs adjusting to wherever you actually stored each value in Vault's KV engine.

Option 2: Vault Secrets Operator (VSO)

If you'd rather talk to Vault directly, without installing external-secrets.io, HashiCorp's own Vault Secrets Operator does the same job — a VaultStaticSecret CR syncs a Vault KV path into a Kubernetes Secret on a refresh interval. Point destination.name at the same five Secret names the table above expects:

yaml
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
  name: orbitalreg-session
spec:
  mount: secret
  path: orbitalreg/session
  destination:
    name: orbitalreg-session
    create: true
  refreshAfter: 1h
  vaultAuthRef: orbitalreg-vault-auth

Set auth.sessionExistingSecret: orbitalreg-session in values.yaml to match. Repeat for the other four slots using the key names from the table above.

Rotation

For all three paths (chart-generated, ESO, VSO) rotating the underlying value means updating the source (Vault KV write / secrets manager version) and letting the sync interval (refreshInterval / refreshAfter) pick it up — the API and scanner pods pick up a changed env var on their next restart, same as any other secretKeyRef-sourced value. The signing master key is the one exception worth flagging twice: rotating it makes every AES-GCM encrypted private signing key in signing_keys unrecoverable (see the warning in values.yaml's signing.existingSecret comment) — treat it as a mint-new-keys-and-redistribute-trust event, not a routine rotation.

  • Helm chart values — the full values.yaml reference, including the existingSecret keys from the table above.
  • Redis high availability — the other "bring your own externally-managed dependency" pattern in this chart.

Released under the Apache-2.0 License.