IT-Admin.tech

PostgreSQL production hardening: role management, TLS, pg_hba.conf and disk encryption

Architekturdiagramm zu PostgreSQL-Zugriff, TLS-Handshake und verschlüsseltem Storage mit System-Engineer im Hintergrund
Diagramm zeigt Zugriffsregeln (pg_hba.conf), TLS-Handshake-Pfade und verschlüsseltes Datenvolumen (LUKS/BitLocker) als Grundlage für gehärtete PostgreSQL-Setups.

PostgreSQL production hardening starts with a realistic inventory: which clients connect, from which networks, which auth methods they use and which elevated or reduced privileges are actually required in daily operation? The focus keyword is placed deliberately early – hardening is not a feature but an operationally anchored process that brings together role, network and storage measures while also accounting for migration, backup and recovery.

Threat model, objectives and prioritization

Hardening means addressing concrete risks. Typical attack vectors are: open network access, leaked credentials (e.g. in CI/CD variables), unencrypted backups, stolen storage media or attackers with local root. Prioritize measures by impact (data loss, service interruption) and likelihood of occurrence.

  • Least Privilege: roles and privileges as RESTrictive as possible
  • Reliable transport encryption: TLS with host verification
  • RESTrictive pg_hba.conf as the first firewall layer
  • Encryption of data at REST combined with controlled key management

Role management: structure, responsibility and change processes

In PostgreSQL, roles are technical identities with privileges; they can have login rights (LOGIN) or exist as group roles without login. Use this concept as the basis for a maintainable authorization model: login roles for specific services or people, group roles as policy containers.

Concept: separation of identity and privileges

Group roles aggregate privileges (e.g. read-only, read-write). Login roles receive only the memberships they need. Advantage: in case of compromise or a deployment change you adjust memberships, not privileges across all objects. Risks arise when deployment processes change object owners — then default privileges may no longer apply.

Concrete operations and verification queries

SQL
-- Gruppenrollen anlegen
CREATE ROLE app_ro NOLOGIN;
CREATE ROLE app_rw NOLOGIN;

-- Service-Login-Rolle
CREATE ROLE svc_app_prod LOGIN;
GRANT app_rw TO svc_app_prod;

-- Basis-Grants
GRANT CONNECT ON DATABASE mydb TO app_ro, app_rw;
GRANT USAGE ON SCHEMA public TO app_ro, app_rw;

-- Objekt-Rechte
GRANT SELECT ON ALL TABLES IN SCHEMA public TO app_ro;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_rw;

-- Default-Privileges für neue Objekte
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT ON TABLES TO app_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_rw;

For inventorying, use queries to capture login roles, groups and owner relationships:

SQL
-- Login-fähige Rollen prüfen
SELECT rolname, rolcanlogin, rolsuper FROM pg_roles ORDER BY rolname;

-- Rollenmitgliedschaften
SELECT r.rolname AS role, m.rolname AS member
FROM pg_auth_members am
JOIN pg_roles r ON r.oid = am.roleid
JOIN pg_roles m ON m.oid = am.member
ORDER BY r.rolname, m.rolname;

-- Tabellen-Owner und Rechte prüfen
SELECT n.nspname, c.relname, r.rolname AS owner
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
JOIN pg_roles r ON r.oid = c.relowner
WHERE c.relkind = 'r' -- nur Tabellen
ORDER BY n.nspname, c.relname;

Change and rollback strategy

Carry out permission changes within a ticket, export before/after reports and generate revert scripts (e.g., automatic GRANT/REVOKE scripts). If a change affects connections, restore grants first before removing memberships.

PostgreSQL production hardening: implementing and verifying TLS

TLS protects transport data; it is essential that clients verify the server identity. In short: ssl = on is only the baseline. Without a PKI concept, CA distribution and correct SANs you do not achieve real protection against man‑in‑the‑middle attacks.

Practical prerequisites

You need a server certificate (server.crt) and the private key (server.key). SANs (Subject Alternative Names) in the certificate must cover all used hostnames/DNS aliases. File permissions for the key are critical: PostgreSQL will refuse to start if the permissions are too permissive.

Shell
# Beispielrechte für den privaten Schlüssel
chown postgres:postgres /var/lib/postgresql/server.key
chmod 0600 /var/lib/postgresql/server.key

postgresql.conf: recommended settings

Ini
ssl = on
ssl_cert_file = 'server.crt'
ssl_key_file  = 'server.key'
# CA-Datei für clientseitige Zertifikatprüfung (optional bei mTLS)
# ssl_ca_file = 'root.crt'
# Erzwingen starker TLS-Versionen/Cipher basierend auf OS-Paket
log_connections = on
log_disconnections = on

Client modes and transition strategy

