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

# Secrets providers

> Resolve DNS provider credentials referenced by policy profiles from env vars, files, Vault, or OpenBao.

The broker resolves the `acme.credentials` string on each policy profile through a pluggable secrets provider. The provider is selected with `secrets.provider` in `broker.yml`.

| Provider  | When to use                                                                           |
| --------- | ------------------------------------------------------------------------------------- |
| `env`     | Single broker, credentials supplied via environment variables.                        |
| `file`    | Credentials live on the broker's filesystem (e.g. a sealed file rendered by Ansible). |
| `vault`   | HashiCorp Vault KV.                                                                   |
| `openbao` | OpenBao KV (same wire protocol as Vault).                                             |

## `env` (default)

```yaml theme={null}
secrets:
  provider: env
```

The `acme.credentials` string in a profile is treated as an environment variable name. Set it before starting the broker:

```bash theme={null}
CLOUDFLARE_DNS_API_TOKEN=... certplane-broker -c /etc/certplane/broker.yml serve
```

Under systemd:

```ini /etc/systemd/system/certplane-broker.service.d/env.conf theme={null}
[Service]
Environment=CLOUDFLARE_DNS_API_TOKEN=cf-token-here
```

## `file`

```yaml theme={null}
secrets:
  provider: file
```

The `acme.credentials` string is interpreted as a filesystem path. The broker reads the file, trims whitespace, and uses the contents as the secret. Files must be readable by the `certplane` user.

```bash theme={null}
install -m 0600 -o certplane -g certplane cf.token /etc/certplane/secrets/cloudflare
```

```yaml policy.yml theme={null}
profiles:
  public_edge_main:
    type: wildcard
    dns_names: ["*.example.com"]
    acme:
      challenge: dns-01
      credentials: /etc/certplane/secrets/cloudflare
```

## `vault` / `openbao`

```yaml theme={null}
secrets:
  provider: vault         # or openbao
  vault:
    address: https://vault.int.example.com:8200
    token_file: /etc/certplane/vault-token
    mount_path: secret
    kv_version: 2
    key: value
    timeout: 10s
    namespace: ""
```

| Field        | Default  | Notes                                               |
| ------------ | -------- | --------------------------------------------------- |
| `address`    | —        | **Required** when provider is `vault` or `openbao`. |
| `token`      | —        | Inline token. Avoid in production.                  |
| `token_file` | —        | Path containing the Vault token. Preferred.         |
| `mount_path` | `secret` | KV engine mount.                                    |
| `kv_version` | `2`      | `1` or `2`.                                         |
| `key`        | `value`  | The key inside the secret JSON to read.             |
| `timeout`    | `10s`    |                                                     |
| `namespace`  | —        | Vault Enterprise only.                              |

The `acme.credentials` value names the Vault path **relative to `mount_path`**. For example, with `mount_path: secret` and `kv_version: 2`:

```yaml policy.yml theme={null}
profiles:
  public_edge_main:
    type: wildcard
    dns_names: ["*.example.com"]
    acme:
      challenge: dns-01
      credentials: certplane/cloudflare/example-com
```

…reads `secret/data/certplane/cloudflare/example-com` and returns the value at `data.value` (or whatever `vault.key` is set to).

End-to-end walkthrough: [Vault and OpenBao secrets](/guides/vault-secrets).

## Choosing a provider

* **Just bringing up the broker?** Use `env`. Two seconds to set up.
* **Production single-broker?** `file` is fine if you already render secrets via your config management tool.
* **Multi-broker or centralized secret rotation?** `vault` or `openbao`. Tokens can be short-lived and rotated independently of the broker process.
