Skip to content

Last updated: 2026-02-11

PostgreSQL TLS/SSL Configuration Guide

This guide provides recommended TLS/SSL settings for PostgreSQL to encrypt connections between clients and the database server. Encrypting database traffic is essential for protecting sensitive data in transit.

Prerequisites

Certificate Setup

PostgreSQL expects certificate files in specific locations. By default, it looks in the data directory, but you can specify paths explicitly.

Set appropriate file permissions on the private key:

chmod 600 /etc/postgresql/ssl/server.key
chown postgres:postgres /etc/postgresql/ssl/server.key

Server Configuration

Add the following settings to postgresql.conf.

Path note: The postgresql.conf location varies by distribution:

  • Debian/Ubuntu: /etc/postgresql/<version>/main/postgresql.conf
  • RHEL/CentOS: /var/lib/pgsql/<version>/data/postgresql.conf
  • SLES: /var/lib/pgsql/data/postgresql.conf

Enable SSL

ssl = on

Protocol Versions

Set the minimum TLS protocol version to 1.2. PostgreSQL 12+ supports ssl_min_protocol_version:

ssl_min_protocol_version = 'TLSv1.2'

Cipher Suites

Configure strong cipher suites with ECDHE key exchange and AEAD encryption:

ssl_ciphers = 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305'
ssl_prefer_server_ciphers = on

PostgreSQL 16+: ssl_prefer_server_ciphers has no effect on TLS 1.3 connections (TLS 1.3 always uses client preference). It still applies to TLS 1.2 connections but can be safely omitted on PG 16+ if all clients use TLS 1.3.

ECDH Curve

Specify the elliptic curve for ECDHE key exchange:

ssl_ecdh_curve = 'prime256v1'

PostgreSQL 15+ supports multiple curves (e.g., ssl_ecdh_curve = 'prime256v1:secp384r1'). On PostgreSQL 12-14, only a single curve is accepted.

Certificate Files

ssl_cert_file = '/etc/postgresql/ssl/server.crt'
ssl_key_file = '/etc/postgresql/ssl/server.key'
ssl_ca_file = '/etc/postgresql/ssl/ca.crt'

Complete Server Configuration

Add these lines to postgresql.conf:

# Enable SSL
ssl = on

# Protocol version
ssl_min_protocol_version = 'TLSv1.2'

# Cipher suites
ssl_ciphers = 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305'
ssl_prefer_server_ciphers = on   # No effect on TLS 1.3 (PG 16+); still applies to TLS 1.2
ssl_ecdh_curve = 'prime256v1'  # PostgreSQL 15+ supports multiple curves: 'prime256v1:secp384r1'

# Certificate files
ssl_cert_file = '/etc/postgresql/ssl/server.crt'
ssl_key_file = '/etc/postgresql/ssl/server.key'
ssl_ca_file = '/etc/postgresql/ssl/ca.crt'

Client Authentication (pg_hba.conf)

To require TLS for remote connections, use hostssl entries in pg_hba.conf instead of host. The host type allows both encrypted and unencrypted connections, while hostssl requires TLS:

# Require SSL for all remote connections
hostssl all all 0.0.0.0/0 scram-sha-256
hostssl all all ::/0      scram-sha-256

# Allow local (Unix socket) connections without SSL
local   all all           peer

To explicitly reject non-SSL remote connections, add hostnossl reject rules:

hostnossl all all 0.0.0.0/0 reject
hostnossl all all ::/0      reject

Client Connection Settings

When connecting from a client, specify the SSL mode:

psql "host=db.example.com dbname=mydb user=appuser sslmode=verify-full sslrootcert=/path/to/ca.crt"

Available sslmode values:

For application connection strings:

postgresql://appuser@db.example.com/mydb?sslmode=verify-full&sslrootcert=/path/to/ca.crt

Verification

After restarting PostgreSQL, verify SSL is enabled:

systemctl restart postgresql

Connect and check the SSL status:

psql -h localhost -U postgres -c "SHOW ssl;"
psql -h localhost -U postgres -c "SELECT ssl, version, cipher FROM pg_stat_ssl WHERE pid = pg_backend_pid();"

The second query shows the TLS version and cipher in use for your current connection.