Upgrade an unmanaged PostgreSQL installation

You can upgrade a Puppet Enterprise (PE) installation that relies on an unmanaged PostgreSQL database.

Upgrade PostgreSQL before upgrading to PE 2025.11 or later

  • PE 2025.11 and later requires PostgreSQL 17 for unmanaged PostgreSQL deployments.

  • Unlike PE-managed installations, Puppet Enterprise does not upgrade unmanaged PostgreSQL servers. You must upgrade PostgreSQL separately before upgrading PE.

  • If you attempt to upgrade PE while PostgreSQL is still running version 14, puppet infrastructure configure --upgrade-from detects the version mismatch and exits before making any changes to PE.

The configuration syntax for postgresql.conf and pg_hba.conf is unchanged between PostgreSQL 14 and PostgreSQL 17. Existing connection settings can be used without modification after upgrading PostgreSQL.
These steps are for upgrading to PE 2023.7 or later from an earlier 2023.y version, or from PE 2021.7.z. Due to a significant PostgreSQL upgrade in PE 2021.6, if you want to upgrade from 2021.6 or earlier, follow the instructions linked in the Upgrade paths topic to upgrade from 2021.6 or earlier to 2021.7.z before continuing to 2023.y.
Before you begin:

Before starting the PE upgrade, verify the following on your external PostgreSQL server:

  • PostgreSQL 17 is running. Confirm with psql --version.

  • Required extensions are installed for PG17. See PostgreSQL extension requirements. Note that extensions installed under PG14 do not carry forward — you must install the PG17-compatible versions of pg_repack (and pglogical, for HA) on the new PG17 instance.

  • Backups are complete. Take a full backup of your PE installation and PostgreSQL data before upgrading either PostgreSQL or PE.

  • Disk space is available (if upgrading in-place via pg_upgrade). An in-place major-version upgrade retains both the old and new data directories until you remove the old one. Ensure you have at least 1.1× the current PostgreSQL data directory size in free disk space.

Recommended upgrade sequence

  1. Stop PE services on the primary server before starting the PostgreSQL upgrade:

    puppet resource service pe-puppetdb ensure=stopped
    puppet resource service pe-puppetserver ensure=stopped
    puppet resource service pe-console-services ensure=stopped
    puppet resource service pe-orchestration-services ensure=stopped
  2. Upgrade PostgreSQL from 14 to 17 using your organization's standard procedure (for example, pg_upgrade, or a logical dump/restore via pg_dump/pg_restore). For full details on pg_upgrade, see the PostgreSQL documentation.

  3. Install PG17-compatible extensions on the new PostgreSQL 17 instance. The postgresql17-contrib package covers pgcrypto, pg_trgm, citext, and pg_stat_statements. Install pg_repack >= 1.5.0 separately. For HA installations, install pglogical >= 2.4.4.

  4. Start PostgreSQL 17 and verify that your PE databases are accessible.

  5. Proceed with the PE 2025.11 or later upgrade using the standard upgrade steps (create the pe-hac database, run the installer with -s, upgrade compilers, and so on).

Collation integrity considerations

For most customers performing an in-place PostgreSQL upgrade (same host, same operating system version), no collation issues will occur. PostgreSQL 14 did not record collation versions for libc/glibc-backed collations (the default for en_US.UTF-8 on Linux), so PostgreSQL 17 stamps the current system collation version at upgrade time — the recorded and runtime versions always match on a same-OS upgrade, and no index corruption occurs.

The exception is if you are simultaneously performing an OS major version upgrade (for example, RHEL 8 → RHEL 9, Ubuntu 22.04 → 24.04, or SLES 15 SP5 → SP6) in the same maintenance window as the PostgreSQL upgrade. An OS major version upgrade can change the glibc collation library version, which may have affected indexes built under PG14. Because PostgreSQL 17 re-stamps the collation version to the current glibc at upgrade time, it will not warn about this condition automatically.

Verify database indexes after an operating system upgrade

If you upgraded your OS major version in the same maintenance window as your PostgreSQL upgrade:

  1. After completing the PE upgrade, run pg_amcheck against your PE databases to check for index inconsistencies. pg_amcheck ships in the postgresql17-contrib package, which is already a prerequisite for unmanaged installs. Run this as the PostgreSQL superuser on the external database host:

# RHEL / Rocky Linux / Oracle Linux
/usr/pgsql-17/bin/pg_amcheck --all --username postgres

# Debian / Ubuntu
/usr/lib/postgresql/17/bin/pg_amcheck --all --username postgres

Substitute your actual superuser account name if it differs from postgres. --all checks all databases on the server.

If pg_amcheck reports any inconsistencies, run REINDEX DATABASE <database_name> on the affected databases.

