CIS PostgreSQL 16 Benchmark

Secure configuration guidelines for PostgreSQL 16 database server

v1.0.0 August 2024

Overview

▶

This CIS Benchmark provides prescriptive guidance for establishing a secure configuration posture for PostgreSQL 16. Recommendations cover installation hardening, access control, logging, authentication, SSL/TLS, and replication security.

~100Recommendations
6Sections
2Profile Levels
SectionAreaFocus
1Installation & PatchesSecure install, version management, updates
2Directory & File PermissionsData directory, config file permissions
3Logging & AuditingLog destination, content, rotation
4User Access & AuthorizationSuperuser, roles, privileges, schemas
5Connection & Authenticationpg_hba.conf, SSL/TLS, password encryption
6Replication & BackupStreaming replication, WAL, backup config

Profile Definitions

▶
ProfileDescriptionIntended Use
L1Level 1 — ServerEssential database hardening with minimal operational impact.
L2Level 2 — ServerAdvanced defense-in-depth. May require application changes.

1 — Installation & Patches

▶

1.1 Installation

▶
1.1.1 Ensure PostgreSQL Is Installed from Official Repositories (Manual)
L1 Manual
Description

This recommendation verifies that PostgreSQL Is Installed from Official Repositories on the PostgreSQL 16 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to postgreSQL Is Installed from Official Repositories may leave the PostgreSQL 16 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
psql --version
# Verify installed from PGDG or OS vendor packages
rpm -qi postgresql16-server 2>/dev/null || dpkg -s postgresql-16 2>/dev/null
Remediation

Install PostgreSQL 16 from the official PostgreSQL Global Development Group (PGDG) repository: https://www.postgresql.org/download/

1.1.2 Ensure a Dedicated OS Account for PostgreSQL (Automated)
L1 Auto
Description

This recommendation verifies that a Dedicated OS Account for PostgreSQL on the PostgreSQL 16 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to a Dedicated OS Account for PostgreSQL may leave the PostgreSQL 16 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
id postgres
# Should exist with a dedicated home directory and nologin or restricted shell
Remediation
# The 'postgres' OS user is created by default during installation.
# Ensure it has a restricted shell:
usermod -s /sbin/nologin postgres
1.1.3 Ensure Only Required Extensions Are Installed (Manual)
L1 Manual
Description

This recommendation verifies that Only Required Extensions Are Installed on the PostgreSQL 16 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to only Required Extensions Are Installed may leave the PostgreSQL 16 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
SELECT name, installed_version FROM pg_available_extensions WHERE installed_version IS NOT NULL;
Remediation
-- Remove unnecessary extensions:
DROP EXTENSION IF EXISTS <extension_name>;

1.2 Patches & Updates

▶
1.2.1 Ensure the Latest Security Patches Are Applied (Manual)
L1 Manual
Description

This recommendation verifies that the Latest Security Patches Are Applied on the PostgreSQL 16 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to the Latest Security Patches Are Applied may leave the PostgreSQL 16 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
SELECT version();
-- Compare against https://www.postgresql.org/support/versioning/
Remediation
# Update to latest minor version:
dnf update postgresql16-server
# or
apt upgrade postgresql-16

2 — Directory & File Permissions

▶

2.1 Data Directory

▶
2.1.1 Ensure PGDATA Permissions Are Restricted (Automated)
L1 Auto
Description

This setting ensures that PGDATA Permissions is restricted on the PostgreSQL 16 database server. Restricting this capability limits potential abuse and enforces the principle of least privilege across the environment.

Rationale

Unrestricted PGDATA Permissions could allow unauthorized users or processes to perform actions beyond their intended scope. Applying least-privilege principles to the PostgreSQL 16 database server is essential for defense in depth.

Audit
SHOW data_directory;
-- Then check:
ls -ld /var/lib/pgsql/16/data/
# Should be drwx------ (0700) owned by postgres:postgres
Remediation
chmod 700 /var/lib/pgsql/16/data/
chown postgres:postgres /var/lib/pgsql/16/data/
2.1.2 Ensure WAL Directory Permissions Are Restricted (Automated)
L1 Auto
Description

This setting ensures that WAL Directory Permissions is restricted on the PostgreSQL 16 database server. Restricting this capability limits potential abuse and enforces the principle of least privilege across the environment.

