Project: CloudNativePG (App Definition and Development / Database)
File: postgresql_conf.md

Users that are familiar with PostgreSQL are aware of the existence of the following three files to configure an instance: `postgresql.conf`: main run-time configuration file of PostgreSQL `pg_hba.conf`: clients authentication file `pg_ident.conf`: map external users to internal users Due to the concepts of declarative configuration and immutability of the PostgreSQL containers, users are not allowed to directly touch those files. Configuration is possible through the `postgresql` section of the `Cluster` resource definition by defining custom `postgresql.conf`, `pghba.conf`, and `pgident.conf` settings via the `parameters`, the `pghba`, and the `pgident` keys. These settings are the same across all instances. !!! Warning Please don't use the `ALTER SYSTEM` query to change the configuration of the PostgreSQL instances in an imperative way. Changing some of the options that are normally controlled by the operator might indeed lead to an unpredictable/unrecoverable state of the cluster. Moreover, `ALTER SYSTEM` changes are not replicated across the cluster. See below for details. A reference for custom settings usage is included in the samples, see . The PostgreSQL instance in the pod starts with a default `postgresql.conf` file, to which these settings are automatically added: ```text listen_addresses = '*' include custom.conf ``` The `custom.conf` file will contain the user-defined settings in the `postgresql` section, as in the following example: ```yaml postgresql: parameters: shared_buffers: "1GB" ``` !!! Seealso "PostgreSQL GUCs: Grand Unified Configuration" Refer to the PostgreSQL documentation for , also known as GUC (Grand Unified Configuration). Please note that CloudNativePG accepts only strings for the PostgreSQL parameters. The content of `custom.conf` is automatically generated and maintained by the operator by applying the following sections in this order: Global default parameters Default parameters that depend on the PostgreSQL major version User-provided parameters Fixed parameters The global default parameters are: ```text archive_mode = 'on' dynamicsharedmemory_type = 'posix' logging_collector = 'on' log_destination = 'csvlog' log_directory = '/controller/log' log_filename = 'postgres' logrotationage = '0' logrotationsize = '0' logtruncateon_rotation = 'false' maxparallelworkers = '32' maxreplicationslots = '32' maxworkerprocesses = '32' sharedmemorytype = 'mmap' # for PostgreSQL >= 12 only walkeepsize = '512MB' # for PostgreSQL >= 13 only walkeepsegments = '32' # for PostgreSQL <= 12 only wal_level = 'logical' walloghints = 'on' walsendertimeout = '5s' walreceivertimeout = '5s' ``` !!! Warning It is your duty to plan for WAL segments retention in your PostgreSQL cluster and properly configure either `walkeepsize` or `walkeepsegments`, depending on the server version, based on the expected and observed workloads. Alternatively, if the only streaming replication clients are the replica instances running in the High Availability cluster, you can take advantage of the replication slots feature, which adds support for replication slots at the cluster level. You can enable the feature with the `replicationSlots.highAvailability` option (for more information, please refer to the .) Without replication slots nor continuous backups in place, configuring `walkeepsize` or `walkeepsegments` is the only way to protect standbys from falling out of

