Files
notes/AI_generated/PostgreSQL_TLS_01.md
2026-03-12 22:01:38 +01:00

5.3 KiB
Raw Permalink Blame History

📄 Technical Guide: Setting Up TLS for PostgreSQL

This document consolidates the groups discussion into a practical, productionready reference for configuring and using TLS with PostgreSQL, including server setup, client configuration, password management, and example application code.


1. Overview

PostgreSQL supports encrypted connections using TLS (often referred to as SSL in its configuration). Enabling TLS ensures secure clientserver communication and can optionally enforce client certificate authentication. This guide provides stepbystep instructions for server and client configuration, common pitfalls, and usage examples.


2. Server-Side Configuration

Certificates

  • Required files:
  • Sources: internal PKI, Lets Encrypt, or selfsigned CA.
  • Permissions: server.key must be 0600 or rootowned with restricted group access.

Placement

Configuration

Enable TLS in postgresql.conf:

ssl = on
ssl_ciphers = 'HIGH:!aNULL:!MD5'
ssl_prefer_server_ciphers = on
ssl_min_protocol_version = 'TLSv1.2'
ssl_max_protocol_version = 'TLSv1.3'

Access Control

Configure pg_hba.conf:

  • Allow TLS but not require:

    host all all 0.0.0.0/0 md5
    
  • Require TLS:

    hostssl all all 0.0.0.0/0 md5
    
  • Require TLS + client certificate:

    hostssl all all 0.0.0.0/0 cert
    

3. Client-Side Configuration

Basic TLS

psql "host=db.example.com sslmode=require"

Verify server certificate

psql "host=db.example.com sslmode=verify-full sslrootcert=/etc/ssl/myca/root.crt"
  • sslrootcert is a client-side path to the CA certificate.

Mutual TLS

psql "host=db.example.com sslmode=verify-full \
      sslrootcert=/etc/ssl/myca/root.crt \
      sslcert=/etc/ssl/myca/client.crt \
      sslkey=/etc/ssl/myca/client.key"

Modes comparison

Mode Encrypts Validates CA Validates Hostname Typical Use
require Yes No No Basic encryption
verify-ca Yes Yes No Internal/IP-based
verify-full Yes Yes Yes Production

4. Password Management

Format:

hostname:port:database:username:password

Example:

db.example.com:5432:mydb:myuser:SuperSecretPassword123
localhost:5432:*:postgres:localdevpass
*:5432:*:replicator:replicaPassword
  • Location: ~/.pgpass
  • Permissions: chmod 600 ~/.pgpass
  • Supports wildcards (*).

Environment variable

PGPASSWORD='secret123' psql -U myuser -h localhost -d mydb

Less secure; use only for quick commands.


5. Testing & Verification

  • Check server TLS status:

    SHOW ssl;
    
  • Inspect negotiated protocol & cipher:

    SELECT * FROM pg_stat_ssl;
    
  • External test:

    openssl s_client -connect db.example.com:5432 -starttls postgres
    

6. Common Pitfalls

Issue Cause Fix
FATAL: private key file has group or world access Wrong permissions chmod 600 server.key
Client rejects certificate CN/SAN mismatch Ensure proper DNS SANs
TLS not enforced Used host instead of hostssl Update pg_hba.conf
Backup tools fail Key readable only by postgres Store certs outside $PGDATA if group-readable needed

7. Application Example (Python)

Minimal psycopg2 script with TLS verify-full and bind variables:

import psycopg2
import psycopg2.extras

def main():
    conn = psycopg2.connect(
        host="db.example.com",
        port=5432,
        dbname="mydb",
        user="myuser",
        password="SuperSecretPassword123",
        sslmode="verify-full",
        sslrootcert="/etc/ssl/myca/root.crt",
        sslcert="/etc/ssl/myca/client.crt",   # optional
        sslkey="/etc/ssl/myca/client.key"     # optional
    )

    with conn:
        with conn.cursor(cursor_factory=psycopg2.extras.DictCursor) as cur:
            cur.execute("SELECT id, name FROM demo WHERE id = %s", (1,))
            print("SELECT:", cur.fetchone())

            cur.execute("INSERT INTO demo (id, name) VALUES (%s, %s)", (2, "Inserted Name"))
            cur.execute("UPDATE demo SET name = %s WHERE id = %s", ("Updated Name", 2))
            cur.execute("DELETE FROM demo WHERE id = %s", (2,))

    conn.close()

if __name__ == "__main__":
    main()

Appendix / Future Considerations

  • Hardened production templates (PKI layout, Ansible roles, CI/CD verification checklist).
  • Alternative drivers: psycopg3, SQLAlchemy, async examples.
  • Integration with secret management (Kubernetes secrets, systemd, Ansible vault).
  • Directory layout best practices for server vs client PKI.

This document now serves as a consolidated technical guide for setting up and using TLS with PostgreSQL, including secure password handling and client application integration.