Skip to main content

Wizard-issued credentials

The console issues credentials per product instance before you deploy. Create each product you run — TrustGate under Agent Gateway and TrustGuard under Agent Runtime — and collect its own set. See Console setup for the step-by-step flow. Each private instance issues:
  • A configuration-sync token, scoped to that gateway or TrustGuard
  • A DataAgent enrollment token that authorizes OTLP metadata egress and DataBridge retrieval
The Docker command injects the configuration-sync token, DataAgent enrollment token, and a generated local cache key. The maintained Compose manifest also requires operator-supplied SERVER_SECRET_KEY, CONFIG_SYNC_GRPC_ENDPOINT, and DATABRIDGE_ADDR. The Kubernetes wizard currently writes credentials directly into generated values.yaml; it does not place them in Kubernetes Secret references. Treat the entire generated file as a secret and never commit it. For production, move the credentials into pre-created Kubernetes Secrets or an approved secret manager and map them through the current maintained chart interfaces. Manual displays only CONTROL_PLANE_JWT and DATA_AGENT_JWT. Never print credentials in logs or share them in tickets. Regenerating install configuration from Settings → Agent Gateway → Deployment issues new install credentials.

Chart-managed secrets

For an operator-managed Kubernetes deployment that uses a maintained Helm chart, these settings control runtime secret generation:
For GitOps, pre-create Secrets and set autoGenerateSecrets: false with preserveExistingSecrets: true. helm template cannot preserve generated values via lookup.

Data-plane secrets

postgresql-secrets stores one name per fact

The Secret holds these nine keys:
Plus one connection string, which differs by mode. Hybrid adds SENSIBLE_PG_DSN, the lib/pq DSN that the TrustGate and TrustGuard telemetry exporters and DataAgent read. External adds POSTGRES_PRISMA_URL for the console instead, and since chart 2.8.0 no longer stores SENSIBLE_PG_DSN at all — nothing in External ever read it. Services that expect different variable names still get them: TrustGate, TrustGuard and AlertEngine read DB_HOST, DB_NAME, DB_SSL_MODE and so on, and the chart maps the canonical keys to those names on each Deployment. Do not add DB_* or DATABASE_URL to this Secret — earlier chart versions stored those duplicates and no longer do. If you pre-create the Secret for GitOps, populate the keys above.

Bringing your own Postgres Secret

The two ways of supplying Postgres credentials need opposite key names. This is the most common managed-Postgres install failure.
The reason is that setting global.postgresql.existingSecret.name stops the chart rendering postgresql-secrets at all. With no Secret of its own to map from, every consumer takes yours wholesale with envFrom and nothing gets renamed — so your keys have to be the names the containers actually read. Supply POSTGRES_* here and the pods start with no database configuration and fail on their first query.

Connect to a managed PostgreSQL

This section covers the Hybrid shared role (and External’s control-plane neuraltrust role when you replace the whole postgresql-secrets Secret). For External runtime services — AgentGateway, TrustGuard, AlertEngine, DataCore — prefer the per-service hooks below instead of replacing postgresql-secrets wholesale. Two ways, depending on whether you are willing to put the password in a values file. Either way, create the role and database yourself first on a managed instance — the chart never runs CREATE USER against a store it does not own. (When the chart runs Postgres itself in External mode, chart 2.7.0+ creates the per-service roles for you — see External datastores.)
The simpler path. Give the chart the connection facts and let it assemble postgresql-secrets in the canonical POSTGRES_* shape. Every consumer then resolves without further wiring.
The password lands in the values file, so treat that file as a secret or supply it with --set from your secret store at install time. In External, chart 2.8.0+ lets you drop it entirely and name a Secret instead — see global.postgresql.passwordSecret.
data-plane-api needs the Secret named a second time. It resolves its own Postgres reference, defaulting to postgresql-secrets — the Secret that naming an existingSecret prevents the chart from rendering. Without the data-plane-api block above, its pods reference a Secret that does not exist and sit in CreateContainerConfigError, while every other workload runs normally. It also looks up different key names, which is why the block maps yours onto them.This applies whenever global.products.dataPlane is true. Omit the block entirely when you let the chart build the Secret — the defaults resolve.
For AWS IAM authentication set POSTGRES_LOGIN: aws instead, and see IAM authentication.

External per-service datastore credentials

