Skip to main content
This document explains how Public Key Infrastructure (PKI) and mutual TLS (mTLS) work in ClickHouse Private: which certificates exist and why, what standards the configuration enforces, how certificates are verified, and how rotation is handled. It is the conceptual companion to the how-to guides for configuring Cert Manager and generating FIPS-compliant certificates.

Why PKI Matters Here

A ClickHouse Private cluster is a distributed system: ClickHouse Server replicas talk to each other and to ClickHouse Keeper, Keeper nodes form a Raft quorum among themselves, and the server makes outbound connections (for example to Keeper or to HTTPS-backed resources). In a regulated or air-gapped environment, every one of these hops is expected to be encrypted and, ideally, mutually authenticated so that only trusted components can join the cluster. TLS provides two distinct guarantees, and it is worth keeping them separate:
  • Encryption in transit — traffic cannot be read by an on-path observer. This only requires the server side to present a certificate.
  • Authentication — each side proves its identity with a certificate signed by a trusted CA. When both sides present and verify certificates, you have mutual TLS (mTLS).
ClickHouse Private supports both: you can run encryption-only TLS, or full mTLS, depending on the verificationMode and whether client certificates are configured. The sections below explain how those choices are expressed.

The Certificates and Their Purpose

ClickHouse Private uses a single common Certificate Authority (CA) and one leaf certificate per component: The server’s outbound (client) role is worth calling out, because TLS treats “server” and “client” as separate contexts. The Helm chart configures the OpenSSL <client> context — used when clickhouse-server connects out to another component — to present the same certificate and key as the inbound <server> context (server.openSSL.secret.certKey / keyKey, defaulting to server.crt / server.key). In other words, there is no separate “client” certificate in the standard Kubernetes deployment; the server certificate fills both roles.
The FIPS certificate-generation workflow additionally produces a dedicated client.crt / client.key and bundles them into the server secret. That is specific to that workflow (and the bare-metal deployment path); the Helm chart’s OpenSSL config points the client context at the server certificate by default. See Configure FIPS certificates.
A few important properties:
  • One CA, two leaf certificates. A single CA signs the server and keeper certificates. Any component can therefore validate any other component’s certificate by trusting just the CA.
  • A unique leaf certificate per cluster. The CA can be shared across clusters, but the server and keeper certificates must be generated per ClickHouse cluster, because their Subject Alternative Names (SANs) encode the cluster’s Kubernetes service names.

Subject Alternative Names (SANs)

Leaf certificates must carry the in-cluster DNS names of the services they front, or TLS hostname validation fails for intra-cluster traffic. The SAN patterns are:
  • Server: *.c-<cluster-name>-server-headless.ns-<cluster-name>.svc.cluster.local and c-<cluster-name>-server-any.ns-<cluster-name>.svc.cluster.local
  • Keeper: *.c-<cluster-name>-keeper-headless.ns-<cluster-name>.svc.cluster.local
If your Kubernetes cluster uses a domain other than .cluster.local, substitute it in the SANs.

How Certificates Are Delivered to ClickHouse

Certificates are delivered as Kubernetes secrets, which the ClickHouse Operator mounts into the pods as a projected volume:
  • /etc/clickhouse-server/certs/ for ClickHouse Server
  • /etc/clickhouse-keeper/certs/ for ClickHouse Keeper
Each file is mounted under the same name as its secret key (so the secret key server.crt becomes the file /etc/clickhouse-server/certs/server.crt). The onprem-clickhouse-cluster Helm chart expects these secrets by default: Both the secret name and the individual key names are configurable through Helm values (server.openSSL.secret.* and keeper.openSSL.secret.*), which is what makes the chart compatible with certificate-management tools that use different key names — most notably Cert Manager, which emits tls.crt / tls.key rather than server.crt / server.key.

What the Configuration Enforces

When TLS is enabled, the Helm chart renders an openSSL block for each component with a deliberately hardened baseline. The relevant settings, and what each enforces, are: These settings are applied to both the <server> and <client> halves of the OpenSSL configuration, because clickhouse-server is simultaneously a TLS server (to its clients) and a TLS client (to Keeper and other servers). For FIPS environments, the certificates themselves additionally have to be generated with FIPS-validated algorithms (for example RSA ≥ 3072-bit) in a FIPS-enabled module — see FIPS 140-3 Compliance.

enabled vs. required

Each component exposes two flags that look similar but mean different things:
  • openSSL.enabled turns the TLS configuration on and binds the secure ports, but leaves the insecure ports in place. This is the right setting while migrating: clients can move to TLS at their own pace.
  • openSSL.required goes further. In addition to enabling TLS, it removes the insecure ports (http_port and tcp_port are set to 0) so that only encrypted connections are possible. This is the hardened end-state for a production deployment.
Enabling either flag also makes the operator bind the secure readiness ports, so the cluster’s health checks run over TLS. Setting required additionally drops the insecure readiness listener, leaving only the TLS one.

How Certificates Are Verified: verificationMode

