---
id: certificates
sidebar_position: 320
title: Certificates
---

# Certificates
<!-- SPDX-License-Identifier: CC-BY-4.0 -->

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**](#operator-managed-mode) – Certificates are internally
   managed by the operator in a fully automated way and signed using a CA created
   by CloudNativePG.
2. [**User provided**](#user-provided-certificates-mode) – Certificates are
   generated outside the operator and imported in the cluster definition as
   secrets. CloudNativePG integrates itself with [cert-manager](https://cert-manager.io/)
   (See [Cert-manager example](#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](operator_conf.md).
:::

:::info[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.
:::

When generating certificates, the operator assumes that the Kubernetes
cluster's DNS zone is set to `cluster.local` by default. This behavior can be
customized by setting the `KUBERNETES_CLUSTER_DOMAIN` environment variable. A
convenient alternative is to use the [operator's configuration capability](operator_conf.md).

### 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](https://cert-manager.io/).
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:

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

Create a secret with the TLS certificate:

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

Create a PostgreSQL cluster referencing those secrets:

```bash
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](https://cert-manager.io/)
to set up a self-signed CA and generate the needed TLS server certificate:

```yaml
---
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:

```yaml
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](samples/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](https://cert-manager.io/) or
[HashiCorp vault](https://www.vaultproject.io/docs/secrets/pki). 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.
:::

#### Customizing the `streaming_replica` client certificate

In some environments, it may not be possible to generate a certificate with the
common name `streaming_replica` due to company policies or other security
concerns, such as a CA shared across multiple clusters. In such cases, the user
mapping feature can be used to allow authentication as the `streaming_replica`
user with certificates containing different common names.

To configure this setup, add a `pg_ident.conf` entry for the predefined map
named `cnpg_streaming_replica`.

For example, to enable `streaming_replica` authentication using a certificate
with the common name `streaming-replica.cnpg.svc.cluster.local`, add the
following to your cluster definition:

```yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cluster-example
spec:
  postgresql:
    pg_ident:
    - cnpg_streaming_replica streaming-replica.cnpg.svc.cluster.local streaming_replica
```

For further details on how `pg_ident.conf` is managed by the operator, see the
["PostgreSQL Configuration" page](postgresql_conf.md#the-pg_ident-section) in
the documentation.

#### Cert-manager example

This simple example shows how to use [cert-manager](https://cert-manager.io/)
to set up a self-signed CA and generate the needed TLS server certificate:

```yaml
---
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:

```yaml
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](samples/cluster-example-cert-manager.yaml)
deployment manifest.
