Certificates

CloudNativePG was designed to natively support TLS certificates. To set up a cluster, the operator requires:

  • A server certification authority (CA) certificate
  • A server TLS certificate signed by the server CA
  • A client CA certificate
  • A streaming replication client certificate generated by the client CA

Note

You can find all the secrets used by the cluster and their expiration dates in the cluster's status.

CloudNativePG is very flexible when it comes to TLS certificates. It primarily operates in two modes:

  1. Operator managed – Certificates are internally managed by the operator in a fully automated way and signed using a CA created by CloudNativePG.
  2. User provided – Certificates are generated outside the operator and imported in the cluster definition as secrets. CloudNativePG integrates itself with cert-manager (See Cert-manager example.)

You can also choose a hybrid approach, where only part of the certificates is generated outside CNPG.

Note

The operator and instances verify server certificates against the CA only, disregarding the DNS name. This approach is due to the typical absence of DNS names in user-provided certificates for the <cluster>-rw service used for communication within the cluster.

Operator-Managed Mode

By default, the operator automatically generates a single Certificate Authority (CA) to issue both client and server certificates. These certificates are managed continuously by the operator, with automatic renewal 7 days before expiration (within a 90-day validity period).

Info

You can adjust this default behavior by configuring the CERTIFICATE_DURATION and EXPIRING_CHECK_THRESHOLD environment variables. For detailed guidance, refer to the Operator Configuration.

Important

Certificate renewal does not cause any downtime for the PostgreSQL server, as a simple reload operation is sufficient. However, any user-managed certificates not controlled by CloudNativePG must be re-issued following the renewal process.

Server certificates

Server CA secret

The operator generates a self-signed CA and stores it in a generic secret containing the following keys:

  • ca.crt – CA certificate used to validate the server certificate, used as sslrootcert in clients' connection strings.
  • ca.key – The key used to sign the server SSL certificate automatically.

Server TLS secret

The operator uses the generated self-signed CA to sign a server TLS certificate. It's stored in a secret of type kubernetes.io/tls and configured to be used as ssl_cert_file and ssl_key_file by the instances. This approach enables clients to verify their identity and connect securely.

Server alternative DNS names

In addition to the default ones, you can specify DNS server alternative names as part of the generated server TLS secret.

Client certificates

Client CA secret

By default, the same self-signed CA as the server CA is used. The public part is passed as ssl_ca_file to all the instances so it can verify client certificates it signed. The private key is stored in the same secret and used to sign client certificates generated by the kubectl cnpg plugin.

Client streaming_replica certificate

The operator uses the generated self-signed CA to sign a client certificate for the user streaming_replica, storing it in a secret of type kubernetes.io/tls. To allow secure connection to the primary instance, this certificate is passed as sslcert and sslkey in the replicas' connection strings.

User-provided certificates mode

Server certificates

If required, you can also provide the two server certificates, generating them using a separate component such as cert-manager. To use a custom server TLS certificate for a cluster, you must specify the following parameters:

  • serverTLSSecret – The name of a secret of type kubernetes.io/tls containing the server TLS certificate. It must contain both the standard tls.crt and tls.key keys.
  • serverCASecret – The name of a secret containing the ca.crt key.

Note

The operator still creates and manages the two secrets related to client certificates.

Note

The operator and instances verify server certificates against the CA only, disregarding the DNS name. This approach is due to the typical absence of DNS names in user-provided certificates for the <cluster>-rw service used for communication within the cluster.

Note

If you want ConfigMaps and secrets to be reloaded by instances, you can add a label with the key cnpg.io/reload to it. Otherwise you must reload the instances using the kubectl cnpg reload subcommand.

Example

Given the following files:

  • server-ca.crt – The certificate of the CA that signed the server TLS certificate.
  • server.crt– The certificate of the server TLS certificate.
  • server.key – The private key of the server TLS certificate.

Create a secret containing the CA certificate:

kubectl create secret generic my-postgresql-server-ca \
  --from-file=ca.crt=./server-ca.crt

Create a secret with the TLS certificate:

kubectl create secret tls my-postgresql-server \
  --cert=./server.crt --key=./server.key

Create a PostgreSQL cluster referencing those secrets:

kubectl apply -f - <<EOF
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cluster-example
spec:
  instances: 3
  certificates:
    serverCASecret: my-postgresql-server-ca
    serverTLSSecret: my-postgresql-server
  storage:
    storageClass: standard
    size: 1Gi
EOF

The new cluster uses the provided server certificates for TLS connections.

Cert-manager example

This simple example shows how to use cert-manager to set up a self-signed CA and generate the needed TLS server certificate:

---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: selfsigned-issuer
spec:
  selfSigned: {}
---
apiVersion: v1
kind: Secret
metadata:
  name: my-postgres-server-cert
  labels:
    cnpg.io/reload: ""
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: my-postgres-server-cert
spec:
  secretName: my-postgres-server-cert
  usages:
    - server auth
  dnsNames:
    - cluster-example-lb.internal.mydomain.net
    - cluster-example-rw
    - cluster-example-rw.default
    - cluster-example-rw.default.svc
    - cluster-example-r
    - cluster-example-r.default
    - cluster-example-r.default.svc
    - cluster-example-ro
    - cluster-example-ro.default
    - cluster-example-ro.default.svc
  issuerRef:
    name: selfsigned-issuer
    kind: Issuer
    group: cert-manager.io

Cert-manager creates a secret named my-postgres-server-cert. It contains all the needed files and can be referenced from a cluster as follows:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cluster-example
spec:
  instances: 3
  certificates:
    serverTLSSecret: my-postgres-server-cert
    serverCASecret: my-postgres-server-cert
  storage:
    size: 1Gi

You can find a complete example using cert-manager to manage both server and client CA and certificates in the cluster-example-cert-manager.yaml deployment manifest.

Client certificate

If required, you can also provide the two client certificates, generating them using a separate component such as cert-manager or HashiCorp vault. To use a custom CA to verify client certificates for a cluster, you must specify the following parameters:

  • replicationTLSSecret – The name of a secret of type kubernetes.io/tls containing the client certificate for user streaming_replica. It must contain both the standard tls.crt and tls.key keys.
  • clientCASecret– The name of a secret containing the ca.crt key of the CA to use to verify client certificate.

Note

The operator still creates and manages the two secrets related to server certificates.

Note

As the cluster isn't in control of the client CA secret key, you can no longer generate client certificates using kubectl cnpg certificate.

Note

If you want ConfigMaps and secrets to be automatically reloaded by instances, you can add a label with the key cnpg.io/reload to it. Otherwise, you must reload the instances using the kubectl cnpg reload subcommand.

Cert-manager example

This simple example shows how to use cert-manager to set up a self-signed CA and generate the needed TLS server certificate:

---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: selfsigned-issuer
spec:
  selfSigned: {}
---
apiVersion: v1
kind: Secret
metadata:
  name: my-postgres-client-cert
  labels:
    cnpg.io/reload: ""
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: my-postgres-client-cert
spec:
  secretName: my-postgres-client-cert
  usages:
    - client auth
  commonName: streaming_replica
  issuerRef:
    name: selfsigned-issuer
    kind: Issuer
    group: cert-manager.io

Cert-manager creates a secret named my-postgres-client-cert that contains all the needed files. You can reference it from a cluster as follows:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cluster-example
spec:
  instances: 3
  certificates:
    clientCASecret: my-postgres-client-cert
    replicationTLSSecret: my-postgres-client-cert
  storage:
    size: 1Gi

You can find a complete example using cert-manager to manage both server and client CA and certificates in the cluster-example-cert-manager.yaml deployment manifest.