Rationale

Unrestricted WAL Directory Permissions could allow unauthorized users or processes to perform actions beyond their intended scope. Applying least-privilege principles to the PostgreSQL 16 database server is essential for defense in depth.

Audit
ls -ld /var/lib/pgsql/16/data/pg_wal/
# Should be drwx------ (0700) owned by postgres:postgres
Remediation
chmod 700 /var/lib/pgsql/16/data/pg_wal/
chown postgres:postgres /var/lib/pgsql/16/data/pg_wal/

2.2 Configuration Files

▶
2.2.1 Ensure postgresql.conf Permissions Are 600 (Automated)
L1 Auto
Description

File and directory permissions for postgresql.conf should be set to 600. Overly permissive access controls can allow unauthorized users to read, modify, or execute sensitive files, potentially compromising the PostgreSQL 16 database server.

Rationale

Incorrect permissions on postgresql.conf could allow unauthorized reading, writing, or execution of critical files. Proper file permissions are a foundational control that prevents privilege escalation and data tampering.

Audit
SHOW config_file;
-- Check permissions:
stat -c '%a %U %G' /var/lib/pgsql/16/data/postgresql.conf
# Should be 600 postgres postgres
Remediation
chmod 600 /var/lib/pgsql/16/data/postgresql.conf
chown postgres:postgres /var/lib/pgsql/16/data/postgresql.conf
2.2.2 Ensure pg_hba.conf Permissions Are 600 (Automated)
L1 Auto
Description

File and directory permissions for pg_hba.conf should be set to 600. Overly permissive access controls can allow unauthorized users to read, modify, or execute sensitive files, potentially compromising the PostgreSQL 16 database server.

Rationale

Incorrect permissions on pg_hba.conf could allow unauthorized reading, writing, or execution of critical files. Proper file permissions are a foundational control that prevents privilege escalation and data tampering.

Audit
SHOW hba_file;
-- Check permissions:
stat -c '%a %U %G' /var/lib/pgsql/16/data/pg_hba.conf
# Should be 600 postgres postgres
Remediation
chmod 600 /var/lib/pgsql/16/data/pg_hba.conf
chown postgres:postgres /var/lib/pgsql/16/data/pg_hba.conf

3 — Logging & Auditing

▶

3.1 Log Settings

▶
3.1.1 Ensure Logging Is Enabled (Automated)
L1 Auto
Description

This setting controls whether Logging is enabled on the PostgreSQL 16 database server. Enabling this feature strengthens the security posture by enforcing the recommended configuration via postgresql.conf, pg_hba.conf, or SQL commands.

Rationale

Without Logging enabled, the PostgreSQL 16 database server may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.

Audit
SHOW logging_collector;
-- Should be: on
Remediation
-- postgresql.conf:
logging_collector = on
3.1.2 Ensure Log Destination Is Configured (Automated)
L1 Auto
Description

This recommendation addresses the proper configuration of Log Destination on the PostgreSQL 16 database server. Proper configuration ensures the component operates securely and in accordance with organizational security policies.

Rationale

Misconfiguration of Log Destination can lead to security gaps that may be exploited by attackers. A properly configured PostgreSQL 16 database server reduces exposure to both known vulnerabilities and configuration drift.

Audit
SHOW log_destination;
-- Should be: stderr or csvlog (or syslog)
Remediation
-- postgresql.conf:
log_destination = 'stderr'
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
3.1.3 Ensure Log Rotation Is Configured (Automated)
L1 Auto
Description

This recommendation addresses the proper configuration of Log Rotation on the PostgreSQL 16 database server. Proper configuration ensures the component operates securely and in accordance with organizational security policies.

Rationale

Misconfiguration of Log Rotation can lead to security gaps that may be exploited by attackers. A properly configured PostgreSQL 16 database server reduces exposure to both known vulnerabilities and configuration drift.

Audit
SHOW log_rotation_age;
SHOW log_rotation_size;
-- Recommended: log_rotation_age = 1d
Remediation
-- postgresql.conf:
log_rotation_age = 1d
log_rotation_size = 100MB
log_truncate_on_rotation = on

3.2 Log Content

▶
3.2.1 Ensure log_connections Is Enabled (Automated)
L1 Auto
Description

