From 91da84a671fff1f237617c5d281c815a6fc88251 Mon Sep 17 00:00:00 2001 From: "thomas.boussekey" Date: Thu, 2 Apr 2026 16:24:16 +0200 Subject: [PATCH 1/5] feat: add pg_repack container image Adds the `pg_repack` extension, a tool for online reorganization of tables and indexes. It allows to release BLOAT on heavily updated relations. Closes #170 Signed-off-by: thomas.boussekey --- pgrepack/Dockerfile | 50 +++++++++++++++++++ pgrepack/README.md | 111 ++++++++++++++++++++++++++++++++++++++++++ pgrepack/metadata.hcl | 98 +++++++++++++++++++++++++++++++++++++ 3 files changed, 259 insertions(+) create mode 100644 pgrepack/Dockerfile create mode 100644 pgrepack/README.md create mode 100644 pgrepack/metadata.hcl diff --git a/pgrepack/Dockerfile b/pgrepack/Dockerfile new file mode 100644 index 0000000..fab731b --- /dev/null +++ b/pgrepack/Dockerfile @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: Copyright © contributors to CloudNativePG, established as CloudNativePG a Series of LF Projects, LLC. +# SPDX-License-Identifier: Apache-2.0 + + +ARG BASE=ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie +FROM $BASE AS builder + +ARG PG_MAJOR +ARG EXT_VERSION + +USER 0 + +# TODO: Remove this comment block after customizing the Dockerfile +# Instructions: +# 1. Remove all TODO comment blocks after completing the customization. +# 2. Uncomment and customize the COPY/RUN commands below. +# 3. If your extension requires additional system libraries, ensure they are +# copied to /lib. + +# Install extension via `apt-get` +# RUN apt-get update && apt-get install -y --no-install-recommends \ +# "postgresql-${PG_MAJOR}-pg_repack=${EXT_VERSION}" + +FROM scratch +ARG PG_MAJOR + +# Licenses +# TODO: Uncomment and customize the COPY command below +# Including license files is essential for legal compliance and transparency. +# It ensures proper attribution to original authors, fulfills open source license +# requirements, and enables automated compliance scanning tools to verify licensing. +# COPY --from=builder /usr/share/doc/postgresql-${PG_MAJOR}-pg_repack/copyright /licenses/postgresql-${PG_MAJOR}-pg_repack/ + +# Libraries +# TODO: Uncomment and customize the COPY command below +# Include the extension's shared objects and related dependencies under the /lib directory. +# CNPG will configure PostgreSQL to locate these libraries at runtime by configuring +# the "dynamic_library_path" GUC to include this path. +# For more details, see: https://cloudnative-pg.io/docs/current/imagevolume_extensions#how-it-works +# COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/pg_repack* /lib/ + +# Share +# TODO: Uncomment and customize the COPY command below +# Include the extension's SQL scripts and control files under the /share/extension directory. +# CNPG will configure PostgreSQL to include this path via the "extension_control_path" GUC to +# seamlessly find and manage the current extension. +# For more details, see: https://cloudnative-pg.io/docs/current/imagevolume_extensions#how-it-works +# COPY --from=builder /usr/share/postgresql/${PG_MAJOR}/extension/pg_repack* /share/extension/ + +USER 65532:65532 diff --git a/pgrepack/README.md b/pgrepack/README.md new file mode 100644 index 0000000..337603e --- /dev/null +++ b/pgrepack/README.md @@ -0,0 +1,111 @@ +# Pg_repack + + + + +The pg_repack PostgreSQL extension provides a binary tool that can perform online operation that can remove bloat from tables and indexes. For more information, see the [official documentation](https://reorg.github.io/pg_repack/). + +## Usage + + + +### 1. Add the pg_repack extension image to your Cluster + +Define the `pg_repack` extension under the `postgresql.extensions` section of +your `Cluster` resource. For example: + +```yaml +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: cluster-pg_repack +spec: + imageName: ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie + instances: 1 + + storage: + size: 1Gi + + postgresql: + extensions: + - name: pg_repack + image: + # renovate: suite=trixie-pgdg depName=postgresql-18-pg_repack + reference: ghcr.io/cloudnative-pg/pg_repack:1.0-18-trixie +``` + +### 2. Enable the extension in a database + +You can install `pg_repack` in a specific database by creating or updating a +`Database` resource. For example, to enable it in the `app` database: + +```yaml +apiVersion: postgresql.cnpg.io/v1 +kind: Database +metadata: + name: cluster-pg_repack-app +spec: + name: app + owner: app + cluster: + name: cluster-pg_repack + extensions: + - name: pg_repack + # renovate: suite=trixie-pgdg depName=postgresql-18-pg_repack extractVersion=^(?\d+\.\d+\.\d+) + version: '1.0' +``` + + + +### 3. Verify installation + +Once the database is ready, connect to it with `psql` and run: + +```sql +\dx +``` + +You should see `pg_repack` listed among the installed extensions. + +## Contributors + +This extension is maintained by: + +- FirstName LastName (@GitHub_Handle) + +The maintainers are responsible for: + +- Monitoring upstream releases and security vulnerabilities. +- Ensuring compatibility with supported PostgreSQL versions. +- Reviewing and merging contributions specific to this extension's container + image and lifecycle. + +--- + +## Licenses and Copyright + +This container image contains software that may be licensed under various +open-source licenses. + +All relevant license and copyright information for the `pg_repack` extension +and its dependencies are bundled within the image at: + +```text +/licenses/ +``` + +By using this image, you agree to comply with the terms of the licenses +contained therein. diff --git a/pgrepack/metadata.hcl b/pgrepack/metadata.hcl new file mode 100644 index 0000000..cab0731 --- /dev/null +++ b/pgrepack/metadata.hcl @@ -0,0 +1,98 @@ +# SPDX-FileCopyrightText: Copyright © contributors to CloudNativePG, established as CloudNativePG a Series of LF Projects, LLC. +# SPDX-License-Identifier: Apache-2.0 +metadata = { + name = "pgrepack" + sql_name = "pg_repack" + + # TODO: Remove this comment block after customizing the file. + # `image_name`: MUST be unique across the container registry because + # it identifies the image (e.g. ghcr.io/cloudnative-pg/) + image_name = "pgrepack" + + # TODO: Remove this comment block after customizing the file. + # `licenses`: A list of SPDX identifiers representing the main software's licenses. + # Formatting Rules: + # - Must be a list of strings: ["MIT", "Apache-2.0"] + # - Use SPDX IDs exactly as they appear at https://spdx.org/licenses/ + # - These are automatically joined with " AND " to populate the OCI label + # org.opencontainers.image.licenses + # Warning: the ghcr.io registry requires labels < 256 characters + # Examples: "Apache-2.0", "PostgreSQL", "MIT". + licenses = ["BSD-3-Clause"] + + # TODO: Remove this comment block after customizing the file. + # `shared_preload_libraries`: list libraries to be added to + # `shared_preload_libraries` in Postgres. Usually empty. + # Used in tests. + # Example: ["pgaudit"]. + shared_preload_libraries = ["pg_repack"] + + # TODO: Remove this comment block after customizing the file. + # `extension_control_path`: if EMPTY (`[]`), the operator follows the CNPG + # convention and will add the image's `share` directory to + # `extension_control_path`. Usually empty. + # Used in tests and to generate image catalogs. + # See: https://cloudnative-pg.io/docs/current/imagevolume_extensions#image-specifications + extension_control_path = [] + + # TODO: Remove this comment block after customizing the file. + # `dynamic_library_path`: if EMPTY (`[]`) the operator will add the image's + # `lib` directory to `dynamic_library_path`. Usually empty. + # Used in tests and to generate image catalogs. + dynamic_library_path = [] + + # TODO: Remove this comment block after customizing the file. + # `ld_library_path`: this SHOULD be defined when your extension needs + # additional (usually system) libraries loaded into Postgres before startup. + # If left EMPTY (`[]`) the operator will NOT alter `ld_library_path`. See the + # `postgis` extension metadata for an example usage. Usually empty. + # Used in tests and to generate image catalogs. + ld_library_path = [] + + # TODO: Remove this comment block after customizing the file. + # `bin_path`: this SHOULD be defined when your extension needs executables + # to be present in the PATH of the PostgreSQL process to function properly. + # For most extensions, the default empty list (`[]`) is correct and the + # operator will NOT alter `PATH`. + # Each path provided is appended to the `PATH` environment variable for the + # Postgres process. Used in tests and to generate image catalogs. + bin_path = [] + + # TODO: Remove this comment block after customizing the file. + # `auto_update_os_libs`: set to true to allow the maintenance tooling + # to update OS libraries automatically; look at the `postgis` example. + auto_update_os_libs = false + + # TODO: Remove this comment block after customizing the file. + # `required_extensions`: must contain the name(s) of the sibling + # folders in this repository that contain a required extension. + required_extensions = [] + + # TODO: Remove this comment block after customizing the file. + # `create_extension`: if set to `true` (default), the test suite will + # automatically run `CREATE EXTENSION` for this project during E2E tests. + # Set to `false` if the image only provides libraries or tools without + # a formal Postgres extension object. + create_extension = true + + versions = { + trixie = { + "18" = { + // renovate: suite=trixie-pgdg depName=postgresql-18-pg_repack + package = "1.5.3-1.pgdg13+1" + // Examples: \d+\.\d+ for major.minor (e.g., "18.0"), \d+\.\d+\.\d+ for major.minor.patch (e.g., "0.8.2") + // renovate: suite=trixie-pgdg depName=postgresql-18-pg_repack extractVersion=^(?\d+\.\d+\.\d+) + sql = "1.5.3" + } + } + bookworm = { + "18" = { + // renovate: suite=bookworm-pgdg depName=postgresql-18-pg_repack + package = "1.5.3-1.pgdg12+1" + // Examples: \d+\.\d+ for major.minor (e.g., "18.0"), \d+\.\d+\.\d+ for major.minor.patch (e.g., "0.8.2") + // renovate: suite=bookworm-pgdg depName=postgresql-18-pg_repack extractVersion=^(?\d+\.\d+\.\d+) + sql = "1.5.3" + } + } + } +} From ce7d19dc21f016e8462aecc34a0b4639044aa9bd Mon Sep 17 00:00:00 2001 From: "thomas.boussekey" Date: Thu, 2 Apr 2026 16:33:31 +0200 Subject: [PATCH 2/5] docs: add README part for pg_repack Signed-off-by: thomas.boussekey --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0b9b4ed..f8a51e1 100644 --- a/README.md +++ b/README.md @@ -36,10 +36,10 @@ they are maintained by their respective authors, and PostgreSQL Debian Group | :--- | :--- | :--- | | **[pgAudit](pgaudit)** | PostgreSQL audit extension | [github.com/pgaudit/pgaudit](https://github.com/pgaudit/pgaudit) | | **[pg_crash](pg-crash)** | **Disruptive** fault injection and chaos engineering extension | [github.com/cybertec-postgresql/pg_crash](https://github.com/cybertec-postgresql/pg_crash) | +| **[pg_repack](pgrepack)** | re-organize bloated tables and indexes | [github.com/reorg/pg_repack](https://github.com/reorg/pg_repack) | | **[pgvector](pgvector)** | Vector similarity search for PostgreSQL | [github.com/pgvector/pgvector](https://github.com/pgvector/pgvector) | | **[PostGIS](postgis)** | Geospatial database extension for PostgreSQL | [postgis.net/](https://postgis.net/) | - Extensions are provided only for the OS versions already built by the [`cloudnative-pg/postgres-containers`](https://github.com/cloudnative-pg/postgres-containers) project, specifically Debian `stable` and `oldstable`. From 3f0f9859326a8062920ff524cbf61d4d3231cf6c Mon Sep 17 00:00:00 2001 From: "thomas.boussekey" Date: Thu, 2 Apr 2026 16:41:53 +0200 Subject: [PATCH 3/5] chore: add entries in bake.yml Signed-off-by: thomas.boussekey --- .github/workflows/bake.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/bake.yml b/.github/workflows/bake.yml index efbbfb0..a7a3dfe 100644 --- a/.github/workflows/bake.yml +++ b/.github/workflows/bake.yml @@ -55,6 +55,9 @@ jobs: pg-crash: - 'pg-crash/**' - *shared + pgrepack: + - 'pgrepack/**' + - *shared # Compute a matrix containing the list of all extensions that have been modified - name: Compute matrix From dc8601bbd159d92ac6206b0b3b650462cb49fb58 Mon Sep 17 00:00:00 2001 From: "thomas.boussekey" Date: Thu, 2 Apr 2026 17:02:36 +0200 Subject: [PATCH 4/5] fix: add missing variable in metadata.hcl Signed-off-by: thomas.boussekey --- pgrepack/metadata.hcl | 65 +++---------------------------------------- 1 file changed, 4 insertions(+), 61 deletions(-) diff --git a/pgrepack/metadata.hcl b/pgrepack/metadata.hcl index cab0731..b3cdc08 100644 --- a/pgrepack/metadata.hcl +++ b/pgrepack/metadata.hcl @@ -3,78 +3,21 @@ metadata = { name = "pgrepack" sql_name = "pg_repack" - - # TODO: Remove this comment block after customizing the file. - # `image_name`: MUST be unique across the container registry because - # it identifies the image (e.g. ghcr.io/cloudnative-pg/) image_name = "pgrepack" - - # TODO: Remove this comment block after customizing the file. - # `licenses`: A list of SPDX identifiers representing the main software's licenses. - # Formatting Rules: - # - Must be a list of strings: ["MIT", "Apache-2.0"] - # - Use SPDX IDs exactly as they appear at https://spdx.org/licenses/ - # - These are automatically joined with " AND " to populate the OCI label - # org.opencontainers.image.licenses - # Warning: the ghcr.io registry requires labels < 256 characters - # Examples: "Apache-2.0", "PostgreSQL", "MIT". licenses = ["BSD-3-Clause"] - - # TODO: Remove this comment block after customizing the file. - # `shared_preload_libraries`: list libraries to be added to - # `shared_preload_libraries` in Postgres. Usually empty. - # Used in tests. - # Example: ["pgaudit"]. shared_preload_libraries = ["pg_repack"] - - # TODO: Remove this comment block after customizing the file. - # `extension_control_path`: if EMPTY (`[]`), the operator follows the CNPG - # convention and will add the image's `share` directory to - # `extension_control_path`. Usually empty. - # Used in tests and to generate image catalogs. - # See: https://cloudnative-pg.io/docs/current/imagevolume_extensions#image-specifications extension_control_path = [] - - # TODO: Remove this comment block after customizing the file. - # `dynamic_library_path`: if EMPTY (`[]`) the operator will add the image's - # `lib` directory to `dynamic_library_path`. Usually empty. - # Used in tests and to generate image catalogs. dynamic_library_path = [] - - # TODO: Remove this comment block after customizing the file. - # `ld_library_path`: this SHOULD be defined when your extension needs - # additional (usually system) libraries loaded into Postgres before startup. - # If left EMPTY (`[]`) the operator will NOT alter `ld_library_path`. See the - # `postgis` extension metadata for an example usage. Usually empty. - # Used in tests and to generate image catalogs. ld_library_path = [] - - # TODO: Remove this comment block after customizing the file. - # `bin_path`: this SHOULD be defined when your extension needs executables - # to be present in the PATH of the PostgreSQL process to function properly. - # For most extensions, the default empty list (`[]`) is correct and the - # operator will NOT alter `PATH`. - # Each path provided is appended to the `PATH` environment variable for the - # Postgres process. Used in tests and to generate image catalogs. bin_path = [] - - # TODO: Remove this comment block after customizing the file. - # `auto_update_os_libs`: set to true to allow the maintenance tooling - # to update OS libraries automatically; look at the `postgis` example. auto_update_os_libs = false - - # TODO: Remove this comment block after customizing the file. - # `required_extensions`: must contain the name(s) of the sibling - # folders in this repository that contain a required extension. required_extensions = [] - - # TODO: Remove this comment block after customizing the file. - # `create_extension`: if set to `true` (default), the test suite will - # automatically run `CREATE EXTENSION` for this project during E2E tests. - # Set to `false` if the image only provides libraries or tools without - # a formal Postgres extension object. create_extension = true + # TODO: Add these missing variables in the template + env = {} + postgresql_parameters = {} + versions = { trixie = { "18" = { From 0f6acaa12b06b88ef48ad44c99441edcec56a2bd Mon Sep 17 00:00:00 2001 From: "thomas.boussekey" Date: Thu, 2 Apr 2026 18:48:43 +0200 Subject: [PATCH 5/5] fix: uncomment useful lines in Dockerfile Signed-off-by: thomas.boussekey --- pgrepack/Dockerfile | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/pgrepack/Dockerfile b/pgrepack/Dockerfile index fab731b..5929408 100644 --- a/pgrepack/Dockerfile +++ b/pgrepack/Dockerfile @@ -18,33 +18,19 @@ USER 0 # copied to /lib. # Install extension via `apt-get` -# RUN apt-get update && apt-get install -y --no-install-recommends \ -# "postgresql-${PG_MAJOR}-pg_repack=${EXT_VERSION}" +RUN apt-get update && apt-get install -y --no-install-recommends \ + "postgresql-${PG_MAJOR}-repack=${EXT_VERSION}" FROM scratch ARG PG_MAJOR # Licenses -# TODO: Uncomment and customize the COPY command below -# Including license files is essential for legal compliance and transparency. -# It ensures proper attribution to original authors, fulfills open source license -# requirements, and enables automated compliance scanning tools to verify licensing. -# COPY --from=builder /usr/share/doc/postgresql-${PG_MAJOR}-pg_repack/copyright /licenses/postgresql-${PG_MAJOR}-pg_repack/ +COPY --from=builder /usr/share/doc/postgresql-${PG_MAJOR}-repack/copyright /licenses/postgresql-${PG_MAJOR}-repack/ # Libraries -# TODO: Uncomment and customize the COPY command below -# Include the extension's shared objects and related dependencies under the /lib directory. -# CNPG will configure PostgreSQL to locate these libraries at runtime by configuring -# the "dynamic_library_path" GUC to include this path. -# For more details, see: https://cloudnative-pg.io/docs/current/imagevolume_extensions#how-it-works -# COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/pg_repack* /lib/ +COPY --from=builder /usr/lib/postgresql/${PG_MAJOR}/lib/pg_repack* /lib/ # Share -# TODO: Uncomment and customize the COPY command below -# Include the extension's SQL scripts and control files under the /share/extension directory. -# CNPG will configure PostgreSQL to include this path via the "extension_control_path" GUC to -# seamlessly find and manage the current extension. -# For more details, see: https://cloudnative-pg.io/docs/current/imagevolume_extensions#how-it-works -# COPY --from=builder /usr/share/postgresql/${PG_MAJOR}/extension/pg_repack* /share/extension/ +COPY --from=builder /usr/share/postgresql/${PG_MAJOR}/extension/pg_repack* /share/extension/ USER 65532:65532