Merge pull request 'fix(opentofu): enable S3 versioning on Hetzner object storage buckets' (#227) from fix/issue-191 into master
ci/woodpecker/push/deploy-infrastructure Pipeline failed

This commit was merged in pull request #227.
This commit is contained in:
2026-07-14 19:08:16 +00:00
+66 -2
View File
@@ -48,7 +48,71 @@ locals {
resource "minio_s3_bucket" "k8s" {
for_each = var.enable_hetzner_buckets ? toset(local.hetzner_buckets) : toset([])
bucket = each.value
acl = "private"
bucket = each.value
acl = "private"
# object_locking can only be set at bucket-creation time (S3/MinIO
# semantics) — the provider silently ignores changes to this field on an
# existing bucket (no ForceNew, no Update handling: see
# aminueza/minio resource_minio_s3_bucket.go, Create-only consumption of
# ObjectLocking). These four buckets are already live (created with
# object_locking = false), so flipping this to true here would be a
# silent no-op, NOT a fix. Enabling object-lock requires destroying and
# recreating each bucket (full data migration) — tracked separately,
# see gitea issue #191 discussion. Do not set this to true without also
# planning the recreation.
object_locking = false
}
# Versioning: safe to enable on an already-existing bucket (unlike
# object_locking, this is a real, live S3/MinIO configuration knob, not a
# create-time-only attribute). This is the recoverability fix for issue
# #191: a leaked/misused S3 credential can no longer permanently destroy
# Velero backups, CNPG WAL archives, cluster secrets, or tfstate with a
# plain DeleteObject — the prior version survives until explicitly purged
# by version ID.
resource "minio_s3_bucket_versioning" "k8s" {
for_each = var.enable_hetzner_buckets ? toset(local.hetzner_buckets) : toset([])
bucket = minio_s3_bucket.k8s[each.key].bucket
versioning_configuration {
status = "Enabled"
}
}
locals {
# Buckets that receive high-churn, app-managed backups (Barman WAL/base
# backups, Kopia PVC snapshots via Velero) — versioning alone would let
# noncurrent versions accumulate forever as those tools prune and
# re-upload. Cap noncurrent-version retention to match the retention
# window the app layer already enforces, so old S3 versions don't outlive
# the backups that superseded them by more than that window:
# - CNPG ObjectStore retentionPolicy: "30d" (kubernetes/seed/*/objectstore.yaml)
# - Velero Schedule ttl: 720h0m0s = 30d (kubernetes/infrastructure/post-crds/velero-schedules.yaml)
# renner-uno-k8s-secrets and renner-uno-tfstate hold small, low-churn
# objects (kubeconfig/talosconfig, tfstate) with no existing retention
# precedent in this repo — left uncapped (keep every version) since
# storage cost there is negligible.
hetzner_buckets_noncurrent_expiry_days = {
"renner-uno-k8s-cnpg" = 30
"renner-uno-k8s-velero" = 30
}
}
resource "minio_s3_bucket_lifecycle" "k8s_noncurrent_expiry" {
for_each = var.enable_hetzner_buckets ? local.hetzner_buckets_noncurrent_expiry_days : {}
bucket = minio_s3_bucket.k8s[each.key].bucket
rule {
id = "expire-noncurrent-versions"
status = "Enabled"
noncurrent_version_expiration {
noncurrent_days = each.value
}
}
depends_on = [minio_s3_bucket_versioning.k8s]
}