This setting controls whether log_connections is enabled on the PostgreSQL 16 database server. Enabling this feature strengthens the security posture by enforcing the recommended configuration via postgresql.conf, pg_hba.conf, or SQL commands.

Rationale

Without log_connections enabled, the PostgreSQL 16 database server may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.

Audit
SHOW log_connections;
-- Should be: on
Remediation
-- postgresql.conf:
log_connections = on
3.2.2 Ensure log_disconnections Is Enabled (Automated)
L1 Auto
Description

This setting controls whether log_disconnections is enabled on the PostgreSQL 16 database server. Enabling this feature strengthens the security posture by enforcing the recommended configuration via postgresql.conf, pg_hba.conf, or SQL commands.

Rationale

Without log_disconnections enabled, the PostgreSQL 16 database server may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.

Audit
SHOW log_disconnections;
-- Should be: on
Remediation
-- postgresql.conf:
log_disconnections = on
3.2.3 Ensure log_statement Is Set to DDL or All (Automated)
L2 Auto
Description

This recommendation configures log_statement to DDL or All on the PostgreSQL 16 database server. Setting this value appropriately ensures the system operates within the security parameters defined by the CIS benchmark.

Rationale

An improperly configured value for log_statement could weaken security controls or allow unintended behavior. Setting this to DDL or All ensures the PostgreSQL 16 database server operates within a well-defined security boundary.

Audit
SHOW log_statement;
-- Should be: ddl or all
Remediation
-- postgresql.conf:
log_statement = 'ddl'
3.2.4 Ensure log_line_prefix Is Configured (Automated)
L1 Auto
Description

This recommendation addresses the proper configuration of log_line_prefix on the PostgreSQL 16 database server. Proper configuration ensures the component operates securely and in accordance with organizational security policies.

Rationale

Misconfiguration of log_line_prefix can lead to security gaps that may be exploited by attackers. A properly configured PostgreSQL 16 database server reduces exposure to both known vulnerabilities and configuration drift.

Audit
SHOW log_line_prefix;
-- Should include timestamp, user, database, and process ID
Remediation
-- postgresql.conf:
log_line_prefix = '%m [%p] %u@%d '
3.2.5 Ensure pgAudit Extension Is Enabled (Manual)
L2 Manual
Description

This setting controls whether pgAudit Extension is enabled on the PostgreSQL 16 database server. Enabling this feature strengthens the security posture by enforcing the recommended configuration via postgresql.conf, pg_hba.conf, or SQL commands.

Rationale

Without pgAudit Extension enabled, the PostgreSQL 16 database server may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.

Audit
SHOW shared_preload_libraries;
-- Should include: pgaudit
SELECT * FROM pg_available_extensions WHERE name = 'pgaudit';
Remediation
-- postgresql.conf:
shared_preload_libraries = 'pgaudit'

-- After restart:
CREATE EXTENSION pgaudit;

-- Configure audit settings:
pgaudit.log = 'write, ddl, role'

4 — User Access & Authorization

▶

4.1 Superuser Access

▶
4.1.1 Ensure Superuser Accounts Are Minimized (Automated)
L1 Auto
Description

This recommendation verifies that Superuser Accounts Are Minimized on the PostgreSQL 16 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to superuser Accounts Are Minimized may leave the PostgreSQL 16 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
SELECT rolname FROM pg_roles WHERE rolsuper = true;
-- Should only show 'postgres'
Remediation
-- Remove superuser from unnecessary accounts:
ALTER ROLE <rolename> NOSUPERUSER;
4.1.2 Ensure the postgres Superuser Has a Strong Password (Manual)
L1 Manual
Description

This recommendation verifies that the postgres Superuser Has a Strong Password on the PostgreSQL 16 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to the postgres Superuser Has a Strong Password may leave the PostgreSQL 16 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
-- Verify password is set (not trust or peer-only):
SELECT rolpassword IS NOT NULL as has_password FROM pg_authid WHERE rolname = 'postgres';
Remediation
\password postgres
-- Enter a strong password (14+ characters, mixed case, numbers, special)

4.2 Roles & Privileges

▶
4.2.1 Ensure No Roles Have CREATEDB Unnecessarily (Automated)
L1 Auto
Description

