# Secrets

Encrypted secrets that are injected into your deployments at runtime.

Secrets let you store sensitive values (API keys, database URLs, tokens) on the server. They’re encrypted at rest, never logged, and injected as environment variables when your container starts.

## Managing secrets

```bash
# Create or update a secret
berth secret set STRIPE_KEY sk_live_abc123 --description "Stripe API key"

# List secrets (shows names and descriptions, never values)
berth secret list

# Delete a secret
berth secret delete STRIPE_KEY
```

The `--description` flag is optional but recommended — it helps you (and AI tools) understand what each secret is for without exposing the value.

## Using secrets in deployments

Reference secrets by name when deploying:

```bash
# Single secret
berth deploy --secret STRIPE_KEY

# Multiple secrets
berth deploy --secret STRIPE_KEY --secret DATABASE_URL

# Combine with inline env vars
berth deploy --secret STRIPE_KEY --env NODE_ENV=production
```

Secrets are resolved at container creation time. Your app reads them like any other environment variable:

```javascript
const stripe = require('stripe')(process.env.STRIPE_KEY)
```

If the same name appears in both `--secret` and `--env`, the explicit `--env` value takes precedence.

## Secret rotation

When you update a secret that’s in use by running deployments, OpenBerth automatically restarts those deployments with the new value:

```bash
$ berth secret set STRIPE_KEY sk_live_new_value
  ✓ Secret updated
  ↻ Restarted: my-app, checkout-api
```

This is a runtime-only restart (~5 seconds) — no rebuild required. The container is recreated with the updated secret value.

## Global secrets

Admins can create global secrets that are available to all users on the server:

```bash
# Create a global secret (admin only)
berth secret set SHARED_API_KEY abc123 --global

# Delete a global secret
berth secret delete SHARED_API_KEY --global
```

When a user has both a personal and global secret with the same name, the personal secret takes precedence.

## How encryption works

Secrets use **AES-256-GCM envelope encryption**:

1. A master key is auto-generated when the server first starts and saved in `config.json`
2. Each secret gets its own random data encryption key (DEK)
3. The DEK encrypts the secret value, then the master key encrypts the DEK
4. Both encrypted values are stored in SQLite — the plaintext value is never persisted

Secret values are decrypted only at the moment a container is created, and injected as environment variables. They never appear in `berth secret list`, logs, or API responses.

## MCP tools

AI tools can manage secrets through MCP:

| Tool                | Description                                                   |
|---------------------|---------------------------------------------------------------|
| `berth_secret_set`  | Create or update a secret                                     |
| `berth_secret_list` | List secret names and descriptions (never values)            |
| `berth_secret_delete`| Delete a secret                                             |

The `berth_secret_list` tool returns descriptions so AI tools can discover which secrets are available without seeing the values.
