From 0645c118cabd77f5d85a08fa8615d428a728ff5b Mon Sep 17 00:00:00 2001 From: Jacob Cox Date: Thu, 29 Oct 2026 14:27:29 -0600 Subject: [PATCH 1/6] =?UTF-8?q?docs:=20group=20c=20=E2=80=94=20HA=20databa?= =?UTF-8?q?se=20moves=20to=20patroni-postgres:0.8=20(pgvector=200.8.7),=20?= =?UTF-8?q?upgrade=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WZ5WWhTn9mEkPY7cLt1cr4 --- template-catalog/templates/cdc-pipeline.mdx | 6 +++++- template-catalog/templates/chatwoot.mdx | 7 +++++++ template-catalog/templates/glitchtip.mdx | 5 +++++ template-catalog/templates/grafana.mdx | 5 +++++ template-catalog/templates/listmonk.mdx | 5 +++++ template-catalog/templates/metabase.mdx | 5 +++++ template-catalog/templates/nocodb.mdx | 5 +++++ template-catalog/templates/polaris.mdx | 5 +++++ template-catalog/templates/temporal.mdx | 5 +++++ template-catalog/templates/twenty.mdx | 5 +++++ template-catalog/templates/unleash.mdx | 5 +++++ 11 files changed, 57 insertions(+), 1 deletion(-) diff --git a/template-catalog/templates/cdc-pipeline.mdx b/template-catalog/templates/cdc-pipeline.mdx index fb1a74bc..51d286a0 100644 --- a/template-catalog/templates/cdc-pipeline.mdx +++ b/template-catalog/templates/cdc-pipeline.mdx @@ -194,7 +194,7 @@ postgres-highly-available: maxCpu: 1 maxMemory: 2Gi - image: controlplanecorporation/patroni-postgres:0.7 + image: controlplanecorporation/patroni-postgres:0.8 # pgvector 0.8.7 (CVE-2026-103484); tags 0.1-0.7 are refused walLevel: logical # Debezium's pgoutput decoding needs it; the chart refuses anything else @@ -549,6 +549,10 @@ This upgrade path has not been verified end to end. Snapshot the database volume The bundled components move too: PostgreSQL Highly Available 2.5.0 → 2.8.0, Kafka 4.0.1 → 4.3.0 (the brokers roll, which also applies the new super user), and Kafbat UI keeps the setting your release runs with. +### Upgrading from 1.1.1 or earlier + +1.1.2 moves the database to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7 (CVE-2026-103484). The database members restart and nothing limits that rollout, so expect a brief interruption of writes while the leader changes. The upgrade does not redeploy Debezium; it restarts once when the database leader changes and resumes from its failover replication slot, so changes around the leader change may be delivered twice. Upgrade in a quiet window. Existing data needs nothing. If you pinned `postgres-highly-available.image`, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. The pipeline does not use the `vector` extension; if you created it in your database, run `ALTER EXTENSION vector UPDATE;` there, which only updates the version `\dx` reports. + ### Rotating the Database Password in HA Mode The HA database needs its own order. The replication role `repl` shares the password, and a member that restarts with the old password can be promoted to leader, which splits the cluster. Move the leader to member `-0` first, so it restarts last, after every other member already has the new password. `pgx` runs a command in one member (`LOCATION` is your GVC's location, `DB_USERNAME` the secret's `username`): diff --git a/template-catalog/templates/chatwoot.mdx b/template-catalog/templates/chatwoot.mdx index e8647f77..cca258bd 100644 --- a/template-catalog/templates/chatwoot.mdx +++ b/template-catalog/templates/chatwoot.mdx @@ -336,6 +336,7 @@ Enable exactly one of `postgresHA` (default) and `postgres` — the chart refuse # an HAProxy leader endpoint. Its image ships pgvector, which Chatwoot's schema REQUIRES. postgresHA: enabled: true + image: controlplanecorporation/patroni-postgres:0.8 # pgvector 0.8.7; tags 0.1-0.7 are refused (CVE-2026-103484) config: credentialsSecretName: my-chatwoot-db-credentials # PREREQUISITE dictionary secret (username, password, database) — must exist BEFORE install replicas: 3 @@ -711,6 +712,12 @@ The current values are also in `postgres.credentials` and `redis.auth.password` The upgrade restarts the bundled PostgreSQL too (it now reads the new secret), so Chatwoot can briefly lose its database; it reconnects by itself. The new version of a workload can also wait several minutes with `is not allowed to reveal the secret` in `get-deployments` while access to the new secret propagates; the previous version keeps serving meanwhile, and it clears by itself. +### Upgrading From 1.3.0 or Earlier + +1.3.1 moves the HA database (`postgresHA`) to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7 (CVE-2026-103484). The fix takes effect when the upgrade restarts the Patroni members; existing data needs nothing. Nothing limits that rollout, so expect a brief interruption of writes while the leader changes. Chatwoot itself restarts as on any upgrade; with a single Chatwoot web replica (the default) that is the longer interruption, because the old replica stops before the new one serves. Upgrade in a quiet window. If you pinned `postgresHA.image` in your values, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. + +Chatwoot's schema creates the `vector` extension, so in the Chatwoot database `\dx` keeps reporting the old version until you run `ALTER EXTENSION vector UPDATE;` as the database user, through the proxy endpoint `RELEASE_NAME-postgres-ha-proxy.GVC_NAME.cpln.local:5432`; it only updates that record. Single-instance mode (`postgres`) is unchanged. + ### Scaling and Availability - **Web tier** — `chatwoot.replicas` sets how many web replicas run. Replicas share the database and the bundled Redis, so a message received by one replica reaches a WebSocket client connected to another, and no sticky sessions are needed. Anything above `1` requires `storage.type` `s3` or `s3-compatible`; the chart refuses to render the combination with local storage. diff --git a/template-catalog/templates/glitchtip.mdx b/template-catalog/templates/glitchtip.mdx index 5f224156..d7d0cd57 100644 --- a/template-catalog/templates/glitchtip.mdx +++ b/template-catalog/templates/glitchtip.mdx @@ -254,6 +254,7 @@ Enable exactly one database — the chart refuses to render with both or neither ```yaml postgresHA: enabled: true + image: controlplanecorporation/patroni-postgres:0.8 # pgvector 0.8.7 (CVE-2026-103484); tags 0.1-0.7 are refused config: credentialsSecretName: my-glitchtip-db-credentials # PREREQUISITE dictionary secret (username, password, database) — must exist BEFORE install replicas: 3 @@ -621,6 +622,10 @@ The upgrade restarts the bundled PostgreSQL and Redis too (they now read the new The first Helm upgrade after an install can restart the bundled database and Redis even when their values are unchanged, so expect a brief interruption. +### Upgrading from 1.4.0 or earlier + +1.4.1 moves the HA database (`postgresHA`) to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7 (CVE-2026-103484). The fix takes effect when the upgrade restarts the Patroni members; existing data needs nothing. Nothing limits that rollout, so expect a brief interruption of writes while the leader changes. GlitchTip itself restarts without a gap: the new replica serves before the old one stops. Upgrade in a quiet window. If you pinned `postgresHA.image` in your values, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. GlitchTip does not use the `vector` extension; if you created it yourself in a database, `\dx` keeps reporting the old version until you run `ALTER EXTENSION vector UPDATE;` there, which only updates that record. Single-instance mode (`postgres`) is unchanged. + ### Scaling and Availability `replicas` is the scaling knob. The web tier is stateless — sessions, cache, and queue live in Redis, everything durable in PostgreSQL — so `2` or more web replicas behind the single endpoint gives high availability for the UI and for event ingest with no sticky sessions. diff --git a/template-catalog/templates/grafana.mdx b/template-catalog/templates/grafana.mdx index bac37fce..d813ad44 100644 --- a/template-catalog/templates/grafana.mdx +++ b/template-catalog/templates/grafana.mdx @@ -354,6 +354,7 @@ Exactly one of the two database modes must be enabled — the chart enforces thi ```yaml postgresHA: # default: highly available PostgreSQL app database enabled: true + image: controlplanecorporation/patroni-postgres:0.8 # pgvector 0.8.7 (CVE-2026-103484); tags 0.1-0.7 are refused config: credentialsSecretName: my-grafana-db-credentials # PREREQUISITE dictionary secret (username, password, database), must exist BEFORE install replicas: 3 @@ -735,6 +736,10 @@ Then upgrade with `postgres.credentials` removed and the `credentialsSecretName` The upgrade restarts the bundled PostgreSQL too (it now reads the new secret), so Grafana can briefly lose its database; it reconnects by itself. The new version of a workload can also wait several minutes with `is not allowed to reveal the secret` in `get-deployments` while access to the new secret propagates; the previous version keeps serving meanwhile, and it clears by itself. +### Upgrading from 1.5.0 or earlier + +1.5.1 moves the HA database (`postgresHA`) to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7 (CVE-2026-103484). The fix takes effect when the upgrade restarts the Patroni members; existing data needs nothing. Nothing limits that rollout, so expect a brief interruption of writes while the leader changes. Grafana itself restarts without a gap (the new replica serves before the old one stops); while the leader changes, Grafana can briefly answer valid users with 401. Upgrade in a quiet window. If you pinned `postgresHA.image` in your values, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. Grafana does not use the `vector` extension; if you created it yourself in a database, `\dx` keeps reporting the old version until you run `ALTER EXTENSION vector UPDATE;` there, which only updates that record. Single-instance mode (`postgres`) is unchanged. + ### Scaling and Availability - **`replicas`** scales the Grafana tier; `2` or more requires `redis.enabled: true` — see [Alerting High Availability](#alerting-high-availability). Database replicas are set separately with `postgresHA.replicas`; the single-instance database must stay at one replica. diff --git a/template-catalog/templates/listmonk.mdx b/template-catalog/templates/listmonk.mdx index 4934dd6c..3574f736 100644 --- a/template-catalog/templates/listmonk.mdx +++ b/template-catalog/templates/listmonk.mdx @@ -247,6 +247,7 @@ postgres: postgresHA: enabled: true # set postgresHA.enabled: true for near-zero-downtime upgrades and failover + image: controlplanecorporation/patroni-postgres:0.8 # pgvector 0.8.7 (CVE-2026-103484); 0.1-0.7 are refused config: # REQUIRED PREREQUISITE SECRET (HA mode) — the same kind of `dictionary` # secret as postgres.config.credentialsSecretName above (keys: username, @@ -474,6 +475,10 @@ Then upgrade with `postgres.config.credentialsSecretName` (single-instance mode) The upgrade restarts the bundled PostgreSQL too (it now reads the new secret), so listmonk can briefly lose its database; it reconnects by itself. While access to the new secret propagates, the new version of a workload can wait in `get-deployments` reporting that it is not allowed to reveal the secret; the previous version keeps serving meanwhile, and it clears by itself. +### Upgrading from 1.6.0 or earlier + +1.6.1 moves the HA database (`postgresHA`) to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7 (CVE-2026-103484). The fix takes effect when the upgrade restarts the Patroni members; existing data needs nothing. Nothing limits that rollout, so expect a brief interruption of writes while the leader changes. listmonk itself restarts as on any upgrade, which is the longer interruption, because its single replica stops before the new one serves; a few writes on already-open database connections can also fail right after the leader change. Upgrade in a quiet window. If you pinned `postgresHA.image` in your values, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. listmonk does not use the `vector` extension; if you created it yourself in a database, `\dx` keeps reporting the old version until you run `ALTER EXTENSION vector UPDATE;` there, which only updates that record. Single-instance mode (`postgres`) is unchanged. + ### Rotating the Database Password A running workload keeps the credential values it started with, and PostgreSQL reads the secret only when its data is first initialized, so editing the secret alone does not change the database password. Change one key and keep the others with export, edit, apply: diff --git a/template-catalog/templates/metabase.mdx b/template-catalog/templates/metabase.mdx index cf406f6c..00bc110f 100644 --- a/template-catalog/templates/metabase.mdx +++ b/template-catalog/templates/metabase.mdx @@ -213,6 +213,7 @@ Exactly one of the two database modes must be enabled — the chart enforces thi ```yaml postgresHA: # default: highly available PostgreSQL app database enabled: true + image: controlplanecorporation/patroni-postgres:0.8 # pgvector 0.8.7 (CVE-2026-103484); tags 0.1-0.7 are refused config: credentialsSecretName: my-metabase-db-credentials # PREREQUISITE dictionary secret (username, password, database) — must exist BEFORE install replicas: 3 @@ -538,6 +539,10 @@ Then upgrade with `postgresHA.config.credentialsSecretName` (HA mode) or `postgr The upgrade restarts the bundled PostgreSQL too (it now reads the new secret), so Metabase can briefly lose its database; it reconnects by itself. While access to the new secret propagates, the new version of a workload can wait in `get-deployments` reporting that it is not allowed to reveal the secret; the previous version keeps serving meanwhile, and it clears by itself. +### Upgrading from 1.5.0 or earlier + +1.5.1 moves the HA database (`postgresHA`) to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7 (CVE-2026-103484). The fix takes effect when the upgrade restarts the Patroni members; existing data needs nothing. Nothing limits that rollout, so expect a brief interruption of writes while the leader changes. Metabase itself restarts without a gap: the new replica serves before the old one stops. Upgrade in a quiet window. If you pinned `postgresHA.image` in your values, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. Metabase does not use the `vector` extension; if you created it yourself in a database, `\dx` keeps reporting the old version until you run `ALTER EXTENSION vector UPDATE;` there, which only updates that record. Single-instance mode (`postgres`) is unchanged. + ### Rotating the Database Password A running workload keeps the credential values it started with, and PostgreSQL reads the secret only when its data is first initialized, so editing the secret alone does not change the database password. Change one key and keep the others with export, edit, apply: diff --git a/template-catalog/templates/nocodb.mdx b/template-catalog/templates/nocodb.mdx index 71013f6e..88cd8334 100644 --- a/template-catalog/templates/nocodb.mdx +++ b/template-catalog/templates/nocodb.mdx @@ -301,6 +301,7 @@ postgres: # set postgresHA.enabled: true (and postgres.enabled: false) for near-zero-downtime upgrades and automatic failover postgresHA: enabled: false + image: controlplanecorporation/patroni-postgres:0.8 # pgvector 0.8.7 (CVE-2026-103484); 0.1-0.7 are refused config: credentialsSecretName: my-nocodb-db-credentials # PREREQUISITE dictionary secret (username, password, database) — must exist BEFORE install replicas: 3 @@ -577,6 +578,10 @@ Then upgrade with `postgres.config.credentialsSecretName` (single-instance mode) The upgrade restarts the bundled PostgreSQL and Redis too (they now read the new secrets), so NocoDB can briefly lose its database and Redis; it recovers by itself. While access to the new secrets propagates, the new version of a workload can wait in `get-deployments` reporting that it is not allowed to reveal the secret; the previous version keeps serving meanwhile, and it clears by itself. +### Upgrading from 1.4.0 or earlier + +1.4.1 moves the HA database (`postgresHA`) to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7 (CVE-2026-103484). The fix takes effect when the upgrade restarts the Patroni members; existing data needs nothing. Nothing limits that rollout, so expect a brief interruption of writes while the leader changes. NocoDB itself restarts as on any upgrade, and its bundled Redis restarts with it; with a single NocoDB replica (the default) that is the longer interruption, because the old replica stops before the new one serves. Upgrade in a quiet window. If you pinned `postgresHA.image` in your values, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. NocoDB does not use the `vector` extension; if you created it yourself in a database, `\dx` keeps reporting the old version until you run `ALTER EXTENSION vector UPDATE;` there, which only updates that record. Single-instance mode (`postgres`) is unchanged. + ### Rotating the Database Password PostgreSQL keeps the password it was initialized with, and a running workload keeps the values it started with, so editing the secret alone does not change the database password. Change one key and keep the others with export, edit, apply (letters, digits, `-` and `_` only): diff --git a/template-catalog/templates/polaris.mdx b/template-catalog/templates/polaris.mdx index dad862b9..2eb967ea 100644 --- a/template-catalog/templates/polaris.mdx +++ b/template-catalog/templates/polaris.mdx @@ -297,6 +297,7 @@ The credentials are applied when the metastore volume is first initialized. Chan ```yaml postgresHA: enabled: false + image: controlplanecorporation/patroni-postgres:0.8 # pgvector 0.8.7 (CVE-2026-103484); 0.1-0.7 are refused config: credentialsSecretName: my-polaris-db-credentials # PREREQUISITE dictionary secret (username, password, database) — must exist BEFORE install replicas: 3 @@ -655,6 +656,10 @@ Your current values are in `postgres.credentials` of the 1.2.1 release, and also The upgrade restarts the bundled PostgreSQL too (it now reads the new secret), so Polaris briefly loses its database; it reconnects by itself. While access to the new secret propagates, the new version of a workload can wait in `get-deployments` reporting that it is not allowed to reveal the secret; the previous version keeps serving meanwhile, and it clears by itself. When that wait happens, the PostgreSQL restart (and its brief outage) comes only after it clears. +### Upgrading from 1.3.0 or earlier + +1.3.1 moves the HA database (`postgresHA`) to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7 (CVE-2026-103484). The fix takes effect when the upgrade restarts the Patroni members; existing data needs nothing. Nothing limits that rollout, so expect a brief interruption of writes while the leader changes. Polaris itself restarts without a gap (the new replica serves before the old one stops); while the leader changes, Polaris's token endpoint can briefly refuse requests. Upgrade in a quiet window. If you pinned `postgresHA.image` in your values, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. Polaris does not use the `vector` extension; if you created it yourself in a database, `\dx` keeps reporting the old version until you run `ALTER EXTENSION vector UPDATE;` there, which only updates that record. Single-instance mode (`postgres`) is unchanged. + ### Rotating the Metastore Password A running workload keeps the credential values it started with, and PostgreSQL reads the secret only when its data is first initialized, so editing the secret alone does not change the database password. Change one key and keep the others with export, edit, apply: diff --git a/template-catalog/templates/temporal.mdx b/template-catalog/templates/temporal.mdx index 7c150d7b..bf7a824a 100644 --- a/template-catalog/templates/temporal.mdx +++ b/template-catalog/templates/temporal.mdx @@ -248,6 +248,7 @@ Exactly one of `postgresHA` and `postgres` must be enabled; the chart refuses to ```yaml postgresHA: enabled: true + image: controlplanecorporation/patroni-postgres:0.8 # pgvector 0.8.7 (CVE-2026-103484); tags 0.1-0.7 are refused config: # REQUIRED PREREQUISITE SECRET (HA mode) — CREATE IT BEFORE YOU INSTALL. If # it does not exist the deployment WEDGES silently and looks like a platform @@ -695,6 +696,10 @@ cpln secret create-dictionary --name RELEASE_NAME-postgres-credentials \ The upgrade restarts the bundled PostgreSQL too (it now reads the new secret), so Temporal can briefly lose its database; it reconnects by itself. While access to the new secret propagates, the new version of a workload can wait in `get-deployments` reporting that it is not allowed to reveal the secret; the previous version keeps serving meanwhile, and it clears by itself. +### Upgrading from 2.1.0 or earlier + +2.1.1 moves the HA database (`postgresHA`) to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7 (CVE-2026-103484). The fix takes effect when the upgrade restarts the Patroni members; existing data needs nothing. Nothing limits that rollout, so expect a brief interruption of writes while the leader changes. Temporal itself restarts without a gap, but its API is briefly unavailable while the database leader changes; running workflows and schedules continue. Upgrade in a quiet window. If you pinned `postgresHA.image` in your values, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. Temporal does not use the `vector` extension; if you created it yourself in a database, `\dx` keeps reporting the old version until you run `ALTER EXTENSION vector UPDATE;` there, which only updates that record. Single-instance mode (`postgres`) is unchanged. + ### Rotating the Database Password A running workload keeps the credential values it started with, and PostgreSQL reads the secret only when its data is first initialized, so editing the secret alone does not change the database password. Change one key and keep the others with export, edit, apply — keep `database` at `temporal`: diff --git a/template-catalog/templates/twenty.mdx b/template-catalog/templates/twenty.mdx index a2edf88f..116df0e1 100644 --- a/template-catalog/templates/twenty.mdx +++ b/template-catalog/templates/twenty.mdx @@ -398,6 +398,7 @@ postgres: # set postgres.enabled: false. postgresHA: enabled: false + image: controlplanecorporation/patroni-postgres:0.8 # pgvector 0.8.7 (CVE-2026-103484); 0.1-0.7 are refused config: # REQUIRED PREREQUISITE SECRET (HA mode) — the same kind of `dictionary` # secret as postgres.config.credentialsSecretName above (keys: username, @@ -720,6 +721,10 @@ Then upgrade with `postgres.config.credentialsSecretName` (single-instance mode) The upgrade restarts the bundled PostgreSQL and Redis too (they now read the new secrets), so Twenty briefly loses its database and Redis and reconnects by itself. The new version of a workload can also wait for several minutes, with `get-deployments` reporting that it is not allowed to reveal the secret, while access to the new secret propagates; the previous version keeps serving meanwhile, and it clears by itself. +### Upgrading From 1.4.0 or Earlier + +1.4.1 moves the HA database (`postgresHA`) to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7 (CVE-2026-103484). The fix takes effect when the upgrade restarts the Patroni members; existing data needs nothing. Nothing limits that rollout, so expect a brief interruption of writes while the leader changes. Twenty itself restarts as on any upgrade, and its worker and bundled Redis restart with it; with a single Twenty server replica (the default) that is the longer interruption, because the old replica stops before the new one serves, and writes fail while Redis restarts. Upgrade in a quiet window. If you pinned `postgresHA.image` in your values, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. Twenty does not use the `vector` extension; if you created it yourself in a database, `\dx` keeps reporting the old version until you run `ALTER EXTENSION vector UPDATE;` there, which only updates that record. Single-instance mode (`postgres`) is unchanged. + ### Scaling and Availability - **Server tier** — `twenty.replicas` sets how many server replicas run behind the endpoint. Anything above `1` requires `storage.type: s3`; the chart refuses to render the combination with local storage. diff --git a/template-catalog/templates/unleash.mdx b/template-catalog/templates/unleash.mdx index 94aa5d96..0ee703db 100644 --- a/template-catalog/templates/unleash.mdx +++ b/template-catalog/templates/unleash.mdx @@ -192,6 +192,7 @@ Exactly one of the two database modes must be enabled — the chart enforces thi ```yaml postgresHA: enabled: true + image: controlplanecorporation/patroni-postgres:0.8 # pgvector 0.8.7 (CVE-2026-103484); tags 0.1-0.7 are refused config: credentialsSecretName: my-unleash-db-credentials # PREREQUISITE dictionary secret (username, password, database) — must exist BEFORE install replicas: 3 @@ -509,6 +510,10 @@ Then upgrade with `postgresHA.config.credentialsSecretName` (HA mode) or `postgr The upgrade restarts the bundled PostgreSQL too (it now reads the new secret), so Unleash can briefly lose its database; it reconnects by itself. The new version of a workload can also wait for several minutes, with `get-deployments` reporting that it is not allowed to reveal the secret, while access to the new secret propagates; the previous version keeps serving meanwhile, and it clears by itself. +### Upgrading from 1.5.0 or earlier + +1.5.1 moves the HA database (`postgresHA`) to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7 (CVE-2026-103484). The fix takes effect when the upgrade restarts the Patroni members; existing data needs nothing. Nothing limits that rollout, so expect a brief interruption of writes while the leader changes. Unleash itself restarts without a gap: the new replica serves before the old one stops. Upgrade in a quiet window. If you pinned `postgresHA.image` in your values, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. Unleash does not use the `vector` extension; if you created it yourself in a database, `\dx` keeps reporting the old version until you run `ALTER EXTENSION vector UPDATE;` there, which only updates that record. Single-instance mode (`postgres`) is unchanged. + ### Rotating the Database Password PostgreSQL reads the database credentials secret only when its data is first initialized, and a running workload keeps the values it started with. In single-instance mode, change the password in the database first (`ALTER ROLE DB_USERNAME PASSWORD 'NEW_PASSWORD';`), then update the secret with `cpln secret edit SECRET_NAME` and force a redeployment of the Unleash workload: From d46dd40ce57261f71e38b6ba7e1a52c45f66dfa5 Mon Sep 17 00:00:00 2001 From: Jacob Cox Date: Thu, 29 Oct 2026 14:28:43 -0600 Subject: [PATCH 2/6] =?UTF-8?q?docs:=205376=20vulnerability-fix=20versions?= =?UTF-8?q?=20=E2=80=94=20keycloak=201.5.1,=20minio=201.4.0,=20pgvector=20?= =?UTF-8?q?1.0.1,=20nginx=201.1.3,=20open-webui=201.4.0,=20ollama=201.2.0,?= =?UTF-8?q?=20uptime-kuma=201.3.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01WZ5WWhTn9mEkPY7cLt1cr4 --- template-catalog/templates/keycloak.mdx | 13 ++++- template-catalog/templates/minio.mdx | 38 ++++++++------ template-catalog/templates/nginx.mdx | 59 ++++++++++------------ template-catalog/templates/ollama.mdx | 25 +++++++-- template-catalog/templates/open-webui.mdx | 18 ++++++- template-catalog/templates/pgvector.mdx | 17 +++++-- template-catalog/templates/uptime-kuma.mdx | 16 ++++-- 7 files changed, 123 insertions(+), 63 deletions(-) diff --git a/template-catalog/templates/keycloak.mdx b/template-catalog/templates/keycloak.mdx index 142efba1..6b78ae57 100644 --- a/template-catalog/templates/keycloak.mdx +++ b/template-catalog/templates/keycloak.mdx @@ -145,7 +145,7 @@ To install using another method, follow the instructions for your preferred tool ### Keycloak ```yaml -image: quay.io/keycloak/keycloak:26.6.3 +image: quay.io/keycloak/keycloak:26.8.1 # Replica count. 2+ (default) forms an Infinispan cluster over JGroups JDBC_PING # for zero-downtime restarts. 1 = dev mode: clustering fully disabled (local cache). @@ -192,6 +192,7 @@ postgresHA: config: credentialsSecretName: my-keycloak-db-credentials # PREREQUISITE dictionary secret (username, password, database) — must exist BEFORE install replicas: 3 + image: controlplanecorporation/patroni-postgres:0.8 # pgvector 0.8.7 (CVE-2026-103484); tags 0.1-0.7 are refused volumeset: capacity: 10 # initial capacity in GiB per replica (minimum is 10) @@ -480,6 +481,16 @@ Your current values are in `postgres.credentials` of the 1.4.0 release, and also The upgrade restarts the bundled PostgreSQL too (it now reads the new secret), so Keycloak can briefly lose its database; it reconnects by itself. The new version of a workload can also wait several minutes with `is not allowed to reveal the secret` in `get-deployments` while access to the new secret propagates; the previous version keeps serving meanwhile, and it clears by itself. +### Upgrading From 1.5.0 + +Version `1.5.1` moves Keycloak from 26.6.3 to 26.8.1, which fixes an unauthenticated account-takeover vulnerability in the reset-credentials flow (CVE-2026-18963). No values change: upgrade with the values you already use. If your values set `image` (installs made through the Console wizard store it), change it to `quay.io/keycloak/keycloak:26.8.1` or remove it; the chart refuses an official Keycloak image older than 26.7.2. + +The first 26.8.1 server to start migrates the database schema, and Keycloak cannot run an older version against a migrated database, so this upgrade cannot be rolled back to 1.5.0: a rolled-back release reports healthy, but every login page fails with HTTP 500. Take a database backup before upgrading (see [Backing Up](#backing-up)); to recover from a rollback, upgrade to 1.5.1 again or restore the backup. + +With 2 or more replicas Keycloak keeps serving throughout the upgrade, apart from the brief interruption of database writes in HA mode described below. With `replicas: 1`, Keycloak is unavailable while its single server restarts. + +In HA mode, `1.5.1` also moves the database to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7 (CVE-2026-103484). The database members restart, so expect a brief interruption of writes while the leader changes, even with 2 or more Keycloak replicas. Upgrade in a quiet window. Keycloak does not use the `vector` extension; if you created it yourself in a database, run `ALTER EXTENSION vector UPDATE;` there after the upgrade. If your values set `postgresHA.image`, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. + ### Scaling and Availability - **Keycloak replicas.** Change `replicas` and upgrade the release; there is deliberately no autoscaling, so cluster membership only changes when you change it. Clustered replicas (`2` or more) share realm, user and session state through the database, so one replica restarting does not interrupt sign-ins. With `replicas: 1` a restart is a short outage. diff --git a/template-catalog/templates/minio.mdx b/template-catalog/templates/minio.mdx index b104d724..d1ace180 100644 --- a/template-catalog/templates/minio.mdx +++ b/template-catalog/templates/minio.mdx @@ -7,7 +7,7 @@ keywords: ['minio', 's3 alternative', 'self-hosted s3', 'aws s3 alt', 'object st ## Overview -MinIO is a high-performance, S3-compatible object storage server. This template deploys it in **distributed mode**: `replicas` nodes form one erasure-coded pool, every object is striped with parity across all of them, and the pool keeps serving reads and writes while some nodes are down. It is the usual in-org S3 target for other catalog templates that back up to MinIO. +MinIO is a high-performance, S3-compatible object storage server. This template deploys it in **distributed mode**, running [Silo](https://github.com/pgsty/silo), the maintained open-source fork of MinIO (MinIO no longer publishes a public image): `replicas` nodes form one erasure-coded pool, every object is striped with parity across all of them, and the pool keeps serving reads and writes while some nodes are down. It is the usual in-org S3 target for other catalog templates that back up to MinIO. The root credentials — the S3 access key and secret key every client uses — come from a dictionary secret you create **before** installing. Nothing sensitive passes through Helm values, and the template creates no credential secret of its own. @@ -41,11 +41,11 @@ This template does not create a GVC. You must deploy it into an existing GVC. Set `admin.credentialsSecretName` to this name. - - The template defaults to `replicas: 6`, which is above the default `replicas-per-workload` quota of 5. Either request a quota increase before installing, or install with `--set replicas=4` (the minimum). Your org's current limit is shown by: + + The workload uses per-replica addressing, so the quota that applies is `replicas-per-replica-direct-workload`, which is 6 by default. The default `replicas: 6` fits it. For more replicas, check your org's limit and request an increase before installing: ```bash - cpln quota get + cpln quota get --max 0 | grep replicas-per-replica-direct-workload ``` @@ -103,11 +103,13 @@ To install, follow the instructions for your preferred method: ### Image and Replicas ```yaml -image: quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z # quay.io: MinIO withdrew minio/minio from Docker Hub (2025); quay is its public registry. Same release tag. +image: pgsty/silo:RELEASE.2026-10-18T00-00-00Z # Silo, the maintained AGPL fork of MinIO; MinIO no longer publishes a public image replicas: 6 # Must be at least 4 and an even number ``` +If you set your own `image`, the chart starts whichever of `silo` or `minio` the image contains. + `replicas` is fixed at install time — see [Scaling and Availability](#scaling-and-availability). ### Root Credentials @@ -254,6 +256,12 @@ its name. See Prerequisites in the README. +### Upgrading From 1.3.x + +MinIO's own images are no longer publicly pullable (Docker Hub removed them, and quay.io now refuses anonymous pulls), so a `1.3.x` node that restarts on a new host cannot start again. Version `1.4.0` runs Silo instead: same S3 API, same `MINIO_*` settings and the same on-disk data format, so your objects, buckets and credentials carry over. Upgrade with the values you already use. + +**Plan the upgrade as a maintenance window.** Nodes switch to Silo one at a time, and a Silo node does not join a pool that still runs mostly MinIO nodes: until about half the nodes run Silo, a share of S3 reads and writes fail. Pause writers, or make sure clients retry, until every node is ready. Once the rollout finishes, do not return to `1.3.x`. + ### Rotating the Root Credentials The root credentials are the S3 access key and secret key, so rotating them is a fleet-wide change: every client and every other template configured with these keys has to be updated in the same window. @@ -302,9 +310,9 @@ cpln workload force-redeployment RELEASE_NAME-minio --gvc GVC_NAME **Fix:** follow [Upgrading From Earlier Versions](#upgrading-from-earlier-versions). - **Cause:** the default `replicas: 6` is above the default `replicas-per-workload` quota of 5. + **Cause:** `replicas` is above your org's `replicas-per-replica-direct-workload` quota, which is 6 by default. - **Fix:** request a quota increase, or install with `--set replicas=4`. Check your org's current limit with `cpln quota get`. + **Fix:** request a quota increase, or install with a lower `replicas`. Check your org's current limit with `cpln quota get --max 0 | grep replicas-per-replica-direct-workload`. **Cause:** the nodes cannot reach each other, so no pool forms. The usual reason is `internalAccess.type: none`, or a `workload-list` that does not include the MinIO workload itself. @@ -331,17 +339,17 @@ cpln workload force-redeployment RELEASE_NAME-minio --gvc GVC_NAME ## External References - - Official MinIO documentation + + Official Silo documentation - - How MinIO stripes data and parity across nodes + + What carries over from MinIO - - Command-line client for the S3 API + + How data and parity are striped across nodes - - Source code and release notes for the MinIO server + + Command-line client for the S3 API View the source files, default values, and chart definition diff --git a/template-catalog/templates/nginx.mdx b/template-catalog/templates/nginx.mdx index 42f56b57..f0a82f1a 100644 --- a/template-catalog/templates/nginx.mdx +++ b/template-catalog/templates/nginx.mdx @@ -7,7 +7,7 @@ keywords: ['http proxy', 'reverse proxy', 'path based routing', 'load balancer t ## Overview -Nginx is a high-performance web server and reverse proxy. This template deploys Nginx as a stateless reverse proxy that routes incoming requests by path to other workloads in the same GVC, so several internal services can share one public endpoint. The `nginx.conf` is generated from your `locations` values and mounted into the container from a secret. +Nginx is a high-performance web server and reverse proxy. This template deploys Nginx as a stateless reverse proxy that routes incoming requests by path to other workloads in the same GVC, so several internal services can share one public endpoint. The `nginx.conf` is generated from your `locations` values (or supplied whole through `nginxConf`) and mounted into the container from a secret. A default install also deploys a small example backend and routes every request to it, so you can confirm the proxy works before pointing it at your own services. @@ -20,7 +20,7 @@ This template does not create a GVC. It deploys into an existing GVC that you al | Resource | Name | Purpose | Optional | |---|---|---|---| | Workload | `RELEASE_NAME-nginx` | Nginx reverse proxy on port `80` (serverless, autoscaling), open to the internet | — | -| Secret | `RELEASE_NAME-nginx-config` | Opaque secret holding the generated `nginx.conf`, mounted at `/etc/nginx/nginx.conf` | — | +| Secret | `RELEASE_NAME-nginx-config` | Opaque secret holding the `nginx.conf` (generated from your values, or your own from `nginxConf`), mounted at `/etc/nginx/nginx.conf` | — | | Identity | `RELEASE_NAME-nginx-identity` | Identity bound to the proxy workload | — | | Policy | `RELEASE_NAME-nginx-policy` | Grants the identity `reveal` on the configuration secret only | — | | Workload | `RELEASE_NAME-example` | Example backend that receives all `/` traffic; reachable only from the proxy | `enableExample: true` (the default) | @@ -37,7 +37,7 @@ Install the template into an existing GVC. No `--set` values are required: ```bash cpln helm install RELEASE_NAME oci://ghcr.io/controlplane-com/templates/nginx \ - --version 1.1.2 --gvc GVC_NAME + --version 1.1.3 --gvc GVC_NAME ``` To install using another method, follow the instructions for your preferred tool: @@ -70,15 +70,13 @@ To install using another method, follow the instructions for your preferred tool ```yaml proxyWorkload: - image: nginx:1.31.4 # pinned: `latest` makes installs non-reproducible + image: nginx:1.31.7 # pinned: `latest` makes installs non-reproducible port: 80 - capacityAI: false timeoutSeconds: 5 ``` - `proxyWorkload.image` — the Nginx container image. - `proxyWorkload.port` — the container port exposed by the workload. Leave it at `80`: the generated `nginx.conf` listens on `80` and the health probes check port `80`, neither of which follows this value. -- `proxyWorkload.capacityAI` — enables Control Plane CapacityAI on the proxy workload. - `proxyWorkload.timeoutSeconds` — the workload request timeout in seconds. ### Resources @@ -108,10 +106,10 @@ The scaling metric is fixed in the chart: CPU, with a 50 percent target. ### Example Backend ```yaml -enableExample: true # set to true to deploy an example backend workload and route all traffic to it +enableExample: true # deploy an example backend that answers every path none of your locations match ``` -When `true`, the chart deploys `RELEASE_NAME-example` and routes every `/` request to it. Set it to `false` before routing to your own services; otherwise the example keeps the `/` route. +When `true`, the chart deploys `RELEASE_NAME-example`, a demo backend that answers every request none of your `locations` match. Set it to `false` to route `/` to your own service; a `/` location while it is on stops the proxy from starting. ### Locations @@ -150,6 +148,14 @@ locations: regexModifier: "" ``` +### Custom nginx.conf + +To run your own configuration instead of the generated one, put the whole file in `nginxConf`. Helm template syntax in it is rendered, so it can still use `.Values.locations` and `.Values.global.cpln.gvc`. Keep `listen 80` and a `location /health` that returns 200, because the health probes check them: + +```yaml +nginxConf: "" # a full nginx.conf replacing the generated one (Helm template syntax is rendered); empty = generated from the settings above +``` + ### Built-in Routes Two routes are always present, whatever `locations` contains: @@ -159,7 +165,7 @@ Two routes are always present, whatever `locations` contains: | `/health` | `200` with `{"success":true,"message":"OK"}`; used by the liveness and readiness probes | | `/fail` | `500` with `{"success":false,"message":"Error"}` | -Any `500`, `502`, `503` or `504` from an upstream workload is replaced with the `/fail` response, so the client sees the JSON error body rather than the upstream page. +A `500`, `502`, `503` or `504` from an upstream workload is answered with the `/fail` body; the status code is kept. ## Connecting @@ -192,26 +198,24 @@ The `nginx.conf` lives in the `RELEASE_NAME-nginx-config` secret and is rebuilt ```bash cpln helm upgrade RELEASE_NAME oci://ghcr.io/controlplane-com/templates/nginx \ - --version 1.1.2 --gvc GVC_NAME \ + --version 1.1.3 --gvc GVC_NAME \ -f values.yaml ``` The values file must use the chart's nesting, exactly as the blocks in [Configuration](#configuration) show. A flat dotted key is accepted without error and silently changes nothing. -The configuration is mounted as a file, and a running replica keeps the file it started with. Force a redeployment so every replica starts with the new `nginx.conf`: - -```bash -cpln workload force-redeployment RELEASE_NAME-nginx --gvc GVC_NAME -``` - -Then confirm a route you changed answers on the public endpoint. Whether the upgrade alone restarts the proxy has not been verified on this template, so run the redeployment every time. +A routing change rolls the proxy onto the new configuration by itself after the upgrade. With one replica, requests may fail for a few seconds during the swap. Confirm a route you changed answers on the public endpoint. -Edit routing through Helm values only. Whether a later upgrade overwrites a hand edit to the secret has not been verified, so keep your routing in your values file and re-check the secret after every upgrade. +Edit routing through Helm values only, and keep your routing in your values file. ### Upgrading From 1.1.1 or Earlier Versions 1.1.1 and earlier defaulted `proxyWorkload.image` to `nginx:latest`. Version 1.1.2 pins it to `nginx:1.31.4`, so an upgrade that does not set the image restarts the proxy on the pinned version. The proxy holds no data, so nothing needs to be migrated. To keep a specific image, set `proxyWorkload.image` explicitly. +### Upgrading From 1.1.2 + +Version `1.1.3` moves the proxy to nginx 1.31.7, adds `nginxConf`, and removes `proxyWorkload.capacityAI`, which never had any effect (CapacityAI is always off for this template). Delete the key from your values file if you set it; the proxy holds no data, so nothing needs to be migrated. + ### Scaling and Availability The proxy is stateless, so it scales horizontally. The shipped default runs exactly one replica (`minScale: 1`, `maxScale: 1`), which means a restart or redeployment briefly interrupts traffic. Set `autoscaling.minScale` to `2` or more for an endpoint other systems depend on, and raise `autoscaling.maxScale` to let it scale out under load. @@ -222,9 +226,9 @@ The proxy is stateless, so it scales horizontally. The shipped default runs exac **Symptom:** You added `locations`, but requests to `/` still return the example greeting page. - **Cause:** `enableExample` is still `true`, so the example backend keeps the `/` route. + **Cause:** `enableExample` is still `true`, so the example backend answers every request your `locations` do not match, including `/`. - **Fix:** Set `enableExample: false`, run a Helm upgrade, then force a redeployment as described in [Changing the Routing](#changing-the-routing). + **Fix:** Set `enableExample: false` and run a Helm upgrade as described in [Changing the Routing](#changing-the-routing). **Symptom:** Requests to one of your paths return `500` with `{"success":false,"message":"Error"}`. @@ -252,27 +256,16 @@ The proxy is stateless, so it scales horizontally. The shipped default runs exac cpln workload get-deployments RELEASE_NAME-nginx --gvc GVC_NAME -o yaml ``` - - **Symptom:** The upgrade succeeded, but the proxy still routes the old way. - - **Cause:** The running replicas are still using the `nginx.conf` they started with. - - **Fix:** Force a redeployment: - - ```bash - cpln workload force-redeployment RELEASE_NAME-nginx --gvc GVC_NAME - ``` - ## Important Notes -- Set `enableExample: false` before routing to your own services; the default sends all `/` traffic to the example backend. +- Set `enableExample: false` before routing to your own services; the default example backend answers every request none of your `locations` match, and a `/` location while it is on stops the proxy from starting. - Put only the bare workload name in `locations[].workload`; the chart appends `.GVC_NAME.cpln.local` itself. - Each target workload's internal firewall must allow `RELEASE_NAME-nginx`, or its route returns the JSON error body. - The proxy is always open to the internet; there is no value to make it private. - Leave `proxyWorkload.port` at `80`; Nginx and its health probes are fixed to that port. -- After changing routing, force a redeployment so the replicas load the new `nginx.conf`. +- A routing change rolls the proxy onto the new config after `helm upgrade`; with one replica, requests may fail for a few seconds during the swap. - The example backend image, `gcr.io/knative-samples/helloworld-go`, publishes only `:latest` and cannot be pinned; it does not affect the proxy. ## External References diff --git a/template-catalog/templates/ollama.mdx b/template-catalog/templates/ollama.mdx index 77a37d00..3b25ae3a 100644 --- a/template-catalog/templates/ollama.mdx +++ b/template-catalog/templates/ollama.mdx @@ -93,11 +93,11 @@ workload: containers: ui: name: ollama-ui - image: ghcr.io/open-webui/open-webui:v0.11.0 # pinned: `main` is a moving branch build + image: ghcr.io/open-webui/open-webui:v0.12.4 # pinned: `main` is a moving branch build; v0.12.4 or newer is required port: 8080 resources: cpu: 500m - memory: 1Gi + memory: 2Gi # Open WebUI v0.12 needs more than 1Gi; at 1Gi it sits at the limit and API calls intermittently fail api: name: ollama image: ollama/ollama:0.32.15 # pinned: an untagged image resolves to `latest` @@ -233,7 +233,26 @@ Models need no backup: on a fresh or replaced volume, pull each model you use ag ### Upgrading from 1.1.1 or Earlier -Template version 1.1.2 pins both images — `ghcr.io/open-webui/open-webui:v0.11.0` and `ollama/ollama:0.32.15`. Earlier versions used the moving `open-webui:main` branch build and an untagged `ollama/ollama` that resolved to `latest`, so an install from before 1.1.2 is not reproducible and may be running a newer or older build than the pins. Upgrading changes the running image versions and leaves the volume set, and the models and UI data on it, in place. Take a snapshot first (see [Backing Up](#backing-up)) and upgrade with your usual install method. +Versions before 1.1.2 ran the moving `open-webui:main` build and an untagged `ollama/ollama`; this version pins `open-webui:v0.12.4` and `ollama/ollama:0.32.15`. A release on `main` may already run a newer Open WebUI than `v0.12.4`, and Open WebUI cannot read a database that a newer version migrated. When upgrading, keep the image the release runs, or pin a tag at least as new as its running version (Open WebUI shows it under Settings › About): + +```yaml +workload: + containers: + ui: + image: ghcr.io/open-webui/open-webui:main # or a release tag at least as new as the running one +``` + +Upgrading leaves the volume set, and the models and UI data on it, in place. Take a snapshot first (see [Backing Up](#backing-up)). + +### Upgrading from 1.1.2 + +Version 1.2.0 moves Open WebUI from `v0.11.0` to `v0.12.4`, whose image fixes Critical CVEs. The chart refuses an official Open WebUI tag older than `v0.12.4`, so a `workload.containers.ui.image` in your values that pins one must be changed or removed. + +- **Open WebUI migrates its database on the first start, and rolling back to 1.1.2 is not supported.** Take a volume set snapshot first (see [Backing Up](#backing-up)) and wait until it shows `Completed` in the snapshot listing. +- **Tool servers that users saved under Settings › Integrations stop being used in chats** until an admin turns on Direct Integrations in Admin Settings › Integrations. +- **Every user is signed out once** by the upgrade and signs in again. +- **Open WebUI's memory default rises from 1Gi to 2Gi.** A `workload.containers.ui.resources.memory` of 1Gi in your values keeps the old limit, and v0.12.4 then intermittently fails API calls. +- **Custom functions and tools that install pip packages need versions that support Python 3.12**, which the image now runs. ### Scaling and Availability diff --git a/template-catalog/templates/open-webui.mdx b/template-catalog/templates/open-webui.mdx index 5aff45a2..3ce759e4 100644 --- a/template-catalog/templates/open-webui.mdx +++ b/template-catalog/templates/open-webui.mdx @@ -131,7 +131,7 @@ One subsection per top-level values area. Each block shows the shipped defaults. ### Image and Resources ```yaml -image: ghcr.io/open-webui/open-webui:v0.11.0 +image: ghcr.io/open-webui/open-webui:v0.12.4 # tags below v0.12.4 of this image are refused (Critical CVEs) resources: maxCpu: 1 # max vCPU @@ -140,7 +140,7 @@ resources: minMemory: 1Gi ``` -- `image` — The Open WebUI container image. +- `image` — The Open WebUI container image. Tags of `ghcr.io/open-webui/open-webui` below v0.12.4 carry Critical CVEs and are refused at render; remove `image` or set it to `ghcr.io/open-webui/open-webui:v0.12.4`. - `resources.minCpu` / `resources.minMemory` — CPU and memory reserved for the container. - `resources.maxCpu` / `resources.maxMemory` — The container's limits. The first boot loads a local RAG embedding model into RAM, so keep `maxMemory` at or above the default. @@ -506,6 +506,20 @@ Settings → Admin → Authentication (New Sign Ups) instead. Remove auth.enable The Control Plane tools are added on upgrade only when the admin secret holds your current administrator's email and password. Otherwise add them by hand, as described in [Connecting Control Plane Tools](#connecting-control-plane-tools). +### Upgrading from 1.3.0 + +Version 1.4.0 moves Open WebUI from v0.11.0 to v0.12.4, which fixes Critical CVEs. The database migrates on the first start and rolling back to 1.3.0 afterwards is not supported, so snapshot the data volume first and wait until the snapshot shows `Completed`: + +```bash +cpln volumeset snapshot create RELEASE_NAME-open-webui-data --gvc GVC_NAME --snapshot-name before-1-4-0 +cpln volumeset snapshot get RELEASE_NAME-open-webui-data --gvc GVC_NAME +``` + +- **Pinned images.** Values that pin `image` to a `ghcr.io/open-webui/open-webui` tag below v0.12.4 are refused; remove `image` or set it to `ghcr.io/open-webui/open-webui:v0.12.4`. +- **Custom tools and functions** now run on Python 3.12. Packages the image no longer ships (such as `nltk` and `pymongo`) must be listed in the tool's own requirements. +- **Direct Integrations.** Tool servers that users saved in their own Settings → Integrations stop being used in chats until an admin turns on Direct Integrations in Settings → Admin → Integrations. The Control Plane server is an admin tool server and is not affected. +- **Prerequisite secrets** must exist before you upgrade as well as before you install. + ### Scaling and Availability The workload runs as exactly one replica by design, with no `replicas` value: the embedded SQLite database is single-writer and the volume set is per-replica, so a second instance would be a second, disconnected application rather than a cluster. A restart or upgrade is therefore a brief full outage of the UI. diff --git a/template-catalog/templates/pgvector.mdx b/template-catalog/templates/pgvector.mdx index 8601d149..06a981f5 100644 --- a/template-catalog/templates/pgvector.mdx +++ b/template-catalog/templates/pgvector.mdx @@ -1,13 +1,13 @@ --- title: pgvector icon: /template-catalog/templates/icons/pgvector.png -description: PostgreSQL 18 with the pgvector 0.8.6 extension pre-created for embedding storage and similarity search. Single server on a persistent volume with optional PgBouncer pooling and scheduled S3, GCS or MinIO backups. Deploys into an existing GVC; needs a dictionary credentials secret first. +description: PostgreSQL 18 with the pgvector 0.8.7 extension pre-created for embedding storage and similarity search. Single server on a persistent volume with optional PgBouncer pooling and scheduled S3, GCS or MinIO backups. Deploys into an existing GVC; needs a dictionary credentials secret first. keywords: ['vector database', 'embeddings', 'rag', 'nearest neighbor', 'cosine distance', 'hnsw', 'ivfflat', 'halfvec', 'ef_search', 'langchain', 'llamaindex', 'pinecone alternative', 'qdrant alternative', 'ann search', 'pg_dumpall'] --- ## Overview -[pgvector](https://github.com/pgvector/pgvector) adds a `vector` column type and approximate nearest-neighbor indexes to PostgreSQL, so embeddings live in the same database as the relational data they describe. This template deploys one PostgreSQL 18 server with pgvector 0.8.6 on a persistent volume, an optional [PgBouncer](https://www.pgbouncer.org/) connection pooler in front of it, and an optional cron job that writes compressed `pg_dumpall` backups to AWS S3, Google Cloud Storage or a MinIO (S3-compatible) bucket. +[pgvector](https://github.com/pgvector/pgvector) adds a `vector` column type and approximate nearest-neighbor indexes to PostgreSQL, so embeddings live in the same database as the relational data they describe. This template deploys one PostgreSQL 18 server with pgvector 0.8.7 on a persistent volume, an optional [PgBouncer](https://www.pgbouncer.org/) connection pooler in front of it, and an optional cron job that writes compressed `pg_dumpall` backups to AWS S3, Google Cloud Storage or a MinIO (S3-compatible) bucket. The extension is not just installed in the image — the template **creates it on first boot**, in the database named in your credentials secret. A fresh install can store vectors and run similarity queries with no setup SQL. @@ -25,7 +25,7 @@ This is a single server, not a cluster — there is no replication or failover. | Resource | Name | Purpose | Optional | |---|---|---|---| -| Workload | `RELEASE_NAME-pgvector` | PostgreSQL 18 with pgvector 0.8.6 (stateful, 1 replica, TCP `5432`) | — | +| Workload | `RELEASE_NAME-pgvector` | PostgreSQL 18 with pgvector 0.8.7 (stateful, 1 replica, TCP `5432`) | — | | Volume Set | `RELEASE_NAME-pgvector-vs` | `PGDATA` on an `ext4` general-purpose SSD volume; a final snapshot is kept for 7 days when the volume is deleted | — | | Secret | `RELEASE_NAME-pgvector-init` | First-boot SQL mounted at `/docker-entrypoint-initdb.d/00-pgvector.sql`; holds the `CREATE EXTENSION` statements and no credentials | — | | Identity | `RELEASE_NAME-pgvector-identity` | Shared by the database, pooler and backup workloads; carries the cloud account binding when backups use AWS or GCP | — | @@ -110,7 +110,7 @@ Each block below is the shipped default for that part of `values.yaml`. ### Server and Resources ```yaml -image: pgvector/pgvector:0.8.6-pg18 # PostgreSQL 18 + pgvector 0.8.6 (Debian bookworm base) +image: pgvector/pgvector:0.8.7-pg18 # PostgreSQL 18 + pgvector 0.8.7 (Debian bookworm base) resources: minCpu: 300m @@ -482,6 +482,13 @@ Workloads resolve the secret when a replica starts, so an updated secret is not cpln workload force-redeployment RELEASE_NAME-pgbouncer --gvc GVC_NAME ``` +### Upgrading From 1.0.0 + +Version `1.0.1` moves to pgvector 0.8.7, which fixes CVE-2026-103484: in 0.8.6 and earlier, a database user who can create an IVFFlat index can run arbitrary code on the server. + +- **If your values pin `image`** (an install through the Console wizard stores it), set it to `pgvector/pgvector:0.8.7-pg18` or remove it. The chart refuses an official pgvector tag older than 0.8.7. +- **The fix is in the server library and is active after the upgrade's restart**; existing data and indexes need nothing. `\dx` keeps reporting `vector` 0.8.6 until you run `ALTER EXTENSION vector UPDATE;` in each database that has it, which only updates that record. + ### Scaling and Availability - The server is pinned to one replica. Do not raise it — a second stateful replica gets its own volume, which is a second empty database rather than a replica. @@ -493,7 +500,7 @@ cpln workload force-redeployment RELEASE_NAME-pgbouncer --gvc GVC_NAME | | pgvector template | postgres-highly-available | |---|---|---| | PostgreSQL | 18 | 17 | -| pgvector | 0.8.6 | 0.8.0 | +| pgvector | 0.8.7 | 0.8.0 | ### Troubleshooting diff --git a/template-catalog/templates/uptime-kuma.mdx b/template-catalog/templates/uptime-kuma.mdx index 9aa529ec..2dca3778 100644 --- a/template-catalog/templates/uptime-kuma.mdx +++ b/template-catalog/templates/uptime-kuma.mdx @@ -35,7 +35,7 @@ Install the template into an existing GVC. No `--set` values are required: ```bash cpln helm install RELEASE_NAME oci://ghcr.io/controlplane-com/templates/uptime-kuma \ - --version 1.2.0 --gvc GVC_NAME + --version 1.3.0 --gvc GVC_NAME ``` To install using another method, follow the instructions for your preferred tool: @@ -67,7 +67,7 @@ To install using another method, follow the instructions for your preferred tool ### Image ```yaml -image: louislam/uptime-kuma:2.4.0 +image: louislam/uptime-kuma:2.5.8 ``` ### Resources and Storage @@ -165,7 +165,7 @@ Claim the admin account over a tunnel before anything is published. The chart pr ```bash cpln helm upgrade RELEASE_NAME oci://ghcr.io/controlplane-com/templates/uptime-kuma \ - --version 1.2.0 --gvc GVC_NAME \ + --version 1.3.0 --gvc GVC_NAME \ --set publicAccess.enabled=true ``` @@ -232,12 +232,19 @@ Version 1.2.0 changed the default of `publicAccess.enabled` from `true` to `fals ```bash cpln helm upgrade RELEASE_NAME oci://ghcr.io/controlplane-com/templates/uptime-kuma \ - --version 1.2.0 --gvc GVC_NAME \ + --version 1.3.0 --gvc GVC_NAME \ --set publicAccess.enabled=true ``` Your monitors, status pages and admin account live on the volume set and are unaffected by the upgrade. +### Upgrading From 1.2.0 + +Version 1.3.0 moves the image to Uptime Kuma 2.5.8, which migrates the SQLite database on its first start. Rolling back to the previous image afterwards is not supported, so snapshot the volume set first (see [Backing Up](#backing-up)) and wait until the snapshot shows `Completed` in the snapshot listing. + +- **Image pins.** Values that pin an `image` older than 2.5.8 are refused at render; set `image: louislam/uptime-kuma:2.5.8` or remove `image` from your values. +- **TCP Port monitors** that checked TLS or STARTTLS become plain TCP checks. + ### Scaling and Availability This template is single-instance. Upstream Uptime Kuma supports no clustering, and the workload is pinned to exactly one replica with no value to change it. A restart means a brief gap in monitoring; monitors resume on their own when the workload is back, and all data survives on the volume set. @@ -286,6 +293,7 @@ This template is single-instance. Upstream Uptime Kuma supports no clustering, a - **Create the admin account over the tunnel before enabling public access** — until an account exists, anyone who can reach the dashboard can claim it. - **Upgrading from 1.1.0 or earlier closes public access unless you set `publicAccess.enabled: true`** — see [Upgrading From 1.1.0 or Earlier](#upgrading-from-1-1-0-or-earlier). +- **TCP Port monitors cannot detect a closed or unreachable external port** — outbound connections pass through the platform's sidecar, which completes the TCP handshake itself, so such a monitor stays UP. Watch external services with HTTP(s), keyword or DNS monitors instead; HTTP monitors do report a dead port as DOWN. - **Single instance only** — there is no failover; a restart is a brief monitoring gap. - **All data lives on the volume set.** `cpln helm uninstall` deletes it, and a reinstall starts a fresh instance with a new setup wizard; the final snapshot is kept for 7 days. - **There are no cloud backups in this template** — take a manual volume set snapshot before risky changes. From 9fbf04287d42d8e2ae4cf0560c6867143e195402 Mon Sep 17 00:00:00 2001 From: Jacob Cox Date: Thu, 29 Oct 2026 14:30:37 -0600 Subject: [PATCH 3/6] =?UTF-8?q?docs:=20polaris=20=E2=80=94=20quote=20descr?= =?UTF-8?q?iption=20so=20frontmatter=20parses?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WZ5WWhTn9mEkPY7cLt1cr4 --- template-catalog/templates/polaris.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template-catalog/templates/polaris.mdx b/template-catalog/templates/polaris.mdx index 2eb967ea..58801d62 100644 --- a/template-catalog/templates/polaris.mdx +++ b/template-catalog/templates/polaris.mdx @@ -1,7 +1,7 @@ --- title: Polaris icon: /template-catalog/templates/icons/polaris.png -description: Deploy Apache Polaris, an Apache Iceberg REST catalog, on Control Plane. A stateless, horizontally scalable server with a bundled PostgreSQL metastore (single-instance or HA). Needs an existing GVC plus three prerequisite secrets: root client credentials, a token signing key, metastore credentials. +description: "Deploy Apache Polaris, an Apache Iceberg REST catalog, on Control Plane. A stateless, horizontally scalable server with a bundled PostgreSQL metastore (single-instance or HA). Needs an existing GVC plus three prerequisite secrets: root client credentials, a token signing key, metastore credentials." keywords: ['lakehouse', 'data lakehouse', 'data lake', 'iceberg rest catalog', 'hive metastore alternative', 'aws glue alternative', 'unity catalog alternative', 'nessie alternative', 'table format', 'parquet', 'trino iceberg', 'spark iceberg', 'pyiceberg', 'oauth2 client credentials', 'realm', 'polaris template'] --- From d789d25dad134753b7906ac8dbd331f18539a4af Mon Sep 17 00:00:00 2001 From: Jacob Cox Date: Thu, 29 Oct 2026 14:35:14 -0600 Subject: [PATCH 4/6] =?UTF-8?q?docs:=20group=20b=20(5376)=20=E2=80=94=20n8?= =?UTF-8?q?n=201.5.0,=20umami=201.5.0,=20langfuse=202.0.0,=20postgres-ha?= =?UTF-8?q?=202.8.1,=20postgres-multi-location=202.0.1,=20timescaledb-ha?= =?UTF-8?q?=201.2.1,=20timescaledb=20pgvector=20note;=20fix=20n8n=20frontm?= =?UTF-8?q?atter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WZ5WWhTn9mEkPY7cLt1cr4 --- template-catalog/templates/langfuse.mdx | 69 +++++++++++++++++-- template-catalog/templates/n8n.mdx | 21 ++++-- .../templates/postgres-highly-available.mdx | 14 +++- .../templates/postgres-multi-location.mdx | 24 +++++-- .../timescaledb-highly-available.mdx | 28 +++++++- template-catalog/templates/timescaledb.mdx | 1 + template-catalog/templates/umami.mdx | 32 +++++++-- 7 files changed, 167 insertions(+), 22 deletions(-) diff --git a/template-catalog/templates/langfuse.mdx b/template-catalog/templates/langfuse.mdx index ffeb6b82..84045b49 100644 --- a/template-catalog/templates/langfuse.mdx +++ b/template-catalog/templates/langfuse.mdx @@ -180,7 +180,7 @@ Install from the marketplace registry, naming your auth secret, your three datas ```bash cpln helm install RELEASE_NAME oci://ghcr.io/controlplane-com/templates/langfuse \ - --version 1.3.0 --gvc GVC_NAME \ + --version 2.0.0 --gvc GVC_NAME \ --set langfuse.auth.secretName=AUTH_SECRET_NAME \ --set postgres.config.credentialsSecretName=DB_CREDENTIALS_SECRET_NAME \ --set redis.credentialsSecretName=REDIS_SECRET_NAME \ @@ -241,7 +241,7 @@ langfuse: publicUrl: "" # custom domain WITH scheme, e.g. https://langfuse.example.com; empty = the platform canonical endpoint web: - image: langfuse/langfuse:3.225.2 + image: langfuse/langfuse:4.70.1 # 4.70.1 or newer: the chart refuses older tags (Critical CVEs) minReplicas: 2 # Keep at 2+ for zero-downtime rolling deploys maxReplicas: 5 resources: @@ -251,7 +251,7 @@ langfuse: maxMemory: 2Gi worker: - image: langfuse/langfuse-worker:3.225.2 + image: langfuse/langfuse-worker:4.70.1 # 4.70.1 or newer, same as the web image replicas: 1 resources: minCpu: 250m @@ -263,6 +263,9 @@ langfuse: secretName: my-langfuse-auth # REQUIRED prerequisite dictionary secret — create it BEFORE installing (see Prerequisites) disableSignup: true # false opens self-service registration to anyone who can reach the UI organizationName: Langfuse # organization created for the first-run admin + migration: # keep the defaults on a fresh install; see "Upgrading from 1.3.0" + writeMode: events_only # events_only (v4 default) | dual (old + new tables) | legacy (v3 behaviour) + historicBackfill: true # copy traces stored before the upgrade into the v4 tables; must be false with legacy ``` `langfuse.publicUrl` is the origin the browser uses: auth redirects, the pages NextAuth renders server-side, and whether the session cookie gets the `Secure` flag all derive from it. Leave it empty unless you serve Langfuse on a custom domain, and when you set it include the scheme — a value without one is rejected at render. @@ -318,7 +321,7 @@ redis: ```yaml clickhouse: - image: clickhouse/clickhouse-server:25.10 + image: clickhouse/clickhouse-server:26.8 # Langfuse 4 needs 25.12 or newer; the chart refuses older tags resources: minCpu: 1 maxCpu: 2 @@ -344,6 +347,24 @@ The three datastore credentials come from the prerequisite secrets you created; | Redis | `RELEASE_NAME-langfuse-redis.GVC_NAME.cpln.local:6379` | Internal only. `password` from your `redis.credentialsSecretName` secret. | | ClickHouse | `RELEASE_NAME-langfuse-clickhouse.GVC_NAME.cpln.local:8123` (HTTP) and `:9000` (native) | Internal only. `username` / `password` from your `clickhouse.credentialsSecretName` secret. | +Langfuse 4 ingests traces over OpenTelemetry. Send a first trace with a project key pair: + +```bash +NOW=$(date +%s) +curl -X POST https://YOUR_LANGFUSE_ENDPOINT/api/public/otel/v1/traces \ + -H "Content-Type: application/json" \ + -H "x-langfuse-ingestion-version: 4" \ + -u "YOUR_PUBLIC_KEY:YOUR_SECRET_KEY" \ + -d '{"resourceSpans":[{"resource":{"attributes":[{"key":"service.name","value":{"stringValue":"my-app"}}]}, + "scopeSpans":[{"scope":{"name":"curl"},"spans":[{"traceId":"0123456789abcdef0123456789abcdef", + "spanId":"0123456789abcdef","name":"my-first-trace","kind":1, + "startTimeUnixNano":"'"$NOW"'000000000","endTimeUnixNano":"'"$NOW"'500000000", + "attributes":[{"key":"langfuse.observation.input","value":{"stringValue":"Hello"}}, + {"key":"langfuse.observation.output","value":{"stringValue":"Hello back"}}]}]}]}]}' +``` + +Or use a [Langfuse SDK](https://langfuse.com/docs/observability/sdk/overview): Python SDK v4 or newer, or JS/TS SDK v5 or newer. + Verify the web tier is serving once `cpln workload get-deployments RELEASE_NAME-langfuse-web --gvc GVC_NAME -o yaml` reports it ready: ```bash @@ -499,6 +520,45 @@ Your current values are `redis.auth.password` and `clickhouse.config.password` o Then upgrade with `postgres.config.credentialsSecretName`, `redis.credentialsSecretName` and `clickhouse.credentialsSecretName` set to those names, and `postgres.credentials`, `redis.auth` and `clickhouse.config.password` removed. The upgrade restarts the bundled PostgreSQL (it now reads the new secret), so Langfuse briefly loses its database and reconnects by itself. While access to the new secrets propagates, the new version of a workload can wait in `get-deployments` reporting that it is not allowed to reveal the secret; the previous version keeps serving meanwhile, and it clears by itself. +### Upgrading from 1.3.0 + +Version 2.0.0 moves Langfuse 3 to Langfuse 4, and ClickHouse 25.10 to 26.8 (Langfuse 4 needs 25.12 or newer). It is an in-place `helm upgrade` of the existing release: the data stays where it is, the web and worker workloads wait until ClickHouse reports the new version, and the web workload then applies the Langfuse 4 database migrations at start. + +**The upgrade is one-way.** After the migrations, a 1.3.0 web container exits at start, and moving ClickHouse back to 25.10 on the same data is not supported. Going back means restoring PostgreSQL from a backup; this template has no ClickHouse backup. Langfuse documents a [manual schema rewind](https://langfuse.com/self-hosting/upgrade/upgrade-guides/upgrade-v3-to-v4#rollback) for the time before the cutover. + +Before you upgrade: + +1. A release older than 1.3.0 goes to 1.3.0 first, following the matching sections above. +2. Check that every Langfuse 3 background migration has finished, because Langfuse 4 drops the tables they copy from. The five `20260701_v4_step_*` migrations are already listed on 1.3.0 but run only on Langfuse 4, so the query leaves them out. It must print no rows: + + ```bash + cpln workload exec RELEASE_NAME-postgres --gvc GVC_NAME --container postgresql -- \ + sh -c 'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT name, failed_reason FROM background_migrations WHERE finished_at IS NULL AND name NOT LIKE '"'"'20260701_v4_step_%'"'"';"' + ``` + + If it prints rows, check the UI (Langfuse version tag, then **Background Migrations**). The worker runs background migrations only when it starts, and gives up if PostgreSQL is not reachable yet, so rows that never started are run by restarting it: + + ```bash + cpln workload force-redeployment RELEASE_NAME-langfuse-worker --gvc GVC_NAME + ``` + +3. Back up PostgreSQL (see [Backing Up](#backing-up)) and check the backup object is not empty. +4. Choose the write mode. It decides what keeps working from Langfuse 3: + +| `langfuse.migration.writeMode` | Choose it when | +|---|---| +| `events_only` (default) | No producer runs Python SDK v2 or JS/TS SDK v3 or older (rejected); Python SDK 4.7+, JS/TS SDK 5.4+ or plain OpenTelemetry write directly (Python 4.0-4.6 and JS/TS 5.0-5.3 ingest with a delay); nothing uses the legacy APIs or trace-level evaluators. Writes only the new tables. | +| `dual` | Some producers still run older SDKs, or you want the old tables kept as a safety net. Writes the old and the new tables; data from older SDKs shows up after about 15 minutes. | +| `legacy` | You want Langfuse 4 with Langfuse 3 behaviour for now. Writes only the old tables. Set `historicBackfill: false`. | + +With `events_only`, the following stop working: Python SDK v2 and older and JS/TS SDK v3 and older (rejected at ingestion), the legacy read endpoints such as `GET /api/public/traces` and `GET /api/public/observations` (404), every `POST /api/public/ingestion` event except scores, trace-level LLM-as-a-judge evaluators, and the "Traces and observations (legacy)" export source. + +`historicBackfill: true` copies the traces stored before the upgrade into the new tables, once, in the worker, newest first: older traces appear gradually, and the progress is under **Background Migrations**. While it runs the bucket holds up to about three times the current ClickHouse data. A scratch copy of the old observations stays in the bucket afterwards: the last step, which drops it, is off by default upstream, so **Background Migrations** keeps showing one unfinished row. After a backfill on top of `dual`, a trace can appear twice in the UI until ClickHouse merges the two copies in the background; the data is not damaged. With `dual`, Langfuse suggests leaving it off until the dual write is confirmed working, then turning it on in a later `helm upgrade`. With `legacy` it must be off. + +When every producer and consumer has moved, cut over with a `helm upgrade` setting `writeMode: events_only` (and `historicBackfill: true` if it has not run). From then on new data lands only in the new tables, so this is the point of no return. + +The traces list is now an **Observations** view filtered to `Is Root Observation = true`, one row per trace; clear the filter to see every observation. + ### Rotating Credentials A running workload keeps the credential values it started with, so every rotation ends with a forced redeployment. Change one key and keep the others with export, edit, apply: @@ -612,6 +672,7 @@ Between the datastore restarting and the Langfuse workloads coming back, Langfus - Sign-up is closed by default and the owner account comes from your secret. Record `adminPassword` — it is displayed nowhere, and with sign-up closed there is no other way to create the first account. - Give each install its own bucket. Two installs on one bucket share ClickHouse data parts under `clickhouse/`. - Give each release its own database, Redis and ClickHouse secrets. Secret names are org-wide, so two releases pointed at one secret share a password, and rotating it for one breaks the other. +- Upgrading from 1.3.0 is one-way and changes what older SDKs and the legacy APIs can do: read [Upgrading from 1.3.0](#upgrading-from-1-3-0) before you upgrade. - Serving Langfuse on your own domain requires `langfuse.publicUrl`, including the scheme. - With `publicAccess.enabled: false` there is no browser path to the UI; only other workloads in the GVC can reach the API. - Prerequisite secrets are not owned by the release: the auth, datastore credentials and GCS credentials secrets survive `helm uninstall` and must be deleted by hand if no longer wanted. diff --git a/template-catalog/templates/n8n.mdx b/template-catalog/templates/n8n.mdx index a1ca5d91..d6d31837 100644 --- a/template-catalog/templates/n8n.mdx +++ b/template-catalog/templates/n8n.mdx @@ -1,7 +1,7 @@ --- title: n8n icon: /template-catalog/templates/icons/n8n.png -description: Deploy n8n workflow automation on Control Plane with a bundled PostgreSQL database — highly available by default, single-instance optional — into an existing GVC. Three secrets must exist before install: the credential-encryption key, the owner login as a bcrypt hash, and the database credentials. +description: Deploy n8n workflow automation on Control Plane with a bundled PostgreSQL database — highly available by default, single-instance optional — into an existing GVC. Needs three secrets before install (encryption key, owner login as a bcrypt hash, database credentials). keywords: ['zapier alternative', 'make alternative', 'ipaas', 'no-code', 'low-code', 'self-hosted', 'fair-code', 'integration platform', 'api orchestration', 'scheduled triggers', 'webhook automation', 'n8n template', 'prerequisite secret', 'bcrypt hash', 'htpasswd'] --- @@ -116,7 +116,7 @@ Once all three secrets exist, install from the marketplace registry with the thr ```bash cpln helm install RELEASE_NAME oci://ghcr.io/controlplane-com/templates/n8n \ - --version 1.4.0 --gvc GVC_NAME \ + --version 1.5.0 --gvc GVC_NAME \ --set encryptionKey.secretName=ENCRYPTION_KEY_SECRET_NAME \ --set owner.secretName=OWNER_SECRET_NAME \ --set postgresHA.config.credentialsSecretName=DB_CREDENTIALS_SECRET_NAME @@ -153,7 +153,7 @@ Or follow the instructions for your preferred method: ### n8n Instance ```yaml -image: n8nio/n8n:2.29.8 +image: n8nio/n8n:2.45.4 # versions before 2.45.4 are refused (Critical CVEs) resources: minCpu: 250m @@ -215,6 +215,7 @@ postgresHA: # set postgresHA.enabled: false and postgres.enabled: true for a lig config: credentialsSecretName: my-n8n-db-credentials # PREREQUISITE dictionary secret (username, password, database) — must exist BEFORE install replicas: 3 + image: controlplanecorporation/patroni-postgres:0.8 # pgvector 0.8.7 (CVE-2026-103484); tags 0.1-0.7 are refused volumeset: capacity: 10 # initial capacity in GiB per replica (minimum is 10) @@ -314,7 +315,7 @@ Verify the instance is serving before you sign in: curl -s https://CANONICAL_ENDPOINT/healthz ``` -**Webhook URLs match the public address automatically.** The canonical hostname is only known once the workload runs, so the chart boots n8n through a start script that reads `CPLN_GLOBAL_ENDPOINT` and sets `N8N_HOST`, `WEBHOOK_URL`, and `N8N_EDITOR_BASE_URL` to `https://CANONICAL_ENDPOINT/`. The URLs n8n shows in the editor are therefore the ones external callers use, with no extra configuration. With `publicAccess.enabled: false` those URLs still point at the canonical endpoint, which external callers cannot reach — in that mode, in-GVC callers use the internal address above, and you reach the editor through a port-forward: +**Webhook URLs match the public address automatically.** The canonical hostname is only known once the workload runs, so the chart boots n8n through a start script that reads `CPLN_GLOBAL_ENDPOINT` and sets `N8N_HOST`, `N8N_WEBHOOK_URL`, and `N8N_EDITOR_BASE_URL` to `https://CANONICAL_ENDPOINT/`. The URLs n8n shows in the editor are therefore the ones external callers use, with no extra configuration. With `publicAccess.enabled: false` those URLs still point at the canonical endpoint, which external callers cannot reach — in that mode, in-GVC callers use the internal address above, and you reach the editor through a port-forward: ```bash cpln port-forward RELEASE_NAME-n8n 5678:5678 --gvc GVC_NAME @@ -492,6 +493,16 @@ Then upgrade with the `credentialsSecretName` of your database mode (`postgresHA The upgrade restarts the bundled PostgreSQL too (it now reads the new secret), so n8n can briefly lose its database; it reconnects by itself. While access to the new secret propagates, the new version of a workload can wait in `get-deployments` reporting that it is not allowed to reveal the secret; the previous version keeps serving meanwhile, and it clears by itself. +### Upgrading From 1.4.0 + +n8n moves from 2.29.8 to 2.45.4 and migrates its database on the first start. Rolling back to `1.4.0` is not supported, so back up the database first. The chart refuses any `n8nio/n8n` tag below 2.45.4, so if your values pin `image`, set it to `n8nio/n8n:2.45.4` or remove it. Schedule Triggers set to "every N seconds/minutes" now run N apart from when the workflow was activated, instead of on clock boundaries. + +In HA mode the database moves to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7. The database members restart and nothing limits that rollout, so expect a brief interruption of writes while the leader changes; n8n itself restarts as on any upgrade, which is the longer interruption, because its single replica stops before the new one serves. Upgrade in a quiet window. If your values set `postgresHA.image`, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. n8n's own tables do not use the `vector` extension, but a PGVector Vector Store node pointed at this database creates it. If it exists, run this in that database after the upgrade: + +```sql +ALTER EXTENSION vector UPDATE; +``` + ### Rotating the Database Password A running workload keeps the credential values it started with, and PostgreSQL reads the secret only when its data directory is first initialized, so editing the secret alone does not change the database password. Change one key and keep the others with export, edit, apply: @@ -588,7 +599,7 @@ pgx N curl -s -XPOST -d '{"force": true}' localhost:8008/reinitialize - **Editing the database credentials secret does not change the database password** — run `ALTER ROLE` first, then force-redeploy n8n; in HA mode move the leader first ([Rotating the Database Password](#rotating-the-database-password)). - **Give each n8n release its own database credentials secret** — secret names are org-wide, so two releases pointed at one secret share a password. - **Synchronous webhook responses must finish within 30 seconds** — see [Connecting](#connecting). -- **Every upgrade restarts the single n8n replica** — expect a brief editor and webhook outage; the first upgrade after an install can also restart the bundled database. +- **Every upgrade restarts the single n8n replica** — expect about two minutes of editor and webhook downtime while the replica is recreated and its volume reattaches; the first upgrade after an install can also restart the bundled database. - **Uninstall deletes the database and n8n volume sets** — all workflows, credentials, and execution data; enable backups if the data matters. - **n8n is fair-code under the Sustainable Use License** — free to self-host, not OSI open source. diff --git a/template-catalog/templates/postgres-highly-available.mdx b/template-catalog/templates/postgres-highly-available.mdx index 8ae45be7..182368cd 100644 --- a/template-catalog/templates/postgres-highly-available.mdx +++ b/template-catalog/templates/postgres-highly-available.mdx @@ -78,7 +78,7 @@ Install the chart from the marketplace registry, pointing it at the secret you c ```bash cpln helm install RELEASE_NAME oci://ghcr.io/controlplane-com/templates/postgres-highly-available \ - --version 2.7.0 --gvc GVC_NAME \ + --version 2.8.1 --gvc GVC_NAME \ --set config.credentialsSecretName=CREDENTIALS_SECRET_NAME ``` @@ -123,7 +123,7 @@ resources: # Patroni's Prometheus metrics are scraped by the platform automatically on the # REST API port — no knob, no exporter. See "Cluster metrics" in the README. -image: controlplanecorporation/patroni-postgres:0.7 +image: controlplanecorporation/patroni-postgres:0.8 # pgvector 0.8.7; tags 0.1-0.7 are refused multiZone: false ``` @@ -654,6 +654,16 @@ Two things changed in `2.6.0` that an upgrade does not apply to a cluster that a Also note that `failsafe_mode` is on for clusters created from `2.6.0`: when the leader loses etcd but every member still answers its REST API, it keeps serving instead of demoting. A cluster created earlier gains it only through `edit-config -s failsafe_mode=true`. +### Upgrading From 2.8.0 or Earlier + +Version 2.8.1 moves to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7. The fix is in the server library and takes effect when the upgrade restarts the members; existing data and indexes need nothing. If you pinned `image` in your values, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. + +In each database where you created the `vector` extension, `\dx` keeps reporting the old version until you run the following, which only updates that record: + +```sql +ALTER EXTENSION vector UPDATE; +``` + ### Scaling and Availability - **Leader loss fails over automatically.** When the leader stops answering, Patroni promotes the most up-to-date replica and HAProxy's health checks move port `5432` to it. Writes are refused in between and connections open at that moment are reset — build retry with backoff into your applications. diff --git a/template-catalog/templates/postgres-multi-location.mdx b/template-catalog/templates/postgres-multi-location.mdx index d19b556c..b6e85727 100644 --- a/template-catalog/templates/postgres-multi-location.mdx +++ b/template-catalog/templates/postgres-multi-location.mdx @@ -102,7 +102,7 @@ global: ```bash cpln helm install RELEASE_NAME oci://ghcr.io/controlplane-com/templates/postgres-multi-location \ - --version 2.0.0 --gvc GVC_NAME -f postgres-locations.yaml \ + --version 2.0.1 --gvc GVC_NAME -f postgres-locations.yaml \ --set postgres.credentialsSecretName=POSTGRES_CREDENTIALS_SECRET_NAME ``` @@ -176,7 +176,7 @@ Changing `global.locations` on a running release restarts every Patroni member a ### Image and Resources ```yaml -image: controlplanecorporation/patroni-postgres:0.7 +image: controlplanecorporation/patroni-postgres:0.8 resources: minCpu: 500m @@ -723,6 +723,20 @@ Values that changed: | `global.gvc.locations` | `global.locations` | | Bundled etcd Multi-Location 1.x | Pinned to **2.0.0**, which also creates no GVC | +### Upgrading From 2.0.0 + +Version 2.0.1 moves the default image to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7 and fixes CVE-2026-103484 (a database user who can create an IVFFlat index can run arbitrary code). It also changes how the HAProxy tier starts: a new proxy no longer waits for every member, and the old proxies keep serving until a new one is up. Nothing for you to do there. + +- Run `helm upgrade` in place. The fix is in the server library and applies on the upgrade's restart, which, like every upgrade of this chart, interrupts writes in every location and can lose the last writes acknowledged before it (see [Important Notes](#important-notes)). Stop writes first. +- Existing data and indexes need nothing. +- `\dx` keeps reporting the old `vector` version until you run the following in each database that has the extension; that only updates the recorded version. + + ```sql + ALTER EXTENSION vector UPDATE; + ``` + +- If your values pin `image` to `controlplanecorporation/patroni-postgres` 0.7 or earlier, the chart refuses to render: set it to `0.8`, or remove `image` from your values. + ### Scaling and Availability What the cluster survives follows from the quorum table in [Locations and Quorum](#locations-and-quorum); the points below are how each case plays out. @@ -753,7 +767,7 @@ With **two locations**, losing one loses consensus quorum permanently: the survi ```bash cpln helm upgrade RELEASE_NAME oci://ghcr.io/controlplane-com/templates/postgres-multi-location \ - --version 2.0.0 --gvc GVC_NAME -f postgres-locations.yaml \ + --version 2.0.1 --gvc GVC_NAME -f postgres-locations.yaml \ --set postgres.credentialsSecretName=POSTGRES_CREDENTIALS_SECRET_NAME \ --set etcd.recovery.forceNewClusterInLocation=LOCATION_NAME ``` @@ -895,7 +909,9 @@ cpln logs '{gvc="GVC_NAME", workload="RELEASE_NAME-postgres"} |= "[patroni]"' -- - **Set `primaryLocation` before the first install if you care where the primary is.** Changing it later restarts every member to move the leader; use `patronictl switchover` instead. - **Credentials are read only when the cluster first bootstraps.** Rotate with `ALTER ROLE` on the superuser and `repl`, then update the secret and redeploy — see [Rotating the Password](#rotating-the-password). - **Replication is asynchronous.** A failover can lose the most recent transactions, bounded by the replication lag at the moment of failure. -- **Every `cpln helm upgrade` can restart members in every location together, including a no-op one.** Expect a brief write outage; the data survives. The same applies to changing `primaryLocation`, `global.locations` or `backup.mode`. +- **Every `cpln helm upgrade` can restart members in every location together, including a no-op one.** Expect a brief write outage. +- **A `cpln helm upgrade` can lose recently acknowledged writes, so stop writes for the upgrade.** All members restart together, so the leader has no caught-up replica to hand over to, and the member that comes back first can be promoted before it has the last of the old primary's WAL (replication is asynchronous). The old primary rewinds and rejoins as a replica. +- **Existing data survives an upgrade** apart from those last writes. The same applies to changing `primaryLocation`, `global.locations` or `backup.mode`. - **With `internalAccess.type: workload-list`, list only your clients** — this release's own tiers are added for you. The bundled etcd tier is separate: `etcd.internalAccess.type: workload-list` requires adding `//gvc/GVC_NAME/workload/RELEASE_NAME-postgres` by hand. - **Leave etcd compaction at its defaults.** An uncompacted consensus store goes read-only and takes the database's failover with it. - **A WAL-G backup cannot be restored into the running cluster through this template.** The archive is restorable outside the release; see [Restoring a Backup](#restoring-a-backup). diff --git a/template-catalog/templates/timescaledb-highly-available.mdx b/template-catalog/templates/timescaledb-highly-available.mdx index 2ce93471..29815b64 100644 --- a/template-catalog/templates/timescaledb-highly-available.mdx +++ b/template-catalog/templates/timescaledb-highly-available.mdx @@ -80,7 +80,7 @@ Install the chart from the marketplace registry, pointing it at the secret you c ```bash cpln helm install RELEASE_NAME oci://ghcr.io/controlplane-com/templates/timescaledb-highly-available \ - --version 1.2.0 --gvc GVC_NAME \ + --version 1.2.1 --gvc GVC_NAME \ --set postgres.credentialsSecretName=CREDENTIALS_SECRET_NAME ``` @@ -123,7 +123,7 @@ resources: maxCpu: 1 maxMemory: 2Gi -image: timescale/timescaledb-ha:pg18.4-ts2.28.3 # PostgreSQL 18 + TimescaleDB 2.28.3 Community, Patroni bundled +image: timescale/timescaledb-ha:pg18.6-ts2.31.0 # PostgreSQL 18.6 + TimescaleDB 2.31.0 Community (pgvector 0.8.7), Patroni bundled multiZone: false # spread replicas across zones in the location ``` @@ -257,7 +257,7 @@ pgbouncer: poolMode: transaction # options: session, transaction, statement defaultPoolSize: 25 # real Postgres connections PgBouncer maintains per pod maxClientConn: 1000 # maximum client connections PgBouncer accepts per pod - maxDbConnections: 100 # hard cap on total Postgres connections across all pods + maxDbConnections: 100 # cap on Postgres connections per PgBouncer pod (pods do not coordinate) minReplicas: 2 maxReplicas: 4 resources: @@ -617,6 +617,28 @@ Template version `1.2.0` changes how new clusters are initialized, and an upgrad Also in `1.2.0`: `backup.resources.memory` rose from `128Mi` to `512Mi` because the smaller value OOM-killed the dump; passwords containing quotes or backslashes now work on both Patroni and PgBouncer. Before upgrading, confirm a recent backup actually completed — see [Backing Up](#backing-up). +### Upgrading From a Version Before 1.2.1 + +Version 1.2.1 moves the default image from `pg18.4-ts2.28.3` to `pg18.6-ts2.31.0`: PostgreSQL 18.6, TimescaleDB 2.31.0 and pgvector 0.8.7, which fixes CVE-2026-103484 (a database user who can build an IVFFlat index could run code as the server). An upgrade whose values still pin a `timescale/timescaledb-ha` tag with an older pgvector is refused at render; if you set `image` yourself, move it to the new tag. + +- The members restart onto the new image during the upgrade. PostgreSQL 18.4 to 18.6 needs no dump or restore. +- The pgvector fix is in the server library, so it applies on that restart; existing data and indexes need nothing. `\dx` keeps reporting the old `vector` version until you run `ALTER EXTENSION vector UPDATE;` in each database that has it, which only updates that record. +- **TimescaleDB stays at 2.28.3 in each existing database until you update it.** The image ships the new version, but nothing breaks meanwhile. Update it on the leader, in each database where `\dx timescaledb` lists it, soon after the upgrade (the nightly backup records the extension version, and a restore needs the same one). Find the leader, then update the extension in the app database: + +```bash +cpln workload exec RELEASE_NAME-timescaledb-ha --gvc GVC_NAME --container patroni-timescaledb \ + -- patronictl -c /tmp/patroni_config.yml list +``` + +```bash +# -X and -c make it the first command of a fresh session +cpln workload exec RELEASE_NAME-timescaledb-ha --gvc GVC_NAME --replica LEADER_MEMBER --container patroni-timescaledb \ + -- sh -c 'psql -X -h 127.0.0.1 -d "$APP_DATABASE" -c "ALTER EXTENSION timescaledb UPDATE;"' +``` + +- If you set `timescaledb.enable_columnarscan` (now `timescaledb.debug_enable_columnarscan`) or a granular refresh setting (now `timescaledb.cagg_granular_refresh_*`), move it to the new name. +- PostgreSQL 18.6 allows only the `pgoutput` and `test_decoding` logical decoding plugins by default; a consumer using another plugin needs it added to `output_plugin_libraries` (see the [18.6 release notes](https://www.postgresql.org/docs/release/18.6/)). + ### Scaling and Availability - **Leader loss fails over automatically.** When the leader stops answering, Patroni promotes the most up-to-date replica and HAProxy's health checks move port `5432` to it. Writes are refused in between and connections open at that moment are reset — build retry with backoff into your applications. diff --git a/template-catalog/templates/timescaledb.mdx b/template-catalog/templates/timescaledb.mdx index 534fa7af..914540a5 100644 --- a/template-catalog/templates/timescaledb.mdx +++ b/template-catalog/templates/timescaledb.mdx @@ -593,6 +593,7 @@ Three template versions changed what you must supply. An upgrade that still carr - **Public access is unencrypted.** The image ships no TLS certificates — keep `publicAccess.enabled: false` unless you accept plaintext connections. - **Restores need `timescaledb_pre_restore()` and `timescaledb_post_restore()`** around the replay, on a server with the same extension version — see [Restoring a Backup](#restoring-a-backup). - **`cpln helm uninstall` deletes the volume set** and the database with it; a final snapshot is kept for 7 days. Your credentials secrets are yours and are left alone. +- **The image's pgvector (0.8.1) is open to CVE-2026-103484.** A role that can build an IVFFlat index can run code on the server. The secret's user is a superuser, which can do that anyway; until the image ships pgvector 0.8.7, don't give roles you don't fully trust the right to create indexes on `vector` tables. - **Every `cpln helm upgrade` restarts the server.** Treat each one as a short planned write outage. ## External References diff --git a/template-catalog/templates/umami.mdx b/template-catalog/templates/umami.mdx index 1318b8b0..de6bfb76 100644 --- a/template-catalog/templates/umami.mdx +++ b/template-catalog/templates/umami.mdx @@ -74,6 +74,14 @@ cpln workload get-deployments RELEASE_NAME-umami --gvc GVC_NAME -o yaml The message reads `The secret no longer exists. Workload updates are paused until the secret is added or the reference to the secret removed.` It is `get-deployments` — plain `cpln workload get` has no `versions` key. Create the missing secret and the deployment recovers on its own within several minutes, or run `cpln workload force-redeployment RELEASE_NAME-umami --gvc GVC_NAME` to skip the wait. +Optional, for two-factor authentication (`app.twoFactorKeySecretName`, opaque): a 64-character hex key that encrypts users' TOTP secrets. Without it, two-factor setup in **Settings** reports that 2FA is not configured: + +```bash +printf '%s' "$(openssl rand -hex 32)" | cpln secret create-opaque --name my-umami-2fa-key --encoding plain -f - +``` + +Keep it for the life of the install. Changing or removing it locks every enrolled user, admin included, out of their account until the same key is restored. + Optional database backups need a bucket and access setup on AWS S3, Google Cloud Storage or an S3-compatible server, and S3-compatible servers additionally need a dictionary secret with the bucket keys — see [Backing Up](#backing-up). ## Installation @@ -82,7 +90,7 @@ Once both secrets exist, install the template into your GVC, naming them: ```bash cpln helm install RELEASE_NAME oci://ghcr.io/controlplane-com/templates/umami \ - --version 1.4.0 --gvc GVC_NAME \ + --version 1.5.0 --gvc GVC_NAME \ --set app.appSecretName=APP_SECRET_NAME \ --set postgres.config.credentialsSecretName=my-umami-db-credentials ``` @@ -116,7 +124,7 @@ Keep these settings in a values file (`--values`) rather than `--set`, because e ### Application ```yaml -image: ghcr.io/umami-software/umami:3.2.0 +image: ghcr.io/umami-software/umami:3.4.1 # versions before 3.4.1 are refused (Critical CVEs) replicas: 1 # 1 = single instance; 2+ = always-on tier with zero-downtime rolling restarts @@ -131,6 +139,7 @@ app: # and sessions. MUST EXIST BEFORE INSTALL; its value must stay stable. appSecretName: my-umami-app-secret disableTelemetry: true # opt out of Umami's anonymous usage telemetry + twoFactorKeySecretName: "" # optional opaque secret holding the two-factor key; "" = 2FA unavailable ``` Replicas are independent — they share only the database and the app secret, so a session opened against one replica is honored by the others. @@ -139,7 +148,7 @@ Replicas are independent — they share only the database and the app secret, so ```yaml tracker: - scriptName: "" # custom tracker script path, e.g. "s.js" (dodges ad blockers); "" = default /script.js + scriptName: "" # custom tracker script path, e.g. "s.js" (dodges ad blockers); "" = default /script.js; not "recorder.js" (Umami's session-replay script) collectEndpoint: "" # custom collect API path, e.g. "/api/track"; "" = default /api/send ``` @@ -176,6 +185,7 @@ postgresHA: # durable HA: 3-replica Patroni store with an HAProxy leader endpoin # password, database). Create it BEFORE you install. credentialsSecretName: my-umami-db-credentials replicas: 3 + image: controlplanecorporation/patroni-postgres:0.8 # pgvector 0.8.7 (CVE-2026-103484); tags 0.1-0.7 are refused volumeset: capacity: 10 # initial capacity in GiB per replica (minimum is 10) ``` @@ -263,7 +273,7 @@ Umami's bootstrap admin is a hardcoded `admin` / `umami`, seeded by its first da ```bash cpln helm upgrade RELEASE_NAME oci://ghcr.io/controlplane-com/templates/umami \ - --version 1.4.0 --gvc GVC_NAME \ + --version 1.5.0 --gvc GVC_NAME \ --set app.appSecretName=APP_SECRET_NAME \ --set postgres.config.credentialsSecretName=my-umami-db-credentials \ --set publicAccess.enabled=true @@ -470,6 +480,20 @@ Then upgrade with `postgres.config.credentialsSecretName` (single-instance mode) The upgrade restarts the bundled PostgreSQL too (it now reads the new secret), so Umami briefly loses its database and reconnects by itself. The new version of a workload can also wait for several minutes, with `get-deployments` reporting that it is not allowed to reveal the secret, while access to the new secret propagates; the previous version keeps serving meanwhile, and it clears by itself. +### Upgrading From 1.4.0 + +The image moves from Umami 3.2.0 to 3.4.1, which fixes Critical vulnerabilities in its bundled Next.js. The chart refuses any `ghcr.io/umami-software/umami` tag below 3.4.1, so if your values pin `image`, set it to `ghcr.io/umami-software/umami:3.4.1` or remove it. + +Umami migrates its database on first start (two-factor, session linking, annotations, API keys). Rolling back to `1.4.0` afterwards is not supported, so take a backup first if you need a way back. + +Two-factor authentication (new in Umami 3.3) needs the optional key secret described under [Prerequisites](#prerequisites). If you add it in the same upgrade, the new version can wait several minutes with `is not allowed to reveal the secret` in `get-deployments` while the new grant propagates; the previous version keeps serving. + +In HA mode (`postgresHA`) the database moves to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7. The database members restart and nothing limits that rollout, so expect a brief interruption of writes while the leader changes; Umami itself restarts as on any upgrade, and with a single Umami replica (the default) that is the longer interruption, because the old replica stops before the new one serves. Upgrade in a quiet window. Umami does not use the `vector` extension; if you created it yourself in a database, run this there after the upgrade. If your values set `postgresHA.image`, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. + +```sql +ALTER EXTENSION vector UPDATE; +``` + ### Rotating the Database Password PostgreSQL keeps the password it was initialized with, and a running workload keeps the values it started with, so a rotation takes three steps in order (single-instance; in HA mode follow [Rotating the Database Password in HA Mode](#rotating-the-database-password-in-ha-mode) instead): From 152fb1ff06b8d7ac2142087a701231767993b20c Mon Sep 17 00:00:00 2001 From: Jacob Cox Date: Thu, 29 Oct 2026 14:35:52 -0600 Subject: [PATCH 5/6] docs: quote chatwoot and gitea frontmatter descriptions (unquoted colon broke mintlify) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WZ5WWhTn9mEkPY7cLt1cr4 --- template-catalog/templates/chatwoot.mdx | 2 +- template-catalog/templates/gitea.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/template-catalog/templates/chatwoot.mdx b/template-catalog/templates/chatwoot.mdx index cca258bd..8307c15d 100644 --- a/template-catalog/templates/chatwoot.mdx +++ b/template-catalog/templates/chatwoot.mdx @@ -1,7 +1,7 @@ --- title: Chatwoot icon: /template-catalog/templates/icons/chatwoot.png -description: Deploy Chatwoot, the open-source live chat, shared inbox and omnichannel agent desk (Community Edition) with a background worker, a single-node Redis and a PostgreSQL that is highly available by default or single-instance. Needs an existing GVC and three dictionary secrets: keys, database and Redis. +description: "Deploy Chatwoot, the open-source live chat, shared inbox and omnichannel agent desk (Community Edition) with a background worker, a single-node Redis and a PostgreSQL that is highly available by default or single-instance. Needs an existing GVC and three dictionary secrets: keys, database and Redis." keywords: ['chat widget', 'help desk', 'customer support', 'intercom alternative', 'zendesk alternative', 'freshdesk alternative', 'crisp alternative', 'sidekiq', 'actioncable', 'websockets', 'pgvector', 'rails', 'chatwoot template'] --- diff --git a/template-catalog/templates/gitea.mdx b/template-catalog/templates/gitea.mdx index ad62c71f..6e724711 100644 --- a/template-catalog/templates/gitea.mdx +++ b/template-catalog/templates/gitea.mdx @@ -1,7 +1,7 @@ --- title: Gitea icon: /template-catalog/templates/icons/gitea.png -description: Single-replica Gitea Git server with web UI, Git-over-HTTPS, package registry and optional Git-over-SSH, backed by a bundled PostgreSQL. Deploys into an existing GVC and needs two dictionary secrets created before install: auth (admin login plus signing keys) and database credentials. +description: "Single-replica Gitea Git server with web UI, Git-over-HTTPS, package registry and optional Git-over-SSH, backed by a bundled PostgreSQL. Deploys into an existing GVC and needs two dictionary secrets created before install: auth (admin login plus signing keys) and database credentials." keywords: ['self-hosted git', 'git server', 'github alternative', 'gitlab alternative', 'gogs', 'source code management', 'pull requests', 'git clone', 'git lfs', 'container registry', 'jwt secret', 'secret key', 'rootless', 'developer tools'] --- From 5f96d8cedd113fbe8bdaef2277ba10d5c004eb6e Mon Sep 17 00:00:00 2001 From: Jacob Cox Date: Thu, 29 Oct 2026 14:41:49 -0600 Subject: [PATCH 6/6] =?UTF-8?q?docs:=20review=20fixes=20=E2=80=94=20pgvect?= =?UTF-8?q?or=20table=20(HA=20template=20now=200.8.7),=20user-facing=20wor?= =?UTF-8?q?ding=20for=20uptime-kuma=20and=20postgres-multi-location=20note?= =?UTF-8?q?s,=20n8n=20outage=20wording,=20grafana=20heading=20case?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01WZ5WWhTn9mEkPY7cLt1cr4 --- template-catalog/templates/grafana.mdx | 2 +- template-catalog/templates/n8n.mdx | 2 +- template-catalog/templates/pgvector.mdx | 2 +- template-catalog/templates/postgres-multi-location.mdx | 2 +- template-catalog/templates/uptime-kuma.mdx | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/template-catalog/templates/grafana.mdx b/template-catalog/templates/grafana.mdx index d813ad44..a662f3db 100644 --- a/template-catalog/templates/grafana.mdx +++ b/template-catalog/templates/grafana.mdx @@ -736,7 +736,7 @@ Then upgrade with `postgres.credentials` removed and the `credentialsSecretName` The upgrade restarts the bundled PostgreSQL too (it now reads the new secret), so Grafana can briefly lose its database; it reconnects by itself. The new version of a workload can also wait several minutes with `is not allowed to reveal the secret` in `get-deployments` while access to the new secret propagates; the previous version keeps serving meanwhile, and it clears by itself. -### Upgrading from 1.5.0 or earlier +### Upgrading from 1.5.0 or Earlier 1.5.1 moves the HA database (`postgresHA`) to `controlplanecorporation/patroni-postgres:0.8`, which carries pgvector 0.8.7 (CVE-2026-103484). The fix takes effect when the upgrade restarts the Patroni members; existing data needs nothing. Nothing limits that rollout, so expect a brief interruption of writes while the leader changes. Grafana itself restarts without a gap (the new replica serves before the old one stops); while the leader changes, Grafana can briefly answer valid users with 401. Upgrade in a quiet window. If you pinned `postgresHA.image` in your values, set it to the `0.8` tag: tags `0.1` to `0.7` are refused at render. Grafana does not use the `vector` extension; if you created it yourself in a database, `\dx` keeps reporting the old version until you run `ALTER EXTENSION vector UPDATE;` there, which only updates that record. Single-instance mode (`postgres`) is unchanged. diff --git a/template-catalog/templates/n8n.mdx b/template-catalog/templates/n8n.mdx index d6d31837..31703b30 100644 --- a/template-catalog/templates/n8n.mdx +++ b/template-catalog/templates/n8n.mdx @@ -599,7 +599,7 @@ pgx N curl -s -XPOST -d '{"force": true}' localhost:8008/reinitialize - **Editing the database credentials secret does not change the database password** — run `ALTER ROLE` first, then force-redeploy n8n; in HA mode move the leader first ([Rotating the Database Password](#rotating-the-database-password)). - **Give each n8n release its own database credentials secret** — secret names are org-wide, so two releases pointed at one secret share a password. - **Synchronous webhook responses must finish within 30 seconds** — see [Connecting](#connecting). -- **Every upgrade restarts the single n8n replica** — expect about two minutes of editor and webhook downtime while the replica is recreated and its volume reattaches; the first upgrade after an install can also restart the bundled database. +- **Every upgrade restarts the single n8n replica** — expect a brief editor and webhook outage; the first upgrade after an install can also restart the bundled database. - **Uninstall deletes the database and n8n volume sets** — all workflows, credentials, and execution data; enable backups if the data matters. - **n8n is fair-code under the Sustainable Use License** — free to self-host, not OSI open source. diff --git a/template-catalog/templates/pgvector.mdx b/template-catalog/templates/pgvector.mdx index 06a981f5..c518c241 100644 --- a/template-catalog/templates/pgvector.mdx +++ b/template-catalog/templates/pgvector.mdx @@ -500,7 +500,7 @@ Version `1.0.1` moves to pgvector 0.8.7, which fixes CVE-2026-103484: in 0.8.6 a | | pgvector template | postgres-highly-available | |---|---|---| | PostgreSQL | 18 | 17 | -| pgvector | 0.8.7 | 0.8.0 | +| pgvector | 0.8.7 | 0.8.7 | ### Troubleshooting diff --git a/template-catalog/templates/postgres-multi-location.mdx b/template-catalog/templates/postgres-multi-location.mdx index b6e85727..9c502cba 100644 --- a/template-catalog/templates/postgres-multi-location.mdx +++ b/template-catalog/templates/postgres-multi-location.mdx @@ -910,7 +910,7 @@ cpln logs '{gvc="GVC_NAME", workload="RELEASE_NAME-postgres"} |= "[patroni]"' -- - **Credentials are read only when the cluster first bootstraps.** Rotate with `ALTER ROLE` on the superuser and `repl`, then update the secret and redeploy — see [Rotating the Password](#rotating-the-password). - **Replication is asynchronous.** A failover can lose the most recent transactions, bounded by the replication lag at the moment of failure. - **Every `cpln helm upgrade` can restart members in every location together, including a no-op one.** Expect a brief write outage. -- **A `cpln helm upgrade` can lose recently acknowledged writes, so stop writes for the upgrade.** All members restart together, so the leader has no caught-up replica to hand over to, and the member that comes back first can be promoted before it has the last of the old primary's WAL (replication is asynchronous). The old primary rewinds and rejoins as a replica. +- **A `cpln helm upgrade` restarts every member together and can lose writes acknowledged just before it, so stop writes for the upgrade.** - **Existing data survives an upgrade** apart from those last writes. The same applies to changing `primaryLocation`, `global.locations` or `backup.mode`. - **With `internalAccess.type: workload-list`, list only your clients** — this release's own tiers are added for you. The bundled etcd tier is separate: `etcd.internalAccess.type: workload-list` requires adding `//gvc/GVC_NAME/workload/RELEASE_NAME-postgres` by hand. - **Leave etcd compaction at its defaults.** An uncompacted consensus store goes read-only and takes the database's failover with it. diff --git a/template-catalog/templates/uptime-kuma.mdx b/template-catalog/templates/uptime-kuma.mdx index 2dca3778..a7d7e4a2 100644 --- a/template-catalog/templates/uptime-kuma.mdx +++ b/template-catalog/templates/uptime-kuma.mdx @@ -293,7 +293,7 @@ This template is single-instance. Upstream Uptime Kuma supports no clustering, a - **Create the admin account over the tunnel before enabling public access** — until an account exists, anyone who can reach the dashboard can claim it. - **Upgrading from 1.1.0 or earlier closes public access unless you set `publicAccess.enabled: true`** — see [Upgrading From 1.1.0 or Earlier](#upgrading-from-1-1-0-or-earlier). -- **TCP Port monitors cannot detect a closed or unreachable external port** — outbound connections pass through the platform's sidecar, which completes the TCP handshake itself, so such a monitor stays UP. Watch external services with HTTP(s), keyword or DNS monitors instead; HTTP monitors do report a dead port as DOWN. +- **TCP Port monitors report a closed or unreachable external port as UP** — watch external services with HTTP(s), keyword or DNS monitors instead; HTTP monitors do report a dead port as DOWN. - **Single instance only** — there is no failover; a restart is a brief monitoring gap. - **All data lives on the volume set.** `cpln helm uninstall` deletes it, and a reinstall starts a fresh instance with a new setup wizard; the final snapshot is kept for 7 days. - **There are no cloud backups in this template** — take a manual volume set snapshot before risky changes.