If a standby did fall out of sync it would produce error messages like: `"could not receive data from WAL stream: ERROR: requested WAL segment has already been removed"`. This will require you to dedicate a part of your `PGDATA`, or the volume dedicated to storing WAL files, to keep older WAL segments for streaming replication purposes. The following parameters are fixed and exclusively controlled by the operator: ```text archive_command = '/controller/manager wal-archive %p' fullpagewrites = 'on' hot_standby = 'true' listen_addresses = '*' port = '5432' restartaftercrash = 'false' ssl = 'on' sslcafile = '/controller/certificates/client-ca.crt' sslcertfile = '/controller/certificates/server.crt' sslkeyfile = '/controller/certificates/server.key' unixsocketdirectories = '/controller/run' ``` Since the fixed parameters are added at the end, they can't be overridden by the user via the YAML configuration. Those parameters are required for correct WAL archiving and replication. The `primaryconninfo`, `restorecommand`, and `recoverytargettimeline` parameters are managed automatically by the operator according to the state of the instance in the cluster. ```text primary_conninfo = 'host=cluster-example-rw user=postgres dbname=postgres' recoverytargettimeline = 'latest' ``` The operator requires PostgreSQL to output its log in CSV format, and the instance manager automatically parses it and outputs it in JSON format. For this reason, all log settings in PostgreSQL are fixed and cannot be changed. For further information, please refer to the . The `sharedpreloadlibraries` option in PostgreSQL exists to specify one or more shared libraries to be pre-loaded at server start, in the form of a comma-separated list. Typically, it is used in PostgreSQL to load those extensions that need to be available to most database sessions in the whole system (e.g. `pgstatstatements`). In CloudNativePG the `sharedpreloadlibraries` option is empty by default. Although you can override the content of `sharedpreloadlibraries`, we recommend that only expert Postgres users take advantage of this option. !!! Important In case a specified library is not found, the server fails to start, preventing CloudNativePG from any self-healing attempt and requiring manual intervention. Please make sure you always test both the extensions and the settings of `sharedpreloadlibraries` if you plan to directly manage its content. CloudNativePG is able to automatically manage the content of the `sharedpreloadlibraries` option for some of the most used PostgreSQL extensions (see the section below for details). Specifically, as soon as the operator notices that a configuration parameter requires one of the managed libraries, it will automatically add the needed library. The operator will also remove the library as soon as no actual parameter requires it. !!! Important Please always keep in mind that removing libraries from `sharedpreloadlibraries` requires a restart of all instances in the cluster in order to be effective. You can provide additional `sharedpreloadlibraries` via `.spec.postgresql.sharedpreloadlibraries` as a list of strings: the operator will merge them with the ones that it automatically manages. As anticipated in the previous section, CloudNativePG automatically manages the content in `sharedpreloadlibraries` for some well-known and supported extensions. The current list includes: `auto_explain` `pgstatstatements` `pgaudit` `pgfailoverslots` Some of these libraries also require additional objects in a database before using them, normally views and/or functions managed via the `CREATE EXTENSION` command to be run in a database (the `DROP EXTENSION` command typically removes those

For such libraries, CloudNativePG automatically handles the creation and removal of the extension in all databases that accept a connection in the cluster, identified by the following query: ```sql SELECT datname FROM pg_database WHERE datallowconn ``` !!! Note The above query also includes template databases like `template1`. The extension provides a means for logging execution plans of slow statements automatically, without having to manually run `EXPLAIN` (helpful for tracking down un-optimized queries). You can enable `auto_explain` by adding to the configuration a parameter that starts with `auto_explain.` as in the following example excerpt (which automatically logs execution plans of queries that take longer than 10 seconds to complete): ```yaml postgresql: parameters: autoexplain.logmin_duration: "10s" ``` !!! Note Enabling auto_explain can lead to performance issues. Please refer to The extension is one of the most important capabilities available in PostgreSQL for real-time monitoring of queries. You can enable `pgstatstatements` by adding to the configuration a parameter that starts with `pgstatstatements.` as in the following example excerpt: ```yaml postgresql: parameters: pgstatstatements.max: "10000" pgstatstatements.track: all ``` As explained previously, the operator will automatically add `pgstatstatements` to `sharedpreloadlibraries` and run `CREATE EXTENSION IF NOT EXISTS pgstatstatements` on each database, enabling you to run queries against the `pgstatstatements` view. The `pgaudit` extension provides detailed session and/or object audit logging via the standard PostgreSQL logging facility. CloudNativePG has transparent and native support for on PostgreSQL clusters. For further information, please refer to the You can enable `pgaudit` by adding to the configuration a parameter that starts with `pgaudit.` as in the following example excerpt: ```yaml postgresql: parameters: pgaudit.log: "all, -misc" pgaudit.log_catalog: "off" pgaudit.log_parameter: "on" pgaudit.log_relation: "on" ``` The extension by EDB ensures that logical replication slots can survive a failover scenario. Failovers are normally implemented using physical streaming replication, like in the case of CloudNativePG. You can enable `pgfailoverslots` by adding to the configuration a parameter that starts with `pgfailoverslots.`: as explained above, the operator will transparently manage the `pgfailoverslots` entry in the `sharedpreloadlibraries` option depending on this. Please refer to for details on this extension. Additionally, for each database that you intend to you use with `pgfailoverslots` you need to add an entry in the `pg_hba` section that enables each replica to connect to the primary. For example, suppose that you want to use the `app` database with `pgfailoverslots`, you need to add this entry in the `pg_hba` section: ``` yaml postgresql: pg_hba: hostssl app streaming_replica all cert ``` `pg_hba` is a list of PostgreSQL Host Based Authentication rules used to create the `pg_hba.conf` used by the pods. !!! Important See the PostgreSQL documentation for . Since the first matching rule is used for authentication, the `pg_hba.conf` file generated by the operator can be seen as composed of four sections: Fixed rules User-defined rules Optional LDAP section Default rules Fixed rules: ```text local all all peer hostssl postgres streaming_replica all cert hostssl replication streaming_replica all cert ``` Default rules: ```text host all all all <default-authentication-method> ``` From PostgreSQL 14 the default value of the `password_encryption` database parameter is set to `scram-sha-256`. Because of that, the default authentication method is `scram-sha-256` from this PostgreSQL

