
## Reference existing Secrets

URL: https://docs.atlan.com/product/connections/self-deployed-runtime/how-tos/reference-existing-secrets

> Keep credentials out of your Helm values file—point the Self-Deployed Runtime charts at Kubernetes Secrets you already manage.

Many organizations require that credentials never appear in a values file, a Helm release, or a Git repository. On Kubernetes, the Self-Deployed Runtime charts support this: every sensitive value takes **either a literal or a reference to a Kubernetes Secret you already manage**, and you choose which.

This applies to both lifecycle modes—the SDR Orchestrator chart and each connector chart. The [guided install wizard](https://docs.atlan.com/llms/platform/self-deployed-runtime/install-guided/llms.txt) asks which you want and assembles the matching values file.

:::note
This is a Kubernetes capability. On Docker, the runtime reads its credentials from the generated config file and `.env` on the host, so protecting them is a host filesystem and access-control concern rather than a chart option.
:::

## What you can reference

| Value | Where you set the reference |
|---|---|
| Atlan OAuth `clientId` and `clientSecret` | `sdr.credentials.existingSecret` (orchestrator chart) or `global.credentialsSecret` (connector chart) |
| Object store and secret store credentials | A `secretKeyRef` on any Dapr component metadata entry |
| Any other environment variable | `valueFrom` on an `env` entry, or a whole Secret via `envFrom` |

Any tool that produces a Kubernetes Secret works—External Secrets Operator, the Secrets Store CSI driver, Sealed Secrets, or `kubectl`. The charts only read the Secret; they never create or modify it.

## Before you begin

Make sure you have:

- Permission to create Secrets in the namespace you install into.
- The Atlan OAuth `clientId` and `clientSecret` for this deployment.
- The name of the namespace you install into. For the orchestrator, this is also the namespace it deploys apps into.

## Step 1: Create your secret

Create it in the install namespace, before you install the chart:

```bash
kubectl create secret generic atlan-sdr-oauth \
 --namespace atlan \
 --from-literal=client-id=YOUR_CLIENT_ID \
 --from-literal=client-secret=YOUR_CLIENT_SECRET
```

Kubernetes Secrets are namespaced, so a Secret in another namespace can't be referenced.

## Step 2: Reference it from your values file

Name the Secret and map your key names onto the two the runtime reads. The key names are yours to choose—omit either one to fall back to its default.

For the **SDR Orchestrator** chart:

```yaml
sdr:
 credentials:
 existingSecret:
 name: atlan-sdr-oauth
 clientIdKey: client-id # default: ATLAN_AUTH_CLIENT_ID
 clientSecretKey: client-secret # default: ATLAN_AUTH_CLIENT_SECRET
```

For a **connector** chart in single-app mode:

```yaml
global:
 credentialsSecret:
 name: atlan-sdr-oauth
 clientIdKey: client-id # default: ATLAN_AUTH_CLIENT_ID
 clientSecretKey: client-secret # default: ATLAN_AUTH_CLIENT_SECRET
```

Leave the literal `clientId` and `clientSecret` fields empty, or remove them.

## What changes when you do this

- The chart creates **no** Secret of its own.
- The literal `clientId` and `clientSecret` fields are ignored. The referenced Secret always wins, so a leftover literal can't quietly override it.
- Nothing sensitive appears in your values file, in the Helm release, or in `helm get values`. Only the Secret name and the two key names are stored.
- **Orchestrator only:** every app the orchestrator deploys references the same Secret. The orchestrator passes down the reference, not the credential, so no app pod carries it either.

## Reference secrets from Dapr components

Object store and secret store credentials work the same way. Any metadata entry in a Dapr component can be a `secretKeyRef` instead of a literal `value`:

```yaml
objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountName
 value: "mystorageaccount"
 - name: containerName
 value: "atlan-data"
 - name: accountKey
 secretKeyRef:
 name: atlan-blob-creds
 key: account-key
```

Omit `key` to default it to `name`.

A `secretKeyRef` is only a pointer, so the runtime also has to know which store resolves it:

- **By default**, references resolve against the pod's environment. This is the route the OAuth reference in [Step 2](#step-2-reference-it-from-your-values-file) uses, and it needs no extra configuration. It only works for values that already reach the pod's environment, so it isn't a route for your own cloud credentials.
- **For your own credentials**, name the store that holds them—AWS Secrets Manager, Azure Key Vault, Vault, or the Kubernetes secret store:

 ```yaml
 objectstore:
 type: bindings.azure.blobstorage
 version: v1
 metadata:
 - name: accountKey
 secretKeyRef:
 name: atlan-blob-creds
 key: account-key
 auth:
 secretStore: kubernetes-secrets
 ```

 The named store must itself be configured as a component.

:::tip Consider workload identity first
For cloud object and secret stores, the simplest way to keep credentials out of your values file is to not have credentials at all. IRSA on EKS, Workload Identity on GKE, and managed identities on AKS all let you omit `accessKey` and `secretKey` entirely. The orchestrator gives every app it deploys the same ServiceAccount it runs as, so you annotate one ServiceAccount and every app inherits the access.
:::

:::note App image version
For **object store** components, the runtime resolves the reference itself rather than through the Dapr sidecar. Resolving one from a cloud secret store therefore needs a current app image. If a component fails to start with an unresolved reference, update the app to its latest version, or use the environment-backed default instead. Secret store components are unaffected.
:::

## Rotate credentials

Update the Secret's contents, then restart the workloads. Kubernetes doesn't re-inject environment variables into a running pod when a Secret changes:

```bash
kubectl rollout restart deployment --namespace atlan
```

For the orchestrator, this restarts both the orchestrator and the apps it deploys, since they read the same Secret.

## Troubleshooting

| Symptom | Cause and fix |
|---|---|
| Pods stay in `CreateContainerConfigError` | The Secret doesn't exist in the install namespace, or a key name doesn't match. Check `kubectl get secret atlan-sdr-oauth -n atlan -o jsonpath='{.data}'` against the key names in your values file. |
| Authentication fails with the reference set | Confirm you mapped the right keys: `clientIdKey` must name the key holding the client ID, not the client ID itself. |
| The runtime still shows a literal credential | A literal left in the values file is ignored, not used—check that the Secret name is set, and that you're looking at the right release with `helm get values`. |
| A component fails to initialize with an unresolved reference | The store that resolves the reference isn't reachable. Either omit `auth.secretStore` to resolve from the pod environment, or confirm the named store is configured as a component and the app image is current. |

## See also

- [Secret management](https://docs.atlan.com/llms/platform/self-deployed-runtime/secret-management/llms.txt): How the runtime fetches source-system credentials at workflow time.
- [Security](https://docs.atlan.com/llms/platform/self-deployed-runtime/security/llms.txt): Security architecture, encryption, and compliance controls.
- [Install with the guided wizard](https://docs.atlan.com/llms/platform/self-deployed-runtime/install-guided/llms.txt): Assembles a setup guide, including this credential choice.

_Last updated: 26 August 2026._

---

> **AI agent?** Install the Atlan Docs MCP for direct access: https://docs.atlan.com/skills/install-docs-mcp.md
