feat(mariadb): add mariadb-operator and the wordpress backup bucket

WordPress speaks MySQL natively. The PostgreSQL route would mean pg4wp, an
SQL-rewriting shim whose README lists WordPress 6.5.3 as its newest tested
version while renner.uno runs 7.0.4 — every core update would become a
compatibility gamble.

Charts are OCI artifacts, so this follows the OCIRepository pattern from
spegel rather than the HelmRepository pattern used for CNPG. CRDs ship as a
separate chart that upstream requires first, hence the dependsOn. The version
range is capped at the year boundary: the project uses calendar versioning and
ships an upgrade guide with each minor.

renner-uno-k8s-mariadb carries the same 30d noncurrent-version expiry as the
CNPG and Velero buckets, matched to the Backup resource's maxRetention.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014giKN9N6e5J2DF8QZmVh98
This commit is contained in:
2026-08-16 21:48:36 +02:00
co-authored by Claude Opus 5
parent 352f0b5cff
commit b976a67be8
7 changed files with 104 additions and 2 deletions
@@ -48,6 +48,10 @@ spec:
kind: HelmRelease
name: cloudnative-pg # DB operator — seed jobs create databases
namespace: database
- apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
name: mariadb-operator # the MySQL half — WordPress can't use CNPG
namespace: database
# decryption block dropped 2026-07-13: no *.sops.yaml left under this
# path — secrets come from OpenBao via ESO (MIGRATION-sops-openbao.md).
---
@@ -15,6 +15,7 @@ resources:
- rook-ceph/
- ceph-csi-drivers/
- cloudnative-pg/
- mariadb-operator/
- netbird-ingress/
- netbird-backup/
- coredns-config/
@@ -0,0 +1,81 @@
# MariaDB operator, for the one workload in this cluster that cannot use
# CloudNativePG: WordPress. WordPress speaks MySQL natively — the PostgreSQL
# route would mean pg4wp, an SQL-rewriting shim whose own README lists
# WordPress 6.5.3 as its newest tested version while renner.uno runs 7.0.4.
#
# The charts are OCI artifacts (ghcr.io), so this follows the OCIRepository
# pattern from infrastructure/spegel rather than the HelmRepository pattern
# used for CNPG.
#
# CRDs ship as a SEPARATE chart that must be installed first — upstream is
# explicit about the ordering, hence the dependsOn below rather than a single
# release with crds: CreateReplace.
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
name: mariadb-operator-crds
namespace: database
spec:
interval: 24h
url: oci://ghcr.io/mariadb-operator/charts/mariadb-operator-crds
ref:
# Calendar versioning: the major is the year. Upstream ships an upgrade
# guide with each minor (Helm repo deprecations, registry moves), so the
# range is capped at the year boundary instead of the usual open ">=".
semver: ">=26.6.0 <27.0.0"
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: mariadb-operator-crds
namespace: database
spec:
interval: 30m
chartRef:
kind: OCIRepository
name: mariadb-operator-crds
namespace: database
install:
remediation:
retries: 3
upgrade:
remediation:
retries: 3
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
name: mariadb-operator
namespace: database
spec:
interval: 24h
url: oci://ghcr.io/mariadb-operator/charts/mariadb-operator
ref:
semver: ">=26.6.0 <27.0.0"
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: mariadb-operator
namespace: database
spec:
interval: 30m
dependsOn:
- name: mariadb-operator-crds
namespace: database
chartRef:
kind: OCIRepository
name: mariadb-operator
namespace: database
install:
remediation:
retries: 3
upgrade:
remediation:
retries: 3
values:
# The operator watches all namespaces; the MariaDB CR itself lives with
# the app in kubernetes/apps/wordpress/, mirroring how CNPG Clusters sit
# in their consumer's namespace (ak-pg in authentik, im-pg in immich).
metrics:
enabled: false
@@ -0,0 +1,4 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- helmrelease.yaml
@@ -151,3 +151,12 @@ apiVersion: v1
kind: Namespace
metadata:
name: trmnl
---
# WordPress for www.renner.uno, migrated off the Hetzner VM `wordpress-hochzeit`.
# No privileged label needed: the cluster enforces `baseline`, which permits the
# official Apache image's root master process binding :80. It does trip the
# `restricted` audit/warn level — that is expected and not an error.
apiVersion: v1
kind: Namespace
metadata:
name: wordpress
@@ -30,6 +30,7 @@ spec:
- paperless
- trmnl
- velero
- wordpress
provider:
vault: # ESO's provider name; speaks OpenBao fine
server: http://openbao.openbao.svc.cluster.local:8200
+4 -2
View File
@@ -42,6 +42,7 @@ locals {
"renner-uno-k8s-velero", # Velero PVC backups (Kopia data mover)
"renner-uno-k8s-secrets", # SOPS talosconfig/kubeconfig for cluster bootstrap
"renner-uno-tfstate", # OpenTofu remote state (migrated off the nas-1 Garage S3)
"renner-uno-k8s-mariadb", # mariadb-operator logical dumps (wordpress-mariadb)
]
}
@@ -95,8 +96,9 @@ locals {
# 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
"renner-uno-k8s-cnpg" = 30
"renner-uno-k8s-velero" = 30
"renner-uno-k8s-mariadb" = 30 # Backup maxRetention: 720h (kubernetes/apps/wordpress/mariadb.yaml)
}
}