> ## 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.

# Broker configuration

> Complete reference for broker.yml — every field, default, and constraint.

This page documents every field in `broker.yml`. The authoritative source is [`schemas/broker.schema.json`](https://github.com/TaconeoMental/Certplane/blob/main/schemas/broker.schema.json). Most editors (VS Code, JetBrains) will load it automatically if you reference the schema with a YAML `# yaml-language-server: $schema=...` comment or via your editor's schema mapping.

Required top-level keys: `server`, `policy`, `issuer`.

## `server`

```yaml theme={null}
server:
  address: "0.0.0.0:8443"
  tls:
    cert: /etc/certplane/tls/broker.crt
    key:  /etc/certplane/tls/broker.key
    min_version: "1.2"
  mtls:
    agent_ca_bundle: /etc/certplane/ca/agent-identity-ca-bundle.crt
  read_header_timeout: 5s
  read_timeout: 10s
  write_timeout: 60s
  idle_timeout: 120s
```

| Field                  | Type               | Default | Notes                                                               |
| ---------------------- | ------------------ | ------- | ------------------------------------------------------------------- |
| `address`              | string             | `:8443` | Listen address.                                                     |
| `tls.cert`             | string             | —       | **Required.** Path to PEM server certificate.                       |
| `tls.key`              | string             | —       | **Required.** Path to PEM server key.                               |
| `tls.min_version`      | enum: `1.2`, `1.3` | `1.2`   | Minimum TLS version.                                                |
| `mtls.agent_ca_bundle` | string             | —       | **Required.** CA bundle used to verify agent identity certificates. |
| `read_header_timeout`  | duration           | `5s`    |                                                                     |
| `read_timeout`         | duration           | `10s`   |                                                                     |
| `write_timeout`        | duration           | `60s`   |                                                                     |
| `idle_timeout`         | duration           | `120s`  |                                                                     |

`address` accepts any Go `net.Listen` syntax. Use `:8443` to bind all interfaces; use `127.0.0.1:8443` and front with a reverse proxy if you need a custom termination model — keep in mind the broker requires mTLS on the connection that reaches it.

## `policy`

```yaml theme={null}
policy:
  path: /etc/certplane/policy.yml
  watch: true
```

| Field   | Type   | Default | Notes                                              |
| ------- | ------ | ------- | -------------------------------------------------- |
| `path`  | string | —       | **Required.** Policy YAML file.                    |
| `watch` | bool   | `false` | Reload the policy on disk changes without restart. |

The schema and semantics are in [Policy overview](/policy/overview).

## `issuer`

Currently `acme` is the only provider.

```yaml theme={null}
issuer:
  provider: acme
  acme:
    directory_url: https://acme-v02.api.letsencrypt.org/directory
    account_email: admin@example.com
    account_key: /var/lib/certplane/acme/account.key
    dns_provider: cloudflare
    preferred_chain: "ISRG Root X1"
```

| Field                  | Type                          | Default | Notes                                                                                                            |
| ---------------------- | ----------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------- |
| `provider`             | enum: `acme`                  | `acme`  |                                                                                                                  |
| `acme.directory_url`   | string                        | —       | **Required.** Use the staging directory while testing: `https://acme-staging-v02.api.letsencrypt.org/directory`. |
| `acme.account_email`   | string                        | —       | **Required.**                                                                                                    |
| `acme.account_key`     | string                        | —       | **Required.** Path to ACME account private key. Created by the broker on first run if missing.                   |
| `acme.dns_provider`    | enum: `cloudflare`, `httpreq` | —       | **Required.** DNS provider used for `dns-01` challenges.                                                         |
| `acme.preferred_chain` | string                        | —       | Optional; defaults to the CA's preferred chain.                                                                  |

DNS provider credentials are resolved through `secrets` — see below and [Let's Encrypt + dns-01](/guides/lets-encrypt-dns).

## `secrets`

```yaml theme={null}
secrets:
  provider: env       # env | file | vault | 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              | Type                                    | Default  | Notes                                             |
| ------------------ | --------------------------------------- | -------- | ------------------------------------------------- |
| `provider`         | enum: `env`, `file`, `vault`, `openbao` | `env`    |                                                   |
| `vault.address`    | string                                  | —        | Required when `provider` is `vault` or `openbao`. |
| `vault.token`      | string                                  | —        | Inline token. Prefer `token_file`.                |
| `vault.token_file` | string                                  | —        | Path containing the Vault token.                  |
| `vault.mount_path` | string                                  | `secret` | KV engine mount.                                  |
| `vault.kv_version` | enum: `1`, `2`                          | `2`      |                                                   |
| `vault.key`        | string                                  | `value`  | Key inside the secret to read.                    |
| `vault.timeout`    | duration                                | `10s`    |                                                   |
| `vault.namespace`  | string                                  | —        | Vault Enterprise only.                            |

See [Vault and OpenBao secrets](/guides/vault-secrets) for the credential reference format.

## `store`

```yaml theme={null}
store:
  driver: sqlite              # sqlite | file
  path: /var/lib/certplane/broker.db
```

The store caches issued certificates (to avoid hitting Let's Encrypt rate limits) and audit events when audit is enabled.

| Field    | Type                   | Default                        | Notes                         |
| -------- | ---------------------- | ------------------------------ | ----------------------------- |
| `driver` | enum: `sqlite`, `file` | `sqlite`                       |                               |
| `path`   | string                 | `/var/lib/certplane/broker.db` | SQLite DB or JSON cache file. |

## `audit`

```yaml theme={null}
audit:
  enabled: true
  failure_mode: fail_open     # fail_open | fail_closed
  mirror_to_log: false
```

| Field           | Type | Default     | Notes                                                                                         |
| --------------- | ---- | ----------- | --------------------------------------------------------------------------------------------- |
| `enabled`       | bool | `true`      |                                                                                               |
| `failure_mode`  | enum | `fail_open` | If audit recording fails, `fail_closed` rejects the issuance request; `fail_open` permits it. |
| `mirror_to_log` | bool | `false`     | Also emit each audit event as a structured log line.                                          |

Inspect events with `certplane-broker -c <config> audit tail [--limit N]`.

## `rate_limits`

```yaml theme={null}
rate_limits:
  per_identity_per_hour: 50
  per_identity_profile_per_hour: 20
```

`0` disables the corresponding limit. Negative values are invalid.

## `logging`

```yaml theme={null}
logging:
  level: info        # debug | info | warn | error
  format: json       # text | json
  destination: stdout  # stdout | stderr
```

Broker defaults: `info`, `json`, `stdout`.

## Validation

`certplane-broker` rejects the config on startup if:

* Any required field is missing.
* `tls.min_version` is not `1.2` or `1.3`.
* An ACME field required by `provider: acme` is missing.
* `secrets.provider` is `vault`/`openbao` without `vault.address` or with an invalid `kv_version`.
* `store.driver` is not `sqlite` or `file`.
* `audit.failure_mode` is not `fail_open` or `fail_closed`.
* Either rate-limit value is negative.

Errors are accumulated and reported together so you can fix everything in one pass.
