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

# Secret management

> Understand how Qodex encrypts provider keys, OAuth tokens, and sensitive auth credentials in self-hosted deployments.

# Secret management

Qodex encrypts sensitive credentials before storing them in Postgres.

The encryption key comes from `QODECLAW_SECRET_KEY`. In production, this value is one of the most important secrets in the deployment.

## What gets encrypted

Qodex encrypts values that could authenticate to another system:

* BYOK provider API keys.
* OAuth access and refresh tokens.
* Customer auth profile credentials used by API scenarios.
* Sensitive inbox answers, such as passwords or tokens.

Qodex does not encrypt normal product content with this layer. Project metadata, scenarios, finding text, chat transcripts, and memory files are stored as product data. Artifacts live in the configured storage backend.

## How encryption works

Qodex derives an AES-256-GCM key from `QODECLAW_SECRET_KEY` and encrypts sensitive values before persistence.

Encrypted values are stored in a versioned format:

```text theme={null}
enc:v1:<base64(iv)>:<base64(authTag)>:<base64(ciphertext)>
```

The application decrypts values only when it needs to use them. It should not return plaintext secrets to the UI or logs.

## Production requirement

Set `QODECLAW_SECRET_KEY` to a high-entropy string at least 32 characters long.

```bash theme={null}
openssl rand -base64 48
```

Keep this key in the same class of secret manager as your database credentials. Losing it means encrypted values in Postgres cannot be recovered.

## If the key is missing

For local development, Qodex can fall back to a derived development key and log a warning.

Do not rely on that fallback in production. If the container restarts with a different or missing key, previously encrypted values may become unreadable.

## Rotating the key

Changing `QODECLAW_SECRET_KEY` invalidates existing encrypted values.

For small deployments, the practical rotation path is:

1. Generate a new key.
2. Restart Qodex with the new key.
3. Re-enter BYOK keys.
4. Re-authenticate OAuth-based auth profiles.
5. Re-supply any other credentials stored through Qodex.

A dual-key re-encryption flow is planned but not currently implemented.

## Backups

Database backups do not include `QODECLAW_SECRET_KEY`.

If you restore Postgres without the matching key, most product data comes back, but encrypted credentials must be re-supplied. Store and back up the key with the same care as the database.

## JWT secret vs encryption key

`JWT_SECRET` and `QODECLAW_SECRET_KEY` are different and should not share a value.

| Secret                | Used for                          | Rotation impact                                        |
| --------------------- | --------------------------------- | ------------------------------------------------------ |
| `JWT_SECRET`          | Signing sessions and OAuth state. | Users may need to log in again.                        |
| `QODECLAW_SECRET_KEY` | Decrypting stored credentials.    | Stored secrets must be re-entered unless re-encrypted. |

## Next steps

<CardGroup cols={2}>
  <Card title="Environment variables" icon="settings" href="/self-hosted-environment-variables">
    See where `QODECLAW_SECRET_KEY` is configured.
  </Card>

  <Card title="Single-container deploy" icon="box" href="/self-hosted-single-container">
    Add the key to a Docker deployment.
  </Card>

  <Card title="Storage backends" icon="hard-drive" href="/self-hosted-storage-backends">
    Understand artifact storage separately from secrets.
  </Card>

  <Card title="AWS Terraform reference" icon="cloud" href="/self-hosted-aws-terraform">
    Inject secrets into a production ECS task.
  </Card>
</CardGroup>