PostgreSQL 13 and older will use `md5` as the default authentication method. The resulting `pg_hba.conf` will look like this: ```text local all all peer hostssl postgres streaming_replica all cert hostssl replication streaming_replica all cert <user defined rules> <user defined LDAP> host all all all scram-sha-256 # (or md5 for PostgreSQL version <= 13) ``` Inside the cluster manifest, `pg_hba` lines are added as list items in `.spec.postgresql.pg_hba`, as in the following excerpt: ``` yaml postgresql: pg_hba: hostssl app app 10.244.0.0/16 md5 ``` In the above example we are enabling access for the `app` user to the `app` database using MD5 password authentication (you can use `scram-sha-256` if you prefer) via a secure channel (`hostssl`). Under the `postgres` section of the cluster spec there is an optional `ldap` section available to define an LDAP configuration to be converted into a rule added into the `pg_hba.conf` file. This will support two modes: `simple bind` mode which requires specifying a `server`, `prefix` and `suffix` in the LDAP section and the `search+bind` mode which requires specifying `server`, `baseDN`, `binDN`, and a `bindPassword` which is a secret containing the ldap password. Additionally, in `search+bind` mode you have the option to specify a `searchFilter` or `searchAttribute`. If no `searchAttribute` is specified the default one of `uid` will be used. Additionally, both modes allow the specification of a `scheme` for ldapscheme and a `port`. Neither scheme nor port are required, however. This section filled out for search+bind could look as follows: ```yaml postgresql: ldap: server: 'openldap.default.svc.cluster.local' bindSearchAuth: baseDN: 'ou=org,dc=example,dc=com' bindDN: 'cn=admin,dc=example,dc=com' bindPassword: name: 'ldapBindPassword' key: 'data' searchAttribute: 'uid' ``` `pg_ident` is a list of PostgreSQL User Name Maps that CloudNativePG uses to generate and maintain the ident map file (known as `pg_ident.conf`) inside the data directory. !!! Important See the PostgreSQL documentation for . The `pg_ident.conf` file written by the operator is made up of the following two sections: Fixed rules User-defined rules Currently the only fixed rule, automatically generated by the operator, is: ```text local <postgres system user> postgres ``` The instance manager detects the user running the PostgreSQL instance and automatically adds a rule to map it to the `postgres` user in the database. If the `postgres` user is not properly configured inside the container, the instance manager will allow any local user to connect and then log a warning message like the following: ```text Unable to identify the current user. Falling back to insecure mapping. ``` The resulting `pg_ident.conf` will look like this: ```text local <postgres system user> postgres <user defined lines> ``` Inside the cluster manifest, `pg_ident` lines are added as list items in `.spec.postgresql.pg_ident`. For example: ``` yaml postgresql: pg_ident: "mymap /^(.*)@mydomain\\.com$ \\1" ``` You can apply configuration changes by editing the `postgresql` section of the `Cluster` resource. After the change, the cluster instances will immediately reload the configuration to apply the changes. If the change involves a parameter requiring a restart, the operator will perform a rolling

