PKI & Certificates
Cacophony uses a file-based PKI for mutual TLS authentication between cluster nodes. Certificate management is explicit and automatable.
PKI File Layout
$CACOPHONY_DIR/
pki/
ca.pem # Cluster certificate authority
nodes/
localhost.crt # Node certificate
localhost.key # Node private key
worker-1.crt
worker-1.key
Certificate Commands
Initialize CA
# Create the cluster CA if it does not exist
caco cert init
Creates $CACOPHONY_DIR/pki/ca.pem and associated private key. Safe to run repeatedly — does not overwrite an existing CA.
Issue Node Certificate
# Issue or rotate a certificate for a specific node
caco cert issue --node localhost
caco cert issue --node worker-1
Creates <node>.crt and <node>.key under $CACOPHONY_DIR/pki/nodes/. The certificate subject/SAN matches the configured host for that node.
Both direct issuance and CSR bootstrap include the CA's authority key identifier for strict X.509 clients, including Python 3.13's default verifier. This does not retroactively modify existing certificates. Reissue and distribute an older leaf through the normal PKI workflow if a client rejects its missing authority key identifier; do not disable certificate verification.
Distribute Certificates
# Copy CA and node cert to a remote node via SSH
caco cert distribute --node worker-1
Uses the SSH configuration from the node's config entry to copy PKI material to the target machine. Requires SSH access to be configured.
Check Certificate Status
# Validate file presence and expiry
caco cert status
Reports on the presence and validity of the CA, node certificates, and their expiration dates.
Run Certificate Authority Service
caco cert serve
Run the certificate authority and bootstrap HTTPS service in the foreground. Useful for dedicated authority deploys where the full daemon is not needed. A CA-only role running caco cert serve will not answer ordinary daemon health probes; mark that as an expected health annotation when bootstrap HTTPS is the intended service surface.
Pull Certificates from Authority
caco cert pull
Pull certificates from the PKI authority node. Used on secondary nodes to obtain cert material when the authority has already issued it, without needing SSH-based distribution.
Multi-Node Setup
- Run
caco cert initonce on the bootstrap node to create the cluster CA - Run
NODE="worker-1"; caco cert issue --node "$NODE"for each node - Run
NODE="worker-1"; caco cert distribute --node "$NODE"to copy certs to remote nodes - Verify with
caco cert statuson each node
Fresh secondary nodes must not auto-create a new cluster CA locally. They must join the existing cluster trust domain by receiving ca.pem plus their node-specific certificate and key from the bootstrap authority, or by equivalent pre-provisioned PKI files.
config.yaml, the entire PKI lifecycle can be automated in scripts or CI.
Bootstrap exposure is configurable: pki.bootstrap.exposure: tailnet_direct serves the HTTPS authority directly on its bind_port without Tailscale Funnel; use funnel only for intentional public exposure. Daemonless identities in client_nodes get cert material via caco cert issue --node <client-node> / cert pull and stay in the cluster CA trust domain with identity_kind: client_node diagnostics, without becoming daemon peers.
TLS Configuration
Node TLS paths are specified in the config under each node entry:
nodes:
- name: localhost
host: localhost
tls:
cert: $HOME/.cacophony/pki/nodes/localhost.crt
key: $HOME/.cacophony/pki/nodes/localhost.key
caco config validate verifies that TLS file paths exist when cluster listeners are enabled.