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
- PostgreSQL 12 or later (for
ssl_min_protocol_versionsupport) - OpenSSL 1.1.1 or later (for TLS 1.3 support)
- SSL certificates (server certificate, private key, and CA certificate)
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.conflocation 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_ciphershas 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:
- require -- Encrypt the connection, but don't verify the server certificate
- verify-ca -- Encrypt and verify the server certificate against the CA
- verify-full -- Encrypt, verify the CA, and verify the server hostname matches the certificate (recommended)
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.