verificationMode is the single most important knob for the authentication half of TLS. It controls whether — and how strictly — a peer’s certificate is checked. It applies to both the server and client OpenSSL contexts, and the default is none. A few consequences worth internalizing:
  • none is encryption, not authentication. With none, an attacker who can reach the port cannot read the traffic, but ClickHouse will not check who is connecting. To get the “only trusted components may connect” property, you need relaxed (opportunistic) or strict (enforced).
  • mTLS requires a certificate on the connecting side too. Verification only does something if the connecting side actually presents a certificate. The server presents its own certificate on outbound connections (its OpenSSL <client> context), which is what lets server-to-Keeper and server-to-server traffic satisfy a peer that verifies certificates.
  • relaxed is the recommended enforcement mode today. strict mode is not currently recommended, as it can interact poorly with the operator; production deployments should use relaxed, which still validates every certificate that is presented.
These values are passed through to ClickHouse’s TLS configuration unchanged, so they behave exactly as documented for ClickHouse’s openSSL settings.

Certificate Rotation

Certificates expire, so rotation is an operational reality rather than an edge case. ClickHouse Private handles most of it transparently, with one important exception. In both cases, the ClickHouse Operator watches the certificate secret and reacts to changes — you do not rotate certificates by hand. The difference is in how each component adopts a new certificate: the server does it without a restart, while Keeper requires one.

ClickHouse Server: rotation without a restart

ClickHouse Server reads its certificate and key from disk and hot-reloads them when the files change — no pod restart required. The flow end to end is:
  1. The certificate authority (your PKI, or Cert Manager) issues a new certificate and updates the Kubernetes secret.
  2. Kubernetes propagates the new secret contents into the mounted volume inside the pod.
  3. The operator detects the new certificate in the secret and records it in the cluster’s status; ClickHouse Server picks up the new certificate from disk on its own.
Because of this, when you use Cert Manager with automatic renewal, server certificate rotation happens with no human intervention and no downtime.

ClickHouse Keeper: operator-triggered rolling restart

Keeper does not hot-reload its certificate the way the server does — its TLS configuration, including the secured Raft (inter-server) channel that Keeper nodes use to maintain quorum, is established at process startup. To adopt a new certificate, the Keeper pods must restart. This restart is still automated: when the certificate in the Keeper secret changes, the operator stamps the new expiry onto the Keeper StatefulSet’s pod template (the clickhouse.com/certificate-expire-date annotation), which triggers a rolling restart of the Keeper pods. So Keeper rotation, like server rotation, requires no manual step — but unlike the server it cycles the Keeper pods, which is briefly disruptive and should be expected during rotation. Practical implications:
  • Expect a rolling restart of the Keeper StatefulSet whenever the Keeper certificate is renewed. It is automatic, but it is not free the way server rotation is — schedule renewals with that in mind.
  • Keep CA validity long and rotate it rarely. Because every component trusts the CA, rotating the CA itself is the most disruptive operation and should be planned well ahead of expiry. The example tooling defaults the CA to a 10-year (3650-day) validity for exactly this reason, versus 365 days for leaf certificates.
  • Monitor leaf and CA expiry and alert with enough lead time that renewals (and the Keeper restart they trigger) happen before the certificate actually expires.

Integrating with Cert Manager

Cert Manager is the recommended way to run this PKI in production, because it automates issuance and renewal and slots cleanly into the rotation model above. Conceptually:
  • A Cert Manager Issuer or ClusterIssuer plays the role of your CA. This can be a self-signed issuer (for testing), an intermediate backed by your corporate root, or an external CA via ACME or Vault.
  • A Certificate resource per component declares the SANs and the target secret name. Cert Manager generates the key pair and writes ca.crt, tls.crt, and tls.key into that secret.
  • The Helm chart is pointed at those key names (caKey: ca.crt, certKey: tls.crt, keyKey: tls.key), and the operator mounts and reloads them as described above.
  • Cert Manager renews certificates before expiry automatically. Server certificates then rotate with zero downtime; renewing the Keeper certificate triggers an automatic rolling restart of the Keeper pods, as described in the rotation section above.
One caveat: ca.crt is only populated in the secret when the issuer can supply it. ACME issuers, for instance, do not include a ca.crt. In that case, add the public root to the ca.crt key yourself, or use trust-manager to build a CA bundle and target the secret. For step-by-step instructions, see Configure Cert Manager for ClickHouse Certificates.

Choosing a Posture

Bringing the pieces together, a typical progression looks like this:
  1. Encryption first. Set openSSL.enabled: true with verificationMode: none. Traffic is encrypted; insecure ports remain for a smooth migration.
  2. Opportunistic mTLS. Move to verificationMode: relaxed once all components present client certificates. Authentication is now validated where present, without breaking anything that hasn’t migrated.
  3. Enforced TLS. Set openSSL.required: true to drop the insecure ports entirely, so only encrypted connections are accepted. Keep verificationMode: relaxed, which remains the recommended mode (see the note above on strict).
At every step, the certificates, SANs, secret layout, and rotation behaviour are the same — only the enforcement flags change.

Further Reading

Last modified on August 7, 2026