This recommendation verifies that No Roles Have CREATEDB Unnecessarily on the PostgreSQL 16 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to no Roles Have CREATEDB Unnecessarily may leave the PostgreSQL 16 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
SELECT rolname FROM pg_roles WHERE rolcreatedb = true AND rolname != 'postgres';
Remediation
ALTER ROLE <rolename> NOCREATEDB;
4.2.2 Ensure No Roles Have CREATEROLE Unnecessarily (Automated)
L1 Auto
Description

This recommendation verifies that No Roles Have CREATEROLE Unnecessarily on the PostgreSQL 16 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to no Roles Have CREATEROLE Unnecessarily may leave the PostgreSQL 16 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
SELECT rolname FROM pg_roles WHERE rolcreaterole = true AND rolname != 'postgres';
Remediation
ALTER ROLE <rolename> NOCREATEROLE;
4.2.3 Ensure PUBLIC Schema Has Restricted Privileges (Automated)
L1 Auto
Description

This recommendation verifies that PUBLIC Schema Has Restricted Privileges on the PostgreSQL 16 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to pUBLIC Schema Has Restricted Privileges may leave the PostgreSQL 16 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
SELECT nspname, nspacl FROM pg_namespace WHERE nspname = 'public';
-- Should NOT have broad CREATE or USAGE for PUBLIC
Remediation
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
REVOKE ALL ON DATABASE <dbname> FROM PUBLIC;
4.2.4 Ensure Row-Level Security Is Used Where Appropriate (Manual)
L2 Manual
Description

This recommendation verifies that Row-Level Security Is Used Where Appropriate on the PostgreSQL 16 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to row-Level Security Is Used Where Appropriate may leave the PostgreSQL 16 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
SELECT schemaname, tablename, rowsecurity FROM pg_tables WHERE rowsecurity = true;
Remediation
-- For multi-tenant tables:
ALTER TABLE <tablename> ENABLE ROW LEVEL SECURITY;
CREATE POLICY <policy_name> ON <tablename>
  USING (tenant_id = current_setting('app.current_tenant')::int);

5 — Connection & Authentication

▶

5.1 pg_hba.conf

▶
5.1.1 Ensure "trust" Authentication Is Not Used (Automated)
L1 Auto
Description

"trust" Authentication should not be used on the PostgreSQL 16 database server. Removing or disabling this component reduces the attack surface and prevents potential exploitation of unnecessary services or features.

Rationale

If "trust" Authentication remains used, it presents an unnecessary risk vector that attackers could exploit. Removing or disabling unused components is a fundamental principle of secure system hardening.

Audit
grep -v '^#' /var/lib/pgsql/16/data/pg_hba.conf | grep trust
-- Or via SQL:
SELECT * FROM pg_hba_file_rules WHERE auth_method = 'trust';
Remediation
# Replace 'trust' with 'scram-sha-256' in pg_hba.conf:
# local  all  all  scram-sha-256
# host   all  all  127.0.0.1/32  scram-sha-256

SELECT pg_reload_conf();
5.1.2 Ensure "password" Authentication Is Not Used (Automated)
L1 Auto
Description

"password" Authentication should not be used on the PostgreSQL 16 database server. Removing or disabling this component reduces the attack surface and prevents potential exploitation of unnecessary services or features.

Rationale

If "password" Authentication remains used, it presents an unnecessary risk vector that attackers could exploit. Removing or disabling unused components is a fundamental principle of secure system hardening.

Audit
SELECT * FROM pg_hba_file_rules WHERE auth_method = 'password';
-- Should return 0 rows ("password" sends cleartext)
Remediation
# Replace 'password' with 'scram-sha-256' in pg_hba.conf
# Requires password_encryption = scram-sha-256 in postgresql.conf
5.1.3 Ensure password_encryption Is scram-sha-256 (Automated)
L1 Auto
Description

This recommendation verifies that password_encryption Is scram-sha-256 on the PostgreSQL 16 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to password_encryption Is scram-sha-256 may leave the PostgreSQL 16 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
SHOW password_encryption;
-- Should be: scram-sha-256
Remediation
-- postgresql.conf:
password_encryption = 'scram-sha-256'

-- Reset existing md5 passwords after changing:
ALTER ROLE <rolename> PASSWORD '<new_password>';

5.2 SSL/TLS

▶
5.2.1 Ensure SSL Is Enabled (Automated)
L1 Auto
Description

