Files
home-network-k3s-impl/clusters/base/backup.yaml
jakman85andClaude Opus 4.8 d1248e6778 feat(backup): wire Velero + CNPG Barman to the live MinIO S3 target
Author the GitOps side of off-cluster backups against the on-Proxmox MinIO
(http://192.168.1.9:9000, path-style; buckets velero + cnpg).

Velero (R-STATE-03):
- HelmRelease (chart 8.x / Velero 1.15) + velero-plugin-for-aws init container +
  node-agent kopia File System Backup (deployNodeAgent, uploaderType=kopia,
  snapshotsEnabled=false). BSL default -> bucket velero, s3ForcePathStyle.
- Two daily Schedules: `daily` backs up the whole cluster's resources+PVC data
  (defaultVolumesToFsBackup opt-out) EXCEPT monitoring+unifi; `daily-resources-only`
  captures monitoring+unifi RESOURCES only (Prometheus TSDB, Loki 72h logs, and the
  ~7.4GiB UniFi VM disk are reconstructable — excluded from volume backup).
- velero-cloud-credentials SOPS Secret (cloud INI key, ns velero).
- Own non-gating Flux tier clusters/base/backup.yaml (dependsOn platform-config,
  wait:false) + clusters/dev SOPS decryption patch — mirrors headlamp.

CNPG native Barman PITR (R-IDP-05 / R-STATE-03):
- keycloak-db, nextcloud-db, semaphore-db gain spec.backup.barmanObjectStore
  (s3://cnpg/<cluster>, endpointURL MinIO, gzip WAL+data, 30d retention) + a daily
  ScheduledBackup (6-field cron, immediate) each.
- Per-namespace scoped-key SOPS Secrets (<db>-backup-credentials), same-ns only.
- render.py: emit-waves now recognizes <svc>-db-backup-credentials.sops.yaml as a
  DB-wave sidecar (+ self-test); wave-0 kustomization regenerated.

Creds mirror platform/backup/minio-credentials.sops.yaml (scoped key k3s-backup),
SOPS round-trip verified with the cluster age key. gate: green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-08-28 22:37:17 -05:00

40 lines
1.9 KiB
YAML

---
# Flux Kustomization: Velero backup controller — reconciles ./platform/velero.
#
# OWN NON-GATING TIER (dependsOn platform-config, wait:false) — the same rationale as headlamp/
# oauth2-proxy/crafty. Velero is a BACKUP CONTROLLER; it must NEVER gate the platform graph. Its
# HelmRelease (chart + AWS plugin init-container + node-agent DaemonSet) can legitimately be
# not-Ready during a cold start (image pulls, the node-agent rolling out on every node, the BSL
# doing its first reachability probe against MinIO). If it sat in the gating `platform` tier, that
# transient unhealth would stall platform-config + every apps wave/vm on "dependency not ready" —
# exactly the failure headlamp already encodes. Nothing in the graph dependsOn backup, and wait:false
# guarantees its health can NEVER gate anything even if a future resource is (mistakenly) pointed at it.
#
# It reconciles AFTER platform-config only so the storage/CRD surface it backs up already exists; the
# backup path itself (Velero pods → http://192.168.1.9:9000) is independent of the rest of the graph.
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: velero
namespace: flux-system
spec:
interval: 10m
retryInterval: 2m
timeout: 5m
prune: true
wait: false
dependsOn:
- name: platform-config
sourceRef:
kind: GitRepository
name: flux-system
path: ./platform/velero
# cluster-vars feeds the backup cadence/retention knobs (${VELERO_BACKUP_SCHEDULE}, ${VELERO_RETENTION}).
postBuild:
substituteFrom:
- kind: ConfigMap
name: cluster-vars
# SOPS decryption for velero-cloud.sops.yaml (the scoped MinIO `cloud` credential) is layered per
# environment by the overlay (clusters/dev patches THIS Kustomization by name), identical to how
# headlamp/oauth2-proxy/crafty decrypt their own SOPS secrets. See clusters/dev/kustomization.yaml.