Show examples as

Certificates and encryption

kcore uses mutual TLS (mTLS) for all management-plane communication. Disk encryption with LUKS2 protects data at rest.

PKI hierarchy

mTLS bootstrap

kctl create cluster generates the full PKI (root CA, sub-CA, controller cert, kctl client cert). kctl node install pushes the node certificate, private key, and CA chain to the target node. Controller nodes also receive the sub-CA key pair.

Automated certificate rotation

The controller checks its certificate inventory every hour and rotates any node certificate that has entered its renewal window — by default the last 30 days, or the last quarter of the certificate's lifetime, whichever comes first. Certificates are signed for 365 days.

Rotation is driven by the controller but the key material is not. The controller calls RotateNodeCert on the node, the node generates a fresh keypair and sends a CSR to SignNodeCsr, and the sub-CA returns a signed chain. Private keys never leave the node.

The node writes the new certificate and key atomically, then reloads TLS without restarting the process. Established gRPC connections drop and callers reconnect; in-memory state is kept. If the new certificate fails verification, the node rolls back and carries on serving with its old, still-valid certificate.

Manual rotation

# Rotate the sub-CA
kctl rotate sub-ca --certs-dir ~/.kcore/<context>/

# Re-sign the controller cert and trigger TLS reload
kctl rotate certs --controller <host:port> --certs-dir ~/.kcore/<context>/

# Rotate one node, or every approved node, ahead of schedule
kctl rotate node-certs --node <node-id>
kctl rotate node-certs --all

Rotation and revocation stay kctl commands. Provider 0.5.0 can issue an operator certificate.

resource "kcore_operator" "ci" {
  name       = "ci"
  roles      = ["vm-admin"]
  issue_cert = true
}

rotate sub-ca generates a new sub-CA and pushes it to the controller. rotate certs re-signs the controller certificate and triggers ReloadTls on the controller. rotate node-certs runs the CSR flow above immediately instead of waiting for the renewal window.

Revocation: CRL and OCSP

Every certificate the controller signs is recorded in an inventory: serial, subject, node, validity window, SHA-256 fingerprint, and status. Revoking one marks it in that inventory and publishes it through both a CRL and an OCSP responder.

# Revoke by serial, subject CN, or node
kctl revoke cert --serial <hex> --reason key-compromise
kctl revoke cert --node <node-id>

# Fetch the current CRL
kctl get crl -o crl.der

kctl node delete <node-id> revokes every certificate issued to that node before the node row is removed. The reason code is RFC 5280 reason 5, cessation of operation. Delete refuses while the node still hosts a VM, a workload, or a network. Revoking with kctl revoke cert --node leaves the node in the cluster.

The CRL is signed by the sub-CA and carries thisUpdate and nextUpdate; it is valid for 24 hours and regenerated when the revocation set changes or nextUpdate gets close. --reason accepts the RFC 5280 reason codes, such as key-compromise, superseded, or privilege-withdrawn.

Revocation is enforced above TLS, not inside the handshake: a revoked peer completes the TLS handshake and is then rejected with PermissionDenied before any RPC handler runs. No call succeeds with a revoked certificate. Checks run against a snapshot that refreshes every 60 seconds. When that snapshot goes stale the controller soft-fails by default, so a revocation outage cannot lock every node out of the cluster; set revocation.failMode to hard-fail if you would rather reject peers than serve on stale data.

OCSP stapling is not supported. The controller runs an OCSP responder and nodes query it directly, as a fallback when CRL data is stale — no stapled response is attached to a kcore handshake.

PKI endpoints

The controller serves the CRL and OCSP over plain HTTP on pki.httpListenAddr, by default 0.0.0.0:9092. These objects are signed, so they do not need transport security, and a node whose certificate has just expired can still fetch what it needs to recover.

Set pki.httpEnabled: false to turn the listener off. Nodes fall back to the gRPC GetCrl call either way.

Inspecting certificates

kctl get nodes shows cert_expiry_days per node. kctl get certificates lists the controller's inventory, filterable with --node, --status, and --expiring-within-days. kctl get pki-status summarises rotation and revocation health. The compliance report includes a Certificate Lifecycle section with expiring and unknown certificate counts.

LUKS2 disk encryption

LUKS2 encryption is mandatory for the OS disk on every node.

LUKS reporting

The node-agent detects the LUKS unlock method at registration: tpm2 if /dev/mapper/cryptroot exists and a TPM device is present, key-file otherwise. kctl get compliance-report shows the cluster-wide LUKS breakdown by method.

TLS configuration

Never use --insecure in production. Disabling mTLS removes authentication and encryption from the management plane.