Skip to main content

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.

Certplane has no web UI and no runtime API for changing certificate policy or agent configuration. Every piece of configuration the broker and agent consume is a plain YAML file on disk. This is deliberate: it lets you treat certificate policy the same way you treat the rest of your infrastructure — rendered from a single source of truth, reviewed in version control, and applied with the same automation you already use to manage your servers.

What this means in practice

There are three configuration files in a typical Certplane deployment, and each one is a natural fit for IaC:
FileWhere it livesWhat renders it
broker.ymlBroker host, e.g. /etc/certplane/broker.ymlYour config management tool, from broker-side variables
policy.ymlBroker host, e.g. /etc/certplane/policy.ymlYour config management tool, from a host/profile inventory
agent.ymlEach managed host, e.g. /etc/certplane/agent.ymlYour config management tool, from per-host facts
Because the broker can hot-reload policy.yml (see policy.watch), the entire lifecycle — add a host, grant it a new profile, rotate a DNS credential reference — can be driven by a single push to your IaC repo. A simple, scalable pattern is to keep all Certplane configuration under one directory in your IaC repository, rendered from inventory:
infrastructure/
├── inventory/
│   ├── hosts.yml                  # source of truth: hosts and their roles
│   └── certplane.yml              # profiles and host → profile mappings
├── templates/
│   ├── broker.yml.j2
│   ├── policy.yml.j2
│   └── agent.yml.j2
└── playbooks/
    ├── broker.yml
    └── agent.yml
The templates render broker.yml, policy.yml, and agent.yml from inventory variables. Your playbook (or equivalent) places the rendered files on the right hosts, restarts the broker if broker.yml changes, and signals a reload if policy.yml or agent.yml changes.

Rendering policy.yml from inventory

The policy file is the most common thing to render. Keep your profiles and host-to-profile mappings in inventory variables, then template policy.yml:
inventory/certplane.yml
certplane_profiles:
  public_edge_main:
    type: wildcard
    dns_names:
      - "*.example.com"
    acme:
      challenge: dns-01
      credentials: CLOUDFLARE_DNS_API_TOKEN
    renew_before: 720h

certplane_hosts:
  edge01:
    identity: edge01.h.int.example.com
    profiles:
      - public_edge_main
  edge02:
    identity: edge02.h.int.example.com
    profiles:
      - public_edge_main
templates/policy.yml.j2
version: 1

profiles:
{{ certplane_profiles | to_nice_yaml(indent=2) | indent(2, true) }}

hosts:
{{ certplane_hosts | to_nice_yaml(indent=2) | indent(2, true) }}
With policy.watch: true set in broker.yml, the broker reloads automatically the moment your IaC tool writes the new file. No broker restart, no agent restart, no downtime.

Keep secrets out of rendered files

The secrets provider (see Secrets) is what makes the IaC-first model safe. Your rendered broker.yml and policy.yml only contain secret references — environment variable names, file paths, or Vault paths — never the secret values themselves. That means the rendered files are safe to commit to version control, diff in code review, and ship through your normal pipeline. The actual secret values are injected at runtime by whichever secrets provider you configure (env, file, vault, or openbao).

Custom Ansible roles (coming soon)

Official, opinionated Ansible roles for installing and configuring the broker and agent are on the way. They will cover:
  • Installing the certplane-broker and certplane-agent binaries
  • Rendering broker.yml, policy.yml, and agent.yml from inventory variables
  • Managing systemd units and handlers (reload on policy change, restart on config change)
  • Bootstrapping new hosts: token generation on step-ca, copying it to the target host, and triggering certplane-agent enroll
Until the official roles are published, the patterns on this page describe everything you need to roll your own equivalent with Ansible, Salt, Chef, Puppet, or any other config management tool.

Bootstrapping new hosts in your pipeline

Enrollment is the one part of the Certplane lifecycle that requires a short-lived secret (the bootstrap token). The recommended pattern in an IaC pipeline is:
1

Add the host to inventory

Append the new host to inventory/hosts.yml and add an entry under certplane_hosts with its identity CN and allowed profiles. Commit the change.
2

Render and ship policy.yml

Your IaC tool re-renders policy.yml and writes it to the broker host. With policy.watch: true, the broker picks up the new host registration immediately.
3

Generate a bootstrap token on step-ca

From your IaC controller, run step ca token <identity-cn> against your step-ca instance. The token is single-use and short-lived.
4

Place the token on the new host

Copy the token to the path referenced by identity.bootstrap_token in the host’s agent.yml, then render and ship agent.yml.
5

Run enrollment

Invoke certplane-agent enroll --config /etc/certplane/agent.yml on the host as part of the same play. After enrollment, start the renewal loop with certplane-agent run under systemd.
After the first successful enrollment, the bootstrap token is consumed and the host needs no further secrets — the identity certificate it just received is what authenticates every subsequent broker call.

Drift detection

Because every effective change goes through your IaC tool, drift detection is straightforward: re-run the playbook in check mode. Any host whose agent.yml, broker host’s broker.yml, or rendered policy.yml differs from what your inventory describes will show up as a diff. The broker itself enforces policy on every request, so even if a rendered file somehow drifts, an agent cannot request anything the canonical inventory does not allow.

Next steps