Complete setup relevant to your chosen authentication method

  1. Complete setup relevant to your chosen authentication method.
    • Password based authentication: In pe.conf, specify the database password for the pe-hac user as shown in the following example (replacing PASSWORD with the actual password you want to use):
      "puppet_enterprise::hac_database_password": "PASSWORD" 

      Then use your PostgreSQL client to run the following SQL commands (replacing <PASSWORD>):

      CREATE ROLE "pe-hac" LOGIN NOCREATEROLE NOCREATEDB SUPERUSER CONNECTION LIMIT -1 PASSWORD '<PASSWORD>';
      CREATE ROLE "pe-hac-read" LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1 PASSWORD '<PASSWORD>';
      CREATE ROLE "pe-hac-write" LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1 PASSWORD '<PASSWORD>';
      CREATE DATABASE "pe-hac" OWNER "pe-hac" ENCODING 'utf8' LC_CTYPE 'en_US.utf8' LC_COLLATE 'en_US.utf8' template template0;
      REVOKE CONNECT ON DATABASE "pe-hac" FROM public;
      GRANT CONNECT ON DATABASE "pe-hac" TO "pe-hac-read";
      ALTER DEFAULT PRIVILEGES FOR USER "pe-hac" IN SCHEMA "public" GRANT SELECT ON TABLES TO "pe-hac-read";
      ALTER DEFAULT PRIVILEGES FOR USER "pe-hac" IN SCHEMA "public" GRANT ALL PRIVILEGES ON TABLES TO "pe-hac-write";
      ALTER DEFAULT PRIVILEGES FOR USER "pe-hac" IN SCHEMA "public" GRANT ALL PRIVILEGES ON SEQUENCES TO "pe-hac-write";
      ALTER DEFAULT PRIVILEGES FOR USER "pe-hac" IN SCHEMA "public" GRANT ALL PRIVILEGES ON FUNCTIONS TO "pe-hac-write";
    • Certificate based authentication: Add the following entries to pg_hba.conf, replacing <PRIMARY_CERTNAME> with the certname of your primary server:
      hostssl pe-hac  pe-hac 0.0.0.0/0 cert map=pe-hac-pe-hac-map clientcert=verify-full
      hostssl pe-hac  pe-hac-read 0.0.0.0/0 cert map=pe-hac-pe-hac-read-map clientcert=verify-full
      hostssl pe-hac  pe-hac-write 0.0.0.0/0 cert map=pe-hac-pe-hac-write-map clientcert=verify-full

      Add the following lines to pg_ident.conf (replacing <PRIMARY_CERTNAME>):

      pe-hac-pe-hac-map <PRIMARY_CERTNAME> pe-hac
      pe-hac-pe-hac-read-map <PRIMARY_CERTNAME> pe-hac-read
      pe-hac-pe-hac-write-map <PRIMARY_CERTNAME> pe-hac-write

      Then use your PostgreSQL client to run the following SQL commands:

      CREATE ROLE "pe-hac" LOGIN NOCREATEROLE NOCREATEDB SUPERUSER CONNECTION LIMIT -1;
      CREATE ROLE "pe-hac-read" LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1;
      CREATE ROLE "pe-hac-write" LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER CONNECTION LIMIT -1;
      CREATE DATABASE "pe-hac" OWNER "pe-hac" ENCODING 'utf8' LC_CTYPE 'en_US.utf8' LC_COLLATE 'en_US.utf8' template template0;
      REVOKE CONNECT ON DATABASE "pe-hac" FROM public;
      GRANT CONNECT ON DATABASE "pe-hac" TO "pe-hac-read";
      ALTER DEFAULT PRIVILEGES FOR USER "pe-hac" IN SCHEMA "public" GRANT SELECT ON TABLES TO "pe-hac-read";
      ALTER DEFAULT PRIVILEGES FOR USER "pe-hac" IN SCHEMA "public" GRANT ALL PRIVILEGES ON TABLES TO "pe-hac-write";
      ALTER DEFAULT PRIVILEGES FOR USER "pe-hac" IN SCHEMA "public" GRANT ALL PRIVILEGES ON SEQUENCES TO "pe-hac-write";
      ALTER DEFAULT PRIVILEGES FOR USER "pe-hac" IN SCHEMA "public" GRANT ALL PRIVILEGES ON FUNCTIONS TO "pe-hac-write";
  2. Download the tarball for your operating system and architecture. Optionally, you can verify the installation package.
  3. Run tar -xf <TARBALL> to unpack the installation tarball.

    You need about 1 GB of space to untar the installer.

  4. From the installer directory on your primary server, run sudo ./puppet-enterprise-installer -s to start the installer, and then follow the CLI instructions to complete your server upgrade.
    • The -s flag tells the installer to skip database checks.
    • To specify a different pe.conf file than the existing file, use the -c flag as shown here:

      sudo ./puppet-enterprise-installer -c <FULL_PATH_TO_pe.conf>

      The -c flag tells the installer to back up the previous pe.conf file to /etc/puppetlabs/enterprise/conf.d/<TIMESTAMP>.conf and create a pe.conf file at /etc/puppetlabs/enterprise/conf.d/pe.conf.

  5. To upgrade compilers, log in to your primary server as root and run one of these commands:
    • To upgrade specific compilers, run:
      sudo puppet infrastructure upgrade compiler <COMPILER_FQDN-1>,<COMPILER_FQDN-2>
    • To upgrade all compilers simultaneously, run:
      sudo puppet infrastructure upgrade compiler --all
    • To specify an authentication token location other than the default location, include --token-file <PATH_TO_TOKEN> in the command as shown here:
      sudo puppet infrastructure upgrade compiler <COMPILER_FQDN> --token-file <PATH_TO_TOKEN>
  6. Upgrade the following additional PE infrastructure components:
    • Agents
    • PE client tools: On unmanaged nodes, you must re-install the client tools version that matches the PE version you upgraded to. On managed nodes and infrastructure nodes, client tools are automatically updated when you upgrade PE.
  7. Optional: Remove previous PE packages from all infrastructure nodes. On your primary server, run: puppet infrastructure run remove_old_pe_packages.

    All packages earlier than the current version are removed by default. To remove specific versions, append pe_version=<VERSION_NUMBER> to the command.

What to do next
Don't use CONCURRENTLY with PostgreSQL 14.0 through 14.3. However, if you do, ensure that you REINDEX without using CONCURRENTLY.