This setting controls whether SSL is enabled on the PostgreSQL 16 database server. Enabling this feature strengthens the security posture by enforcing the recommended configuration via postgresql.conf, pg_hba.conf, or SQL commands.

Rationale

Without SSL enabled, the PostgreSQL 16 database server may lack critical protections against known attack vectors. Enabling this control mitigates risk and aligns the deployment with industry-accepted security baselines.

Audit
SHOW ssl;
-- Should be: on
Remediation
-- postgresql.conf:
ssl = on
ssl_cert_file = 'server.crt'
ssl_key_file = 'server.key'
ssl_ca_file = 'root.crt'
5.2.2 Ensure Only Strong SSL Ciphers Are Used (Automated)
L1 Auto
Description

This recommendation verifies that Only Strong SSL Ciphers Are Used on the PostgreSQL 16 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to only Strong SSL Ciphers Are Used may leave the PostgreSQL 16 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
SHOW ssl_ciphers;
SHOW ssl_min_protocol_version;
-- Should be TLSv1.2 or TLSv1.3 minimum
Remediation
-- postgresql.conf:
ssl_min_protocol_version = 'TLSv1.2'
ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL'
5.2.3 Ensure SSL Client Authentication Is Required (Manual)
L2 Manual
Description

This setting enforces that SSL Client Authentication is required on the PostgreSQL 16 database server. Making this mandatory ensures consistent security policy enforcement across the environment.

Rationale

Failure to sSL Client Authentication Is Required may leave the PostgreSQL 16 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check pg_hba.conf for 'hostssl' entries with 'cert' auth_method
grep hostssl /var/lib/pgsql/16/data/pg_hba.conf
Remediation
# pg_hba.conf:
hostssl all all 0.0.0.0/0 cert

6 — Replication & Backup

▶

6.1 Replication Settings

▶
6.1.1 Ensure Replication Users Are Minimized (Automated)
L1 Auto
Description

This recommendation verifies that Replication Users Are Minimized on the PostgreSQL 16 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to replication Users Are Minimized may leave the PostgreSQL 16 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
SELECT rolname FROM pg_roles WHERE rolreplication = true;
-- Should only show dedicated replication accounts
Remediation
ALTER ROLE <rolename> NOREPLICATION;
6.1.2 Ensure Replication Is Encrypted (Automated)
L1 Auto
Description

This setting ensures that Replication uses encryption on the PostgreSQL 16 database server. Encrypting data in transit and at rest protects sensitive information from interception and unauthorized disclosure.

Rationale

Without encryption, Replication may transmit or store sensitive information in cleartext, exposing it to interception, eavesdropping, or tampering. Encryption is a critical control for data confidentiality and integrity.

Audit
# Check pg_hba.conf for replication entries:
grep replication /var/lib/pgsql/16/data/pg_hba.conf
-- Should use hostssl, not host
Remediation
# pg_hba.conf:
hostssl replication replicator 10.0.0.0/24 scram-sha-256

6.2 Backup Configuration

▶
6.2.1 Ensure WAL Archiving Is Configured (Manual)
L1 Manual
Description

This recommendation addresses the proper configuration of WAL Archiving on the PostgreSQL 16 database server. Proper configuration ensures the component operates securely and in accordance with organizational security policies.

Rationale

Misconfiguration of WAL Archiving can lead to security gaps that may be exploited by attackers. A properly configured PostgreSQL 16 database server reduces exposure to both known vulnerabilities and configuration drift.

Audit
SHOW archive_mode;
SHOW archive_command;
-- archive_mode should be 'on', archive_command should be set
Remediation
-- postgresql.conf:
archive_mode = on
archive_command = 'cp %p /var/lib/pgsql/wal_archive/%f'
6.2.2 Ensure Regular Backups Are Tested (Manual)
L1 Manual
Description

This recommendation verifies that Regular Backups Are Tested on the PostgreSQL 16 database server. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to regular Backups Are Tested may leave the PostgreSQL 16 database server vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit

Review backup schedules, retention policies, and documented test results for pg_basebackup or pgBackRest operations.

Remediation
# Schedule regular base backups:
pg_basebackup -D /var/lib/pgsql/backups -Ft -z -P -U replicator

# Or use pgBackRest for enterprise backup management