CloudNativePG strongly advocates employing the Cluster manifest as the exclusive method for altering the configuration of a PostgreSQL cluster. This approach guarantees coherence across the entire high-availability cluster and aligns with best practices for Infrastructure-as-Code. In CloudNativePG version 1.22 and onwards, the default configuration disables the use of `ALTER SYSTEM` on new Postgres clusters. This decision is rooted in the recognition of potential risks associated with this command. To enable the use of `ALTER SYSTEM`, you can explicitly set `.spec.postgresql.enableAlterSystem` to `true`. !!! Warning Proceed with caution when utilizing `ALTER SYSTEM`. This command operates directly on the connected instance and does not undergo replication. CloudNativePG assumes responsibility for certain fixed parameters and complete control over others, emphasizing the need for careful consideration. When `.spec.postgresql.enableAlterSystem` is configured as `false`, any attempt to execute `ALTER SYSTEM` will result in an error. The error message might resemble the following: ``` output ERROR: could not open file "postgresql.auto.conf": Permission denied ``` PostgreSQL supports a few implementations for dynamic shared memory management through the configuration option. In CloudNativePG we recommend to limit ourselves to any of the following two values: `posix`: which relies on POSIX shared memory allocated using `shm_open` (default setting) `sysv`: which is based on System V shared memory allocated via `shmget` In PostgreSQL, this setting is particularly important for memory allocation in parallel queries. For details, please refer to this . The default setting of `posix` should be enough in most cases, considering that the operator automatically mounts a memory-bound `EmptyDir` volume called `shm` under `/dev/shm`. You can verify the size of such volume inside the running Postgres container with: ```sh mount | grep shm ``` You should get something similar to the following output: ```console shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=) ``` If you would like to set a maximum size for the `shm` volume, you can do so by setting the `.spec.ephemeralVolumesSizeLimit.shm` field in the `Cluster` resource. For example: ```yaml spec: ephemeralVolumesSizeLimit: shm: 1Gi ``` In case your Kubernetes cluster has a high enough value for the `SHMMAX` and `SHMALL` parameters, you can also set: ```yaml dynamicsharedmemory_type: "sysv" ``` You can check the `SHMMAX`/`SHMALL` from inside a PostgreSQL container, by running: ```sh ipcs -lm ``` For example: ```console Shared Memory Limits -- max number of segments = 4096 max seg size (kbytes) = 18014398509465599 max total shared memory (kbytes) = 18014398509481980 min seg size (bytes) = 1 ``` As you can see, the very high number of `max total shared memory` recommends setting `dynamicsharedmemory_type` to `sysv`. An alternate method is to run: ```sh cat /proc/sys/kernel/shmall cat /proc/sys/kernel/shmmax ``` Some PostgreSQL configuration parameters should be managed exclusively by the operator. The operator prevents the user from setting them using a webhook. Users are not allowed to set the following configuration parameters in the `postgresql` section: `allowsystemtable_mods` `archivecleanupcommand` `archive_command` `archive_mode` `bonjour` `bonjour_name` `cluster_name` `config_file` `data_directory` `datasyncretry` `event_source` `externalpidfile` `fullpagewrites` `hba_file` `hot_standby` `ident_file` `jit_provider` `listen_addresses` `log_destination` `log_directory` `logfilemode` `log_filename` `logrotationage` `logrotationsize` `logtruncateon_rotation` `logging_collector` `port` `primary_conninfo` `primaryslotname` `promotetriggerfile` `recoveryendcommand` `recoveryminapply_delay` `recovery_target` `recoverytargetaction` `recoverytargetinclusive` `recoverytargetlsn` `recoverytargetname` `recoverytargettime` `recoverytargettimeline` `recoverytargetxid` `restartaftercrash` `restore_command` `sharedpreloadlibraries` `ssl` `sslcafile` `sslcertfile` `sslcrlfile` `ssldhparams_file` `sslecdhcurve` `sslkeyfile` `sslpassphrasecommand` `sslpassphrasecommandsupportsreload` `sslpreferserver_ciphers` `statstempdirectory` `synchronousstandbynames` `syslog_facility` `syslog_ident` `syslogsequencenumbers` `syslogsplitmessages` `unixsocketdirectories` `unixsocketgroup` `unixsocketpermissions`