Version matrix¶
Reproducible-from-zero infrastructure means pinning versions. "Latest" drifts; a guide that says "use the latest" is unreproducible by tomorrow. Below is the matrix this guide targets (verified June 2026). Treat the exact patch numbers as what to pin to today — always check the linked release pages and record what you actually deploy.
The components¶
| Component | Version | Why / dependency |
|---|---|---|
terraform-hcloud-kube-hetzner |
pin (e.g. 2.20.0) |
The platform module. Pin version, don't float. |
| k3s / Kubernetes | what the module installs (~1.35) | Needs to be a CNCF-supported release; 1.35 covers everything here. |
| CloudNativePG operator | 1.29.1 | Current stable. 1.29.1 fixes a critical CVE in the metrics exporter — do not use older. |
| PostgreSQL (operand) | 18.3 (system-trixie) |
The default operand in CNPG 1.29; managed via an ImageCatalog. |
kubectl-cnpg plugin |
match the operator (1.29.x) | Install via brew install kubectl-cnpg. |
| Barman Cloud Plugin | 0.12.0 | Backup/restore via CNPG-I. Requires CNPG ≥ 1.26 and cert-manager. |
| cert-manager | latest 1.x (verify) | Required by the Barman Cloud Plugin's TLS channel. Installed by the module. |
| Longhorn | what the module installs (pin it) | Storage. Provides snapshots and S3 backups. |
Security: do not skip the operator version
CloudNativePG 1.29.1 / 1.28.3 ship the fix for CVE-2026-44477 (critical, CVSS 9.4) in the metrics exporter. Since we enable monitoring metrics, an older operator would expose exactly the vulnerable component. Pin 1.29.1 or newer.
The dependency chain¶
Order matters. Each arrow is a "must exist before":
flowchart TB
k8s["k3s / Kubernetes ≥ supported"] --> cm["cert-manager"]
k8s --> lh["Longhorn + longhorn-postgres SC"]
cm --> bcp["Barman Cloud Plugin 0.12.0"]
k8s --> op["CNPG operator 1.29.1"]
op --> bcp
op --> icat["ClusterImageCatalog → PG 18.3"]
bcp --> os["ObjectStore (R2)"]
icat --> cl["Cluster"]
os --> cl
lh --> cl
cl --> pool["Pooler"]
cl --> sb["ScheduledBackup"]
Read it as: cert-manager and Longhorn (platform) come first; the operator and cert-manager both gate the Barman plugin; the operator gates the image catalog; the plugin gates the ObjectStore; and the Cluster needs the image catalog, the ObjectStore, and storage all in place.
Why these specific choices¶
- Barman Cloud Plugin, not in-tree
barmanObjectStore. The in-tree object store support is deprecated since CNPG 1.26 and scheduled for removal in 1.30. Writing a 2026 guide on the deprecated path would create immediate technical debt. The plugin is the living, supported path. The cost is two extra dependencies (cert-manager + the plugin) and one extra resource (ObjectStore). - ImageCatalog, not a hard-coded
imageName. Image catalogs (a headline feature of CNPG 1.29) map a Postgres major version to a specific, pinned, signed operand image. It centralizes image management and is the modern, fleet-friendly approach. - PostgreSQL 18. Released September 2025, supported into 2030; it is the current default operand and unlocks features like image-volume extensions.
How to capture versions for reproducibility¶
Because Layer 1 add-on versions come from the module, record what was actually deployed so you can pin it:
# Operator image (and thus version)
kubectl get deployment -n cnpg-system cnpg-controller-manager \
-o jsonpath='{.spec.template.spec.containers[*].image}'
# cert-manager and Longhorn versions
kubectl get pods -n cert-manager -o jsonpath='{.items[*].spec.containers[*].image}'
kubectl get pods -n longhorn-system -o jsonpath='{.items[*].spec.containers[*].image}'
# Kubernetes / k3s
kubectl version
Put the results into your kube.tf (cert_manager_version, longhorn_version)
and into your manifests, then never rely on "latest" again.
Where to go deeper¶
- CloudNativePG releases
- CloudNativePG supported releases
- Barman Cloud Plugin docs
- postgres-containers (operand images)
Next: the build begins with Layer 1 — the platform.