In External mode each runtime service has its own database and its own password. Writing those passwords into a values file works, but they then sit in Helm release history. Since chart 2.6.0 you can name a Secret you created instead: the chart leaves that key out of the Secret it renders and injects the variable with a secretKeyRef. The last row arrived in chart 2.8.0 and covers the control-plane neuraltrust role, the credential the console and the API share. It behaves like the others but applies globally: the chart omits POSTGRES_PASSWORD and POSTGRES_PRISMA_URL from postgresql-secrets, writes every other key, and points the console (both containers), the API and data-plane-api at your Secret. The console then assembles its own connection URL from the POSTGRES_* parts, so its image must be recent enough to carry scripts/postgres-password-url.mjs — the migration step needs it. It is rejected in Hybrid, which still composes a DSN, and while the chart runs its own Postgres. key is configurable, so one Secret can hold every Postgres role under a different key, and one Redis Secret can hold both REDIS_PASSWORD (gateways) and the assembled REDIS_URL that data-plane-api reads.
With every hook in place the values file holds no credential at all. An inline password next to a hook is rejected at render. The hooks are ignored under iamAuth: true and in Hybrid (which already has global.postgresql.existingSecret / global.redis.existingSecret for the shared role). Do not use global.postgresql.existingSecret for this External layout unless you intend to hand-write every key in postgresql-secrets, connection strings included — passwordSecret above is the narrow version of it, and the one you want. Full example: values-managed-datastores.yaml.example.

platform-secrets keeps both halves of a shared credential in step

Some credentials must be identical on two sides — a signing key on one service and its validator on another. Those live in one platform-secrets Secret that the chart resolves once and every consumer references, so the halves cannot drift. On upgrade it adopts whatever your existing per-service Secrets already hold, so nothing rotates. It is created when global.autoGenerateSecrets is enabled (the default); with autoGenerateSecrets: false each service falls back to its own Secret, which you then keep in step yourself.

Four extra keys under a Central control plane

global.deploymentMode: saas adds four credentials to platform-secrets, generated for you on the same terms as the rest:
If you pre-provision secrets — global.autoGenerateSecrets: false, global.preserveExistingSecrets: true, or global.platformSecret.existingSecret — all four must be present, and the two token keys must hold one identical value. When they drift, every data-plane connection returns 401 with nothing visibly wrong on either side. Running ./create-secrets.sh with DEPLOYMENT_MODE=saas writes all four correctly, including the alias.
TELEMETRY_JWT_PRIVATE_KEY_PEM is a signing key rather than a shared secret — the ingest gateway reads the public half from DataCore’s JWKS endpoint, so only the private PEM is stored. Regenerating it invalidates every token already issued, so if you intend to own it, put it in place before the first install.

Credential contracts

  • The configuration-sync token authenticates the data plane’s outbound configuration pull from the SaaS control plane. Each product gets its own: one for TrustGate, one for TrustGuard.
  • Alongside it, CONFIG_SYNC_LKG_KEY encrypts the last-known-good configuration snapshot on disk. Unlike the token it is not a shared credential — the control plane never sees it — so as of chart 2.6.0 the chart generates it and you should not create one. It becomes yours to supply only under global.autoGenerateSecrets: false or global.preserveExistingSecrets: true, where the chart generates nothing at all. In that case supply it alongside the token as base64 that decodes to exactly 32 bytes — the data planes will not start without it.
  • The DataAgent enrollment token authorizes DataBridge retrieval and metadata export. In Hybrid there is no separate OTLP token to manage: TrustGate and TrustGuard send plain OTLP to a local collector co-located with DataAgent, which exchanges the enrollment JWT for a short-lived access token on their behalf.
  • The LLM and MCP URLs are not secrets. Configure them separately in Settings → Agent Gateway → General.

Credentials across multiple clusters

When you run active/passive clusters, some credentials are per cluster and some must be identical in both. Getting this wrong is invisible until a promotion. Only the active cluster should run the enrolled DataAgent; two would register duplicate streams. Keep the enrollment token in place in the passive cluster and enable DataAgent as part of the promotion. To let a cluster restart while the control plane is unavailable, the encrypted last-known-good file has to survive the restart. The chart mounts it on an emptyDir, so it does not: a pod that restarts during a control-plane outage has no cache to fall back on and will not become Ready. Plan failover on that basis, or move the mount to persistent storage yourself. See Hybrid → High availability, External, or Central.

Chart references

Reference pre-created Secrets by name so no token is ever written into a values file. Both settings are per product — TrustGate and TrustGuard each need their own. Configuration sync — Secrets holding CONFIG_SYNC_TOKEN:
Set existingSecret only. Config sync is already on by default in Hybrid, so restating enabled: true is redundant. DataAgent enrollment — the wizard-issued token, one Secret per product:
Do not set a tenant ID in values. The enrollment JWT already carries tenant_id and instance_id, and the chart reads them from the token. Keep configuration-sync and DataAgent enrollment tokens out of values files and source control.

Registry

Create gcr-secret (or set global.imagePullSecrets) yourself — the chart does not create registry credentials.

Full key reference

This page covers the Secrets you create. The exhaustive per-component key contract — every Secret the chart renders, every key inside it, and which container reads it — is maintained alongside the chart in SECRETS.md. It is the reference to use when integrating Vault, Sealed Secrets or External Secrets Operator, and it ships inside the chart artifact too, so helm pull <chart-ref> --version <VERSION> --untar gives you the copy matching your version.