libpq clients support sslmodes such as disable, require, verify-ca and verify-full. The long-term goal is verify-full (verifies CA and hostname). For rollout, use a staged approach: first deploy servers with TLS, then test clients and gradually switch to verify-full. Document legacy clients that do not support verify-full.

Verification and troubleshooting

SQL
-- TLS-Status pro Session sehen
SELECT a.pid, a.usename, a.client_addr, s.ssl, s.version, s.cipher
FROM pg_stat_activity a
LEFT JOIN pg_stat_ssl s ON a.pid = s.pid
ORDER BY a.client_addr;

Typical errors: Certificate verify failed (CA not distributed or incorrect SANs), Permission denied for server.key, or performance drops due to entropy shortages on older VMs. For OCSP/CRL issues, verify whether firewalls can reach the CRL/OCSP servers.

pg_hba.conf: rules, order and tests

The pg_hba.conf is the first logical access barrier. PostgreSQL evaluates entries sequentially; the first matching rule applies. Therefore: place specific rules at the top, and broad rules at the end or omit them entirely.

Recommended principles

  • No catch-all rules
  • Prefer host connections via hostssl
  • Strong authentication: scram-sha-256 instead of md5
  • Admin access only via bastion hosts with a separate HBA line

Example configuration and verification procedure

Ini
# Wartung lokal
local   all             postgres                                peer
# Tools lokal
local   all             all                                     scram-sha-256
# Adminzugang - nur Bastion-Netz, TLS
hostssl all             dba_admin         10.10.10.0/24          scram-sha-256
# App-Zugriff
hostssl mydb            svc_app_prod      10.20.0.0/16           scram-sha-256
# Replikation
hostssl replication     repl_user         10.40.0.0/24           scram-sha-256

Test changes with an open admin session. After changes, usually SELECT pg_reload_conf(); is enough to reload HBA. Also check IPv6 rules — their absence can lead to seemingly random connection problems.

SQL
SELECT pg_reload_conf();

Planning Full Disk Encryption (FDE) correctly

FDE (Full Disk Encryption) protects against disk theft or unauthorized images. It does not protect against an attacker with root on a running system, because keys are then available. Therefore FDE is part of a defense-in-depth strategy, not the only measure.

Architecture decisions: PGDATA, WAL, Temp and Backups

Encrypt all data-sensitive storage areas: PGDATA (data files), the WAL volume (Write-Ahead Logs), temp directories and backup staging. An unencrypted backup on an unencrypted volume can undermine the entire strategy.

LUKS practice and performance checks

Shell
# Example run (do not run blindly in production)
lsblk
cryptsetup luksFormat /dev/sdb
cryptsetup open /dev/sdb pgdata_crypt
mkfs.xfs /dev/mapper/pgdata_crypt
mount /dev/mapper/pgdata_crypt /var/lib/postgresql/data
# /etc/crypttab and /etc/fstab persist
# Test: I/O measurement
fio --name=seqwrite --filename=/var/lib/postgresql/data/testfile --size=1G --bs=1M --rw=write

Test fsync behavior, checkpoint latencies and WAL throughput after migrations. LUKS overhead is usually moderate on modern CPUs, but on I/O-sensitive systems you must perform measurements and, if necessary, ensure CPU offload or kernel AES-NI support.

Key management: TPM, KMS and recovery

Good practice: automated unlocking via a KMS connector (e.g. Vault, Cloud KMS) or TPM binding with clearly defined break-glass processes. Test recovery procedures regularly. Without tested recovery, FDE is a significant operational risk.

Backup integration and PITR in hardened environments

Backup strategy and PITR (Point-in-Time Recovery) must work together with encryption and TLS. Backups should be transported encrypted and remain encrypted at the destination. WAL archives must meet the same security requirements as live WALs.

Encrypted backups and verification

Shell
# Example: encrypted archiving with GPG (key management assumed)
pg_basebackup -D - -Ft | gpg --encrypt --recipient backup@domain > /mnt/backup/mydb_$(date +%F).tar.gpg

Validate backups regularly: RESTore tests in an isolated environment, verify WAL application, and measure recovery time. Also check that the backup user has the necessary rights but is not a superuser.

Monitoring, auditing and automated tests

Hardening is not a one-off project. Automated checks provide operational assurance:

  • Monitoring: pg_stat_ssl, pg_stat_activity, connection rates
  • Audit logs: connection/disconnection, failed auths, DDL events via pgaudit
  • Automated tests: connection tests from client networks, HBA test matrix, backup-RESTore jobs
SQL
-- Monitor whether TLS is used
SELECT count(*) FILTER (WHERE s.ssl) AS ssl_conn,
       count(*) FILTER (WHERE s.ssl IS NULL OR s.ssl = false) AS nonssl_conn
FROM pg_stat_activity a
LEFT JOIN pg_stat_ssl s ON a.pid = s.pid;

