openova/docs
e3mrah f7796ef807
feat(bp-velero): Hetzner Object Storage backend wiring (closes #384) (#423)
* feat(bp-velero): Hetzner Object Storage backend wiring (closes #384)

Velero on a Hetzner Sovereign now writes its backups DIRECTLY to Hetzner
Object Storage per ADR-0001 §13 (S3-aware app architecture rule) +
docs/omantel-handover-wbs.md §3 — NOT SeaweedFS, which is reserved as a
POSIX→S3 buffer for legacy POSIX-only writers and is not in the minimal
Sovereign set.

Mirrors the Hetzner-direct backend pattern Agent #383 is wiring for
Harbor; both consume the canonical flux-system/hetzner-object-storage
Secret shipped by issue #371 (cloud-init writes 5 keys: s3-endpoint /
s3-region / s3-bucket / s3-access-key / s3-secret-key, derived from
the operator-issued Hetzner-Console keys + the per-Sovereign bucket
provisioned by OpenTofu's aminueza/minio resource).

platform/velero/chart/ (umbrella chart, bumped to 1.1.0):
  - templates/_helpers.tpl: NEW — bp-velero.fullname / bp-velero.labels
    helpers + bp-velero.hetznerCredentialsSecretName (default
    `velero-hetzner-credentials`).
  - templates/hetzner-credentials-secret.yaml: NEW — synthesises a
    velero-namespace Secret with a single `cloud` key in AWS-CLI INI
    format from .Values.veleroOverlay.hetzner.s3.{accessKey,secretKey}.
    The upstream Velero deployment mounts this at /credentials/cloud
    via existingSecret + AWS_SHARED_CREDENTIALS_FILE. Skip-render path
    when veleroOverlay.hetzner.enabled is false (default — keeps
    contabo render clean) or useExistingSecret is true (operator
    supplied Secret out-of-band).
  - values.yaml: BSL provider/region/s3Url/bucket fields populated as
    placeholders the per-Sovereign HelmRelease overrides via Flux
    valuesFrom; backupsEnabled defaults FALSE so default render emits
    no half-broken BSL; veleroOverlay.hetzner block surfaces the
    operator-overridable fields. Long-form rationale comments inline
    on each value per the chart's existing docstring style.

clusters/_template/bootstrap-kit/34-velero.yaml (+ omantel + otech):
  - dependsOn: bp-seaweedfs REMOVED — Velero is no longer a SeaweedFS
    consumer on Sovereigns (was the old SeaweedFS-tiered architecture
    that minimal-omantel retired in favour of cloud-native S3).
  - chart version bumped 1.0.0 → 1.1.0.
  - valuesFrom block added: 5 Secret-key entries pull each canonical
    s3-* key into the matching umbrella value path. Plaintext
    credentials never appear in the committed manifest; Flux
    dereferences valuesFrom at HelmRelease apply time.
  - values block adds the baseline veleroOverlay.hetzner.enabled=true
    + velero.credentials.{useSecret:true,existingSecret:velero-hetzner-
    credentials} + BSL provider/credential/s3ForcePathStyle scaffolding
    that the valuesFrom entries fill in.

docs/omantel-handover-wbs.md:
  - §2 row 19: " chart needs S3 endpoint rework" → "🟢 chart-released
    v1.1.0 — Hetzner Object Storage backend wired to #371 secret".
  - §9 #384 row: detailed status with smoke evidence.

Smoke evidence (contabo, default values — no Hetzner credentials):
  - helm template t . → renders cleanly (no Hetzner Secret, no BSL).
  - helm template t . --set veleroOverlay.hetzner.enabled=true \
      --set ...accessKey=AK_TEST --set ...secretKey=SK_TEST \
      --set velero.backupsEnabled=true (+ BSL config) →
      Secret/velero-hetzner-credentials with `cloud` INI key emitted +
      BackupStorageLocation/default with provider=aws,
      bucket=omantel-velero, region=fsn1,
      s3Url=https://fsn1.your-objectstorage.com.
  - helm install velero-smoke . -n velero-smoke (defaults) → pod
    velero-69bb84c5-669sh Ready 1/1 in 48s. Smoke torn down clean.

Hetzner-S3 E2E deferred to Phase 8 (first omantel run) — contabo has
no Hetzner Object Storage credentials so end-to-end backup→restore
verification can't run here.

Anti-duplication rule: NO bash scripts authored, NO parallel
implementations of upstream Velero functionality. Upstream Velero +
velero-plugin-for-aws natively support any S3-compatible backend; the
work here is values + a credential-shape adapter Secret, not a fork.

Closes #384.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(scripts): drop bp-seaweedfs dep from bp-velero expected DAG (#384)

Mirrors the dependsOn removal in clusters/_template/bootstrap-kit/34-
velero.yaml from the parent commit. Velero on Hetzner Sovereigns now
writes directly to Hetzner Object Storage (ADR-0001 §13 + WBS §3); no
in-cluster prerequisite Blueprint is required.

Local `bash scripts/check-bootstrap-deps.sh` now passes (0 drift,
0 cycles). The CI failure on the parent commit's PR was the audit
flagging bp-velero as having a missing edge to bp-seaweedfs because
this expected-DAG file still listed it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: hatiyildiz <269457768+hatiyildiz@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 17:24:44 +04:00
..
adr docs(adr): 0001 — Catalyst control-plane architecture (#354) 2026-05-01 10:37:47 +04:00
lessons-learned fix(bp-flux): catalyst-cluster-reconciler ClusterRoleBinding overlay (closes #338) (#393) 2026-05-01 15:56:45 +04:00
proposals feat(wizard): job dependencies SVG DAG + (stretch) timeline view (closes #206) (#212) 2026-04-29 21:40:43 +02:00
ARCHITECTURE.md docs(reconcile-pass-1): align docs with ground truth at dd578d1c 2026-04-29 09:40:10 +02:00
AUDIT-PROCEDURE.md docs(component-count): update 53 → 56 anchors after Pass 105 (spire + nats-jetstream + sealed-secrets) 2026-04-28 13:48:24 +02:00
BLUEPRINT-AUTHORING.md fix(bp-*): observability toggles default false — break circular CRD dependency 2026-04-29 19:23:52 +02:00
BOOTSTRAP-KIT-EXPANSION-PLAN.md docs(bootstrap-kit): expansion plan to 40+ HRs (Wave 2 dispatch reference) (#255) 2026-04-30 17:08:16 +04:00
BUSINESS-STRATEGY.md refactor(platform): remove k8gb — replaced by PowerDNS lua-records (#171) 2026-04-29 08:51:09 +02:00
CHART-AUTHORING.md fix(catalyst-chart): annotate api-deployment for Flux strategy-flip recovery 2026-04-29 18:04:07 +02:00
COMPONENT-LOGOS.md docs(reconcile-pass-2): align docs with ground truth at 6afdb303 2026-04-29 11:48:57 +02:00
DEMO-RUNBOOK.md docs(reconcile-pass-2): align docs with ground truth at 6afdb303 2026-04-29 11:48:57 +02:00
FRANCHISE-MODEL.md docs(franchise),test(billing): voucher CRD propagation invariant 2026-04-28 13:59:31 +02:00
GLOSSARY.md docs(reconcile-pass-1): align docs with ground truth at dd578d1c 2026-04-29 09:40:10 +02:00
IMPLEMENTATION-STATUS.md docs(reconcile-pass-2): align docs with ground truth at 6afdb303 2026-04-29 11:48:57 +02:00
INVIOLABLE-PRINCIPLES.md docs(principles): canonical INVIOLABLE-PRINCIPLES.md — 10 non-negotiable rules 2026-04-28 13:28:11 +02:00
MULTI-REGION-DNS.md docs(reconcile-pass-1): align docs with ground truth at dd578d1c 2026-04-29 09:40:10 +02:00
NAMING-CONVENTION.md refactor(platform): remove k8gb — replaced by PowerDNS lua-records (#171) 2026-04-29 08:51:09 +02:00
omantel-handover-wbs.md feat(bp-velero): Hetzner Object Storage backend wiring (closes #384) (#423) 2026-05-01 17:24:44 +04:00
ORCHESTRATOR-STATE.md docs(reconcile-pass-2): align docs with ground truth at 6afdb303 2026-04-29 11:48:57 +02:00
PERSONAS-AND-JOURNEYS.md docs(unified-repo-model): collapse SME and corporate to one shape — Application = Gitea Repo 2026-04-28 10:13:02 +02:00
PLATFORM-POWERDNS.md docs(reconcile-pass-1): align docs with ground truth at dd578d1c 2026-04-29 09:40:10 +02:00
PLATFORM-TECH-STACK.md docs(reconcile-pass-1): align docs with ground truth at dd578d1c 2026-04-29 09:40:10 +02:00
PRODUCT-FAMILIES.md docs(reconcile-pass-2): align docs with ground truth at 6afdb303 2026-04-29 11:48:57 +02:00
PROVISIONING-PLAN.md docs(reconcile-pass-2): align docs with ground truth at 6afdb303 2026-04-29 11:48:57 +02:00
RUNBOOK-OPERATIONS.md docs(ops): comprehensive operator runbook + remediation playbook + idempotent recovery script 2026-04-29 19:26:29 +02:00
RUNBOOK-PROVISIONING.md merge: keep k3s local-path-provisioner; mark StorageClass default before Flux runs (closes #189) 2026-04-29 19:43:59 +02:00
SECRET-ROTATION.md fix(cloudinit): create flux-system/ghcr-pull secret on Sovereign so private bp-* charts pull cleanly 2026-04-29 18:07:27 +02:00
SECURITY.md refactor(platform): remove k8gb — replaced by PowerDNS lua-records (#171) 2026-04-29 08:51:09 +02:00
SOVEREIGN-PROVISIONING.md docs(reconcile-pass-2): align docs with ground truth at 6afdb303 2026-04-29 11:48:57 +02:00
SRE.md refactor(platform): remove k8gb — replaced by PowerDNS lua-records (#171) 2026-04-29 08:51:09 +02:00
TECHNOLOGY-FORECAST-2027-2030.md refactor(platform): remove k8gb — replaced by PowerDNS lua-records (#171) 2026-04-29 08:51:09 +02:00
UI-REGRESSION-GUARDS.md fix(platform): sync blueprint.yaml versions with Chart.yaml (#199) 2026-04-29 22:07:55 +04:00
VALIDATION-LOG.md docs(reconcile-pass-2): align docs with ground truth at 6afdb303 2026-04-29 11:48:57 +02:00