> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ankra.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Organisation Secrets

> Keep a password, key or token out of Git, your terminal and chat - store it as an organisation secret with ankra secrets, reference it by its sentinel in a manifest or add-on, and rotate it in place.

An **organisation secret** (a secret slot) holds one value in Ankra's vault. A manifest, an add-on's values or an MCP server's environment refers to it by a **sentinel**, `${SECRET_SLOT:<id>}`, instead of carrying the value. Ankra puts the value in only when it seals the file with the organisation's SOPS key for delivery, so the value never sits in Git, in a stack definition or in a chat transcript.

Use a secret when the value should never pass through a person: a generated database password, a key you paste once from a file, a token a pipeline pipes in. When you want to write a value into the GitOps repository yourself, encrypted, use [SOPS encryption](https://docs.ankra.ai/guides/sops.md) directly instead.

## Before you start

* **Permissions.** Creating a secret needs `variables.write`, which every role but viewer holds. Replacing, rotating and deleting one needs `secrets.manage`, which owners and admins hold. Without the permission the command names it and exits 7.
* **The organisation's SOPS key is set up.** Ankra substitutes the value when it seals a file, so the place you put the sentinel must be a key the manifest's or add-on's `encrypted_paths` declares. See [Encrypting values in Stacks](https://docs.ankra.ai/guides/sops.md#encrypting-values-in-stacks).

## 1. Create the secret

The value comes from exactly one of `--generate`, `--from-file` or stdin. It is never accepted as a command-line argument, so it never lands in your shell history or the process list.

```bash theme={null}
ankra secrets create db-password --generate --length 48
ankra secrets create stripe-key --from-file ./stripe.key --hint "Stripe live key"
printf '%s' "$CI_TOKEN" | ankra secrets create ci-token
```

* `--generate` has Ankra create a random value that nobody sees. `--length` (16-96, 32 by default) and `--prefix` shape it.
* `--from-file` stores the file's bytes exactly.
* Stdin stores what you pipe, without the one line ending the pipe adds. On a terminal you get a masked prompt instead.

Each command prints the sentinel alone on stdout, so a script can capture it:

```bash theme={null}
SENTINEL="$(ankra secrets create db-password --generate)"
echo "$SENTINEL"
```

A secret does not expire unless you pass `--ttl` (at most `168h` for a generated one). A secret past its TTL is kept for as long as a deployed resource still references it.

## 2. Reference it where the value belongs

Put the sentinel at a key the document's `encrypted_paths` declares. For a Secret manifest in a Stack:

```yaml theme={null}
apiVersion: v1
kind: Secret
metadata:
  name: payments-db
  namespace: payments
type: Opaque
stringData:
  DB_PASSWORD: ${SECRET_SLOT:<id>}
```

with `stringData.DB_PASSWORD` (or a pattern such as `glob:stringData.DB_*`) in that manifest's `encrypted_paths`. An add-on's values work the same way, with the values path in the add-on's `encrypted_paths`.

On its next delivery, Ankra replaces the sentinel with the value and seals the file with SOPS, and the cluster agent decrypts it at deploy. What is committed to Git is the sentinel and the sealed file, never the plain value.

## 3. See who uses it

```bash theme={null}
ankra secrets list
ankra secrets list -o json
```

`list` shows each secret's name, id, whether a person or Ankra supplied the value, the deployed resources that reference it, when the value was last read and when it expires. It never shows a value. `-o json` adds each sentinel and every reference.

## 4. Change or rotate the value

The secret keeps its id, so its sentinel and every reference stay valid. The resources that reference it receive the new value the next time Ankra delivers them.

```bash theme={null}
ankra secrets rotate db-password --generate
ankra secrets set stripe-key --from-file ./stripe-new.key
printf '%s' "$NEW_CI_TOKEN" | ankra secrets set ci-token
```

Use `rotate --generate` for a value Ankra makes, and `set` for one you supply. Both need `secrets.manage`.

## 5. Delete it

```bash theme={null}
ankra secrets delete ci-token
```

Deleting removes the secret and its value for good. A secret that deployed resources still reference is refused, and the refusal names those resources: remove the sentinel from them, or remove the resources, first. There is no `--force`, because the next delivery of those resources would fail.

## Troubleshooting

| Symptom | Cause and fix |
| - | - |
| `ankra secrets create db-password some-value` exits 2 | A value as an argument is refused on purpose. Use `--generate`, `--from-file` or stdin. |
| The deployed resource holds the literal `${SECRET_SLOT:...}` text | The sentinel is at a key that `encrypted_paths` does not declare, so Ankra delivered the document as plain content. Declare the key and save again. |
| A command exits 7 naming `secrets.manage` | Replacing, rotating and deleting need an owner or admin. Creating needs only `variables.write`. |
| `delete` is refused | Deployed resources still reference the secret. The refusal names them. |

## Related

* [SOPS Encryption](https://docs.ankra.ai/guides/sops.md) - `encrypted_paths`, patterns and how decryption works.
* [`ankra secrets` reference](https://docs.ankra.ai/reference/cli/secrets)
* [Roles & Access](https://docs.ankra.ai/guides/roles-and-access.md) - who holds `variables.write` and `secrets.manage`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.