Key rotation, password upgrade and compatibility strategy

Plan for key and password rotation: for TLS certificates, LUKS headers, and PostgreSQL passwords. For SCRAM migration set password_encryption = scram-sha-256 in postgresql.conf and perform a staged update of the login role passwords.

SQL
-- Setzen und erneuern von Passwörtern (nach Einstellen password_encryption)
ALTER ROLE svc_app_prod PASSWORD 'neues_starkes_passwort';
-- Prüfen ob SCRAM verwendet wird
SELECT rolname, rolpassword IS NOT NULL AS has_password FROM pg_authid WHERE rolcanlogin; -- Zugriff erfordert superuser

For LUKS key rotation create new keyslots, test unlocking and locking on a host and document the rollback procedure.

Predictable pitfalls and quick mitigations

  • Missing SANs: server certificate does not cover hostnames → Rollback: temporary HBA exception and certificate exchange
  • Legacy clients break with SCRAM → Mitigation: network segmentation or a transitional rule in HBA
  • Unencrypted backup staging → Immediate action: pause backup transfers, set up encrypted target volumes
  • Incorrect file permissions for server.key → PostgreSQL refuses SSL handshake; fix: set chown/chmod correctly

Conclusion

PostgreSQL production hardening is a pragmatic, iterative process: structure roles cleanly, introduce TLS with proper certificate validation, maintain pg_hba.conf RESTrictively and auditable, and operate disk encryption with a tested recovery and key management strategy. Automated checks, documented rollbacks and coordination with deployment processes are essential so that security remains operable, reproducible and auditable.

Operational perspectives: Rolling Changes, Replication and Container Environments

Besides configuration and encryption, the change and operational strategy determines whether hardening measures remain practical in daily operation. Three areas are particularly critical: orderly rollouts (Canary/Phased), secure replication and behavior in container/orchestration environments.

Canary changes and quick rollback

Changes to pg_hba.conf, TLS certificates or password_encryption should never be rolled out „blindly“ to all nodes. Proceed in short, verifiable steps:

  • Create a modified configuration as a separate file (e.g. pg_hba.conf.new).
  • Activate the new file on a canary host, test connections from all relevant subnets.
  • If problems occur: atomic RESToration of the old file and SELECT pg_reload_conf();.
Shell
# Beispiel: sicherer Swap und Test
cp /etc/postgresql/12/main/pg_hba.conf /tmp/pg_hba.conf.bak
cp /etc/postgresql/12/main/pg_hba.conf.new /etc/postgresql/12/main/pg_hba.conf
psql -h 127.0.0.1 -U svc_test -d mydb -c 'conninfo' || { cp /tmp/pg_hba.conf.bak /etc/postgresql/12/main/pg_hba.conf; psql -c "SELECT pg_reload_conf();"; echo "Rollback ausgeführt"; }
psql -c "SELECT pg_reload_conf();"

Secure replication: roles, limits and monitoring

Replication access requires dedicated roles with minimal privileges, clear IP RESTrictions and connection limits. Assign the REPLICATION attribute selectively, set connection_limit, and monitor slots and latency.

SQL
-- Replikationsrolle anlegen
CREATE ROLE repl_user WITH REPLICATION LOGIN PASSWORD 'starkes_passwort' CONNECTION LIMIT 3;
-- Überwachung: repl slot & lag
SELECT slot_name, active, RESTart_lsn FROM pg_replication_slots;
SELECT application_name, state, sync_state, pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS bytes_lag
FROM pg_stat_replication;

Risks: unlimited replication slots can force WAL retention and fill storage. Plan slot lifecycles and automated cleanup jobs.

Container & Kubernetes: Secrets and Volumes

In Containers/StatefulSets, private keys and LUKS keys must not reside in images. Use Secrets (Kubernetes) or encrypted volumes with CSI‑KMS. Note: certificate rotation usually requires a pod RESTart because Postgres loads the server certificate at startup.

  • Mount Secrets with RESTricted filemode (0600) and check SELinux/AppArmor context on host systems.
  • For rolling RESTarts, plan PodDisruptionBudgets and health checks so clients do not lose all connections.

Quick diagnostic checks

  • Errors after TLS/key changes: check journalctl -u postgresql (permission/SSL errors).
  • Connection issues after HBA adjustments: test from different subnets with psql -h.
  • For performance changes after a LUKS migration: compare I/O benchmarks (fio) and WAL throughput.

In short: operationalization makes hardening resilient. Automated canary tests, dedicated replication roles and well‑managed secrets minimize failure risk and make rollbacks plannable — essential for production environments where custom enterprise software and integrations depend on stable database access.

For this topic, PostgreSQL role management and Pg_Hba.conf best practices are also important. This article places these aspects in context and shows what matters in day‑to‑day operations.