Skip to content

Kubernetes Secrets

Prefect Customer-Managed requires a number of secrets in order to function properly. If secrets are generally incorrect in content, format, or missing, pods can possibly CrashLoop, or remain running without any updated data being retrieved from a database. For a POC, or dev-managed environment, the following option is enabled in the prefect-cloud helm chart to create these secrets in the cluster for you, provided they are configured in values.yaml:

# Creates secrets in K8s cluster if true
createAppSecretsInChart: true

For production environments, it is assumed each customer has requirements and security considerations to restrict and follow best-practices within their organization.

The format below is a list of the top-level Secret kind, the keys + values within. If createAppSecretsInChart is true, these will be created for you during a helm install using supplied values in values.yaml. If createAppSecretsInChart is false, the expectation is that these will already exist in cluster through your own mechanisms.

All Passwords must be URL-encoded. E.g. " !@" should be "%20%21%40" Usernames are referenced as either the serviceUser or the superUser from prefect-cloud/values.yaml and can be changed as necessary. The serviceUser`` - (prefectby default) is how most database connections and daily platform usage is conducted. The ``superUser - (postgres by default) is used to generate the schemas, roles, and perform database migrations.

auth-token-keys

Symmetric keys used to sign and verify the HS256 JWT access/refresh tokens issued by the platform. These must be high-entropy strings of at least 32 characters (e.g. generated with openssl rand -base64 32), and the two keys must be different values.

If createAppSecretsInChart is true, this secret is created for you: either from global.auth.accessTokenKey/global.auth.refreshTokenKey in your values override, or randomly generated at install time if those are unset (generated keys are reused on helm upgrade, so sessions are not invalidated). If you render manifests with helm template instead of installing with Helm, always provide explicit keys — random generation happens on every render and would rotate the keys on each deploy.

Alternatively — and independently of createAppSecretsInChart — you can manage this secret entirely yourself (e.g. via External Secrets Operator or Vault) and point the chart at it by name:

global:
  auth:
    existingSecret: my-jwt-keys

The referenced secret must contain the access-token-key and refresh-token-key keys shown below. When existingSecret is set, the chart never creates the secret and accessTokenKey/refreshTokenKey must not be set.

auth-token-keys
  access-token-key: <high-entropy string, at least 32 characters>
  refresh-token-key: <high-entropy string, at least 32 characters, different from access-token-key>

events-replica-user-connection-strings

events-replica-user-connection-strings
  db-migration: postgresql://postgres:<superUser URL Encoded Password>@<replica database hostname>:<port>/events
  events-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/events
  ladler: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/events
  logs: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/events
  nebula-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/events
  partman: postgresql+asyncpg://postgres:<superUser URL Encoded Password>@<replica database hostname>:<port>/events
  prefect-user-password: <NON URL ENCODED serviceUser password>
  schema-setup: postgresql://postgres:<superUser URL Encoded Password>@<replica database hostname>:<port>/postgres
  triggers: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/events

events-user-connection-strings

events-user-connection-strings
  db-migration: postgresql://postgres:<superUser URL Encoded Password>@<database hostname>:<port>/events
  events-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/events
  ladler: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/events
  logs: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/events
  nebula-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/events
  partman: postgresql+asyncpg://postgres:<superUser URL Encoded Password>@<database hostname>:<port>/events
  prefect-user-password: <NON URL ENCODED serviceUser password>
  schema-setup: postgresql://postgres:<superUser URL Encoded Password>@<database hostname>:<port>/postgres
  triggers: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/events

external-service-secrets

external-service-secrets
  adfs-client-secret: "" # Only if using ADFS
  entra-client-secret: "" # Only if using Entra
  okta-api-key: "" # Only if using Okta
  okta-client-secret: "" # Only if using Okta
  smtp-password: "" # Only if using SMTP

nebula-replica-user-connection-strings

nebula-replica-user-connection-strings
  actions: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/nebula
  auth-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/nebula
  events-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/nebula
  events-background: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/nebula
  expiration-setter: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/nebula
  nebula-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/nebula
  nebula-background: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/nebula
  orion-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/nebula
  triggers: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/nebula

nebula-user-connection-strings

nebula-user-connection-strings
  prefect-user-password: <NON URL ENCODED serviceUser password>
  schema-setup: postgresql://postgres:<superUser URL Encoded Password>@<database hostname>:<port>/postgres
  db-migration: postgresql://postgres:<superUser URL Encoded Password>@<database hostname>:<port>/nebula

  actions: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/nebula
  auth-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/nebula
  events-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/nebula
  events-background: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/nebula
  expiration-setter: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/nebula
  nebula-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/nebula
  nebula-background: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/nebula
  orion-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/nebula
  triggers: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/nebula

orion-replica-user-connection-strings

orion-replica-user-connection-strings
  expiration-processor: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  expiration-setter: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  flow-run-notifications: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  flow-run-reads: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  flow-run-writes: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  foreman: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  logs: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  mark-late-runs: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  nebula-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  nebula-background: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  orchestration-ui-reads: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  orion-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  orion-background: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  reaper-man: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  scheduler: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  task-run-reads: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  task-run-recorder: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  task-run-writes: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  work-pool-reads: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion
  worker-monitor: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<replica database hostname>:<port>/orion

orion-user-connection-strings

orion-user-connection-strings
  db-migration: postgresql://postgres:<superUser URL Encoded Password>@<database hostname>:<port>/orion
  prefect-user-password: prefect-user-password: <NON URL ENCODED serviceUser password>
  schema-setup: postgresql://postgres:<superUser URL Encoded Password>@<database hostname>:<port>/postgres

  concurrency-lease-reaper: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  expiration-processor: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  expiration-setter: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  flow-run-notifications: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  flow-run-reads: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  flow-run-writes: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  foreman: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  logs: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  mark-late-runs: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  nebula-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  nebula-background: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  orchestration-ui-reads: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  orion-api: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  orion-background: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  reaper-man: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  scheduler: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  task-run-reads: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  task-run-recorder: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  task-run-writes: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  work-pool-reads: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion
  worker-monitor: postgresql+asyncpg://prefect:<serviceUser URL Encoded Password>@<database hostname>:<port>/orion

redis-passwords

# Only necessary if Redis is password protected
redis-passwords
  cache: ""
  events: ""
  streams: ""