---
title: "Secrets"
description: "Store API keys, passwords and other credentials once, deliver them to clusters, services, devboxes and agents by identity, and rotate them without downtime."
url: https://frazer.ai/docs/secrets
index: https://frazer.ai/docs/llms.txt
tokens: 3299
---

> For agents: this page is indexed at https://frazer.ai/docs/llms.txt, and every page at https://frazer.ai/llms.txt. Copy commands from this file exactly.

# Secrets

Secrets stores your API keys, passwords and other credentials in Frazer Secrets, run by Frazer in each region outside your clusters. People add values and see metadata; clusters, serverless services, devboxes and agents read values with their own identity, and every read is on the record. Rotation keeps two versions valid until every consumer has moved.

Product overview: [Secrets](https://frazer.ai/secrets).

## How it works

A secret has an ID (`stripe-secret-key`), the environment key your code reads (`STRIPE_SECRET_KEY`), a folder (`/payments`), a kind, labels, aliases and a rotation schedule. Each new value is a version with its author, the time and the reason given. Versions are enabled, disabled or destroyed; a disabled version can be enabled again.

Values live in a namespace of their own per project. Snapshots are taken every 5 minutes and copied to Frazer Storage and off-site. No other cloud’s secret manager sits behind a Frazer secret.

-   **Alias**: a name such as `prod` that points at a version. Consumers follow the alias, so moving it rolls out a new value.
-   **Where used**: every cluster, service, devbox and agent that reads a secret, with the version it holds.
-   **Rotator**: who makes the next version: `frazer` for credentials Frazer issues, `notify` to remind the secret’s owners, or `job` for a serverless job that runs your own rotate handler.

| Kind | Written by | Rotation | Example |
| --- | --- | --- | --- |
| Opaque | People, CI or an import | On a schedule, with a reminder to the owners | `STRIPE_SECRET_KEY` |
| Managed | Frazer, for a Frazer resource | Frazer rotates it; two valid versions overlap | The app user of a managed Postgres, a Valkey ACL user, an LLM gateway key |
| Dynamic | Created on each read | A lease: 1 hour by default, 24 hours at most | A Postgres role for an analyst or an agent session |
| Derived | Frazer, from a template with references | Whenever a referenced secret changes | `DATABASE_URL` |
| Certificate | Frazer’s certificate authority | Before it expires | mTLS client certificates |

A derived secret is a template whose references Frazer fills in, so `DATABASE_URL` follows its password through every rotation:

```text title="DATABASE_URL (derived)"
postgres://app:${secret:db/acme-ledger/app}@ledger.db.acme-production.internal/ledger
```

## Create a secret

### CLI

1.  Create the secret with its folder, environment key and rotation period.
    
    ```sh
    frazer secrets create stripe-secret-key --folder /payments \
      --key STRIPE_SECRET_KEY --rotation 90d
    ```
    
2.  Add the first value. It is read from stdin, so it never lands in your shell history, and the reason is kept with the version.
    
    ```sh
    printf %s "$V" | frazer secrets versions add stripe-secret-key \
      --from-stdin --reason "rotated in Stripe"
    ```
    
3.  Point the `prod` alias at the version. Consumers that follow the alias get it.
    
    ```sh
    frazer secrets versions alias stripe-secret-key prod 7
    ```
    

### Console

1.  Open **Data › Secrets** and choose **New secret**.
    
2.  Give it an ID, an environment key, a folder and a rotation schedule.
    
3.  Add the value with a reason. The console never shows it again.
    

**Import** on the same page opens the import wizard instead.

Then deliver it. In your environment repository, point an `ExternalSecret` at the alias path. The cluster’s secret sync reads it with the cluster’s own identity, so no value enters Git.

```yaml title="envs/production/payments/stripe.yaml"
# envs/production/payments/stripe.yaml: no value in Git
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: payments-stripe
  namespace: payments
spec:
  secretStoreRef:
    kind: ClusterSecretStore
    name: frazer-secrets
  target:
    name: payments-stripe
  data:
    - secretKey: STRIPE_SECRET_KEY
      remoteRef:
        key: "@prod/payments/stripe-secret-key"   # follows the prod alias
```

Check who uses it: `frazer secrets where-used stripe-secret-key` lists every consumer and the version it holds.

## Deliver secrets to workloads

| Consumer | How it gets the value | Version |
| --- | --- | --- |
| Kubernetes cluster | An `ExternalSecret` in the environment repository, through the `ClusterSecretStore` named `frazer-secrets`, with the cluster’s own identity; a config reload restarts pods on change | Latest, an alias, or a pinned number |
| Workload without a Kubernetes Secret | A file mount through the Secrets Store CSI driver, opt-in | Latest or pinned |
| Serverless service | A binding from secret to variable | Pinned per revision; a new version starts a new revision |
| Devbox | References in the provisioning profile; short-lived credentials where the credential broker can mint them | Latest |
| Agent | Never a value in the sandbox: the egress gateway adds the credential for each allowed host | Latest |

A secret can also be shared from one project to chosen projects in the organization. The share grants read access to its versions, and reads are audited in both projects.

## Rotate a secret

1.  Set a schedule: a period of an hour or more, an overlap of 24 hours by default, and a rotator. With `notify`, the owners get an email and an Inbox item, and Frazer sends the `frazer.secret.rotate_due.v1` event to your webhooks.
    
2.  Add the new version. Frazer adds it for credentials it issues; for the rest, an owner adds the value with a reason.
    
    ```sh
    printf %s "$V" | frazer secrets versions add stripe-secret-key \
      --from-stdin --reason "rotated in Stripe"
    ```
    
3.  Move the alias. Clusters refresh, serverless services start a new revision, and the broker hands out the new value.
    
    ```sh
    frazer secrets versions alias stripe-secret-key prod 8
    ```
    
4.  Wait for **Where used** to show every consumer on the new version. A rotation that cannot finish keeps the old version valid and raises a finding.
    
5.  Frazer disables the old version after the overlap and destroys it after 7 days. Every read stays on the record.
    

Managed secrets rotate without you: Postgres app users, Valkey ACL users with two passwords, registry tokens, LLM keys and Frazer service account keys.

## Read a value

Values are write-only for people by default. No basic role reads them, owners and admins included, and workloads read only the secrets bound to them.

A person can read a value only with an explicit grant of the Secret Accessor permission, `secrets.versions.access`. Each read asks for a second factor and is audited. A project can require an approval for reads in production, or forbid human reads with a policy. With the grant, `frazer secrets run` starts a local command with the project’s secrets in its environment:

```sh
frazer secrets run --project acme-staging -- npm start
```

> **Note:** Agents never read values, with or without a grant. The secrets tools on MCP show metadata only, and the egress gateway adds a credential to an agent’s request for each allowed host.

## Import from another secret manager

The import wizard runs four steps: **Source** (a read-only credential and filters), **Select** (the secrets and their folders), **Dry run** (a plan of what is copied, skipped or in conflict, with the source’s egress estimate) and **Import** (progress per item with checksum verification).

-   Sources: Google Secret Manager, AWS Secrets Manager, Azure Key Vault, HashiCorp Vault, 1Password, Doppler and Infisical.
-   A `.env` file: upload it in the browser, where it is parsed on your machine, or run `frazer secrets import .env`.
-   The source is only read. Values pass from the import worker straight into Frazer Secrets and are never logged.
-   An import stays open for up to 30 days, so you can rerun a delta while you cut over; nothing keeps syncing after.
-   The import credential is kept in Frazer Secrets and deleted when the import closes.

The same wizard imports container images; see [Registry](https://frazer.ai/docs/registry#import-from-another-registry).

## Access and audit

| Role | Metadata | Add a version | Manage aliases, rotation, access |
| --- | --- | --- | --- |
| Owner, Admin | Yes | Yes | Yes |
| Developer, Infra admin | Yes | In non-production; production needs an admin or an approval | Developer: no |
| Viewer, Auditor | Yes | No | No |
| Workload identities | No | No | No; they read only the secrets bound to them |

-   Permissions: `secrets.secrets.get`, `list`, `create`, `update`, `delete` and `setIamPolicy`; `secrets.versions.add`, `enable`, `disable` and `destroy`; and `secrets.versions.access` for reading values.
-   Every read is an audit entry, counted per identity and hour, so “who read it” has an answer without a flood of rows.
-   Every version keeps its author and reason. Access changes, alias moves, disables and destroys are on the record.
-   An emergency read outside these grants is a two-person, recorded procedure.
-   Encryption keys and certificates live in the same namespaces but appear in [Security Center](https://frazer.ai/docs/security-center), not on the Secrets page.

## Limits and quotas

| Item | Default |
| --- | --- |
| Secrets per project | 10,000 |
| Value size | 64 KiB |
| Versions kept per secret | 100 |
| Reads per project | 100 a second, bursts to 500 |
| Rotation period | 1 hour or more |
| Rotation overlap | 24 hours |
| Destroy delay | 7 days after a version is disabled |
| Dynamic lease | 1 hour by default, 24 hours at most |
| Imports | 5 running per organization; each open for up to 30 days |

## Pricing

Secrets add nothing to a budget: there is no fee per secret, per version or per read. Imports have no Frazer fee; the source bills its own egress, which the dry run shows.

| Secrets | On your servers | On the Frazer fleet |
| --- | --- | --- |
| Price | No per-secret or per-access fee | No per-secret or per-access fee |

Every line, with the estimator: [pricing](https://frazer.ai/pricing#lines).

## Troubleshooting

| Symptom | Cause | Fix |
| --- | --- | --- |
| The console shows no value | Values are write-only for people | Let workloads read it; for local work, ask an admin for the Secret Accessor permission |
| A developer cannot add a version in production | Production needs an admin or an approval | Ask an admin, or request an approval |
| Pods still use the old value | The `ExternalSecret` pins a version number, or has not refreshed yet | Follow an alias path such as `@prod/…`; check the refresh with `where-used` |
| A rotation raised a finding | A consumer still holds the old version | Run `frazer secrets where-used` and update that consumer; the old version stays valid until then |
| A version is refused as too large | Values are limited to 64 KiB | Store large files in a [bucket](https://frazer.ai/docs/storage) and keep only the credential here |
| Reads fail with `RATE_LIMITED` | The project passed 100 reads a second | Lengthen refresh intervals or read once per process |
| An agent cannot see a value | Agents never hold values | Allow the host on the agent; the egress gateway adds the credential |

## Reference

### CLI

| Command | What it does |
| --- | --- |
| `frazer secrets create` | Create a secret with its folder, environment key and rotation schedule. |
| `frazer secrets versions add` | Add a version from stdin, with a reason. |
| `frazer secrets versions alias` | Point an alias such as prod at a version. |
| `frazer secrets where-used` | List every consumer of a secret and the version it holds. |
| `frazer secrets run` | Run a local command with a project's secrets in its environment (needs the Secret Accessor permission). |
| `frazer secrets import` | Import keys and values from a .env file. |

All of them: [CLI reference](https://frazer.ai/docs/cli).

### Terraform and OpenTofu

| Resource | What it manages |
| --- | --- |
| `frazer_secret` | A secret's metadata, folder, aliases and rotation; never its value. |
| `frazer_secret_version` | A secret version with a write-only value; as an ephemeral resource it reads a value without storing it in state. |

All of them: [Terraform and OpenTofu reference](https://frazer.ai/docs/terraform).

### Events

| Event type | When it is sent |
| --- | --- |
| `frazer.secret.rotate_due.v1` | A secret with the notify rotator is due for rotation. |

All of them: [Events reference](https://frazer.ai/docs/webhooks).

## Related

-   [Secrets product page](https://frazer.ai/secrets)
-   [Kubernetes](https://frazer.ai/docs/kubernetes) for the secret sync in your clusters
-   [Serverless](https://frazer.ai/docs/serverless) for bindings
-   [Databases](https://frazer.ai/docs/databases) for managed Postgres credentials
-   [Frazer Agents](https://frazer.ai/docs/agents) for credentials injected at the egress gateway
-   [Identity and access](https://frazer.ai/docs/iam) for roles and approvals

## Pages in Data

- [Databases](https://frazer.ai/docs/databases.md)
- [In-memory store](https://frazer.ai/docs/memory.md)
- [Frazer Storage](https://frazer.ai/docs/storage.md)
- [Secrets](https://frazer.ai/docs/secrets.md) (this page)
- [Volumes and snapshots](https://frazer.ai/docs/volumes.md)
