Mutual TLS Authentication for Postgres

Resources :

This article will show you how to secure your Postgres database connection.

Generate self-signed certificates

1. Create a Root CA with an EC Key

Generate an EC private key for the root CA

openssl ecparam -name prime256v1 -genkey -noout -out root.key

Alternatively, you can use the secp384r1 or secp256k1 curve.

Create a certificate signing request (CSR) for the root CA

openssl req -new -nodes -text -out root.csr -key root.key -subj "/CN=rootCA"

Sign the root certificate

openssl x509 -req -in root.csr -text -days 3650 -signkey root.key -out root.crt

2. Create a Server Certificate with an EC Key

Generate an EC private key for the server

openssl ecparam -name prime256v1 -genkey -noout -out server.key

Create a CSR for the server

openssl req -new -nodes -text -out server.csr -key server.key -subj "/CN=server"

Sign the server certificate with the root CA

openssl x509 -req -in server.csr -text -days 365 \
  -CA root.crt -CAkey root.key -CAcreateserial -out server.crt

3. Create a Client Certificate with an EC Key

You must create a new certificate for each client.

Generate an EC private key for the client

openssl ecparam -name prime256v1 -genkey -noout -out client.key

Create a CSR for the client

openssl req -new -nodes -text -out client.csr -key client.key -subj "/CN=client"

Sign the client certificate with the root CA

openssl x509 -req -in client.csr -text -days 365 \
  -CA root.crt -CAkey root.key -CAcreateserial -out client.crt

Verifying the Certificates

Verify the root certificate

openssl x509 -in root.crt -text -noout

Verify the server certificate

openssl x509 -in server.crt -text -noout

Configure Postgres

Enable SSL

Edit the postgresql.conf file and set the following parameters:

ssl = on
ssl_cert_file = 'server.crt'
ssl_key_file = 'server.key'
ssl_ca_file = 'root.crt'

Edit the pg_hba.conf file and add the following line:

hostssl   all     all      127.0.0.1/32         scram-sha-256     clientcert=verify-ca

From the Postgres documentation:

This option can be set to verify-ca or verify-full. Both options require the client to present a valid (trusted) SSL certificate, while verify-full additionally enforces that the cn (Common Name) in the certificate matches the username or an applicable mapping.

Restart Postgres

systemctl restart postgresql