Group F deliverables — completes the day-2 IaC layer that takes over after OpenTofu's Phase 0 hand-off (per docs/SOVEREIGN-PROVISIONING.md §4).
Three artifacts:
1. platform/crossplane/compositions/ — XRDs + Compositions for canonical Hetzner resources
under the canonical compose.openova.io/v1alpha1 group (per BLUEPRINT-AUTHORING.md §8):
- XHetznerNetwork + composition-network.yaml — wraps hcloud_network + subnet
- XHetznerFirewall + composition-firewall.yaml
- XHetznerServer + composition-server.yaml
- XHetznerLoadBalancer + composition-loadbalancer.yaml (lb11, 80→31080, 443→31443)
- README documenting the canonical pattern
2. clusters/_template/ — the canonical per-Sovereign Flux Kustomization tree.
Copied to clusters/<sovereign-fqdn>/ at provisioning time; cloud-init's
GitRepository points at the result.
- kustomization.yaml (root: flux-system + infrastructure + bootstrap-kit)
- flux-system/ (placeholder for Flux self-config customization)
- infrastructure/ (provider-hcloud + ProviderConfig referencing hcloud-credentials secret OpenTofu writes)
- bootstrap-kit/ — 11 HelmRelease manifests in dependency order:
01-cilium → 02-cert-manager → 03-flux → 04-crossplane → 05-sealed-secrets
→ 06-spire → 07-nats-jetstream → 08-openbao → 09-keycloak → 10-gitea → 11-bp-catalyst-platform
Each pulls from oci://ghcr.io/openova-io/bp-<name>:1.0.0 — the wrapper charts published by blueprint-release CI.
dependsOn declarations enforce the canonical install order at runtime.
3. clusters/omantel.omani.works/ — the first concrete Sovereign instance.
Mirror of _template with SOVEREIGN_FQDN_PLACEHOLDER substituted to omantel.omani.works.
This is what the wizard's first omantel.omani.works run will actually reconcile.
4. products/catalyst/bootstrap/api/cmd/catalyst-dns/main.go — small Go binary the
OpenTofu module's null_resource.dns_pool invokes via local-exec at Phase-0 apply time.
Reads DYNADOT_API_KEY/SECRET/DOMAIN/SUBDOMAIN/LB_IP env vars; calls existing dynadot.Client.AddSovereignRecords. Containerfile already builds + ships it at /usr/local/bin/catalyst-dns.
Architectural compliance (Lesson #24 closed):
- No bespoke Go cloud-API calls (Crossplane Compositions are the canonical day-2 IaC)
- No exec.Command("helm", ...) (Flux HelmReleases are the canonical install unit)
- No kubectl apply from outside (cloud-init kubectl-applies one Flux GitRepository, then Flux owns everything)
After this commit, the path is end-to-end: wizard → catalyst-api → tofu apply (with infra/hetzner/) → cloud-init installs k3s + Flux + applies GitRepository pointing at clusters/omantel.omani.works/ → Flux reconciles bootstrap-kit (11 HelmReleases in dependency order) → Crossplane adopts day-2 management.
50 lines
1.2 KiB
YAML
50 lines
1.2 KiB
YAML
# bp-crossplane — Catalyst bootstrap-kit Blueprint. Day-2 cloud resource control plane. Adopts management of resources OpenTofu created in Phase 0 (Phase 1 hand-off per SOVEREIGN-PROVISIONING.md §4).
|
|
#
|
|
# Wrapper chart: platform/crossplane/chart/
|
|
# Catalyst-curated values: platform/crossplane/chart/values.yaml
|
|
# Reconciled by: Flux on the new Sovereign's k3s control plane.
|
|
|
|
---
|
|
apiVersion: v1
|
|
kind: Namespace
|
|
metadata:
|
|
name: crossplane-system
|
|
labels:
|
|
catalyst.openova.io/sovereign: SOVEREIGN_FQDN_PLACEHOLDER
|
|
---
|
|
apiVersion: source.toolkit.fluxcd.io/v1beta2
|
|
kind: HelmRepository
|
|
metadata:
|
|
name: bp-crossplane
|
|
namespace: flux-system
|
|
spec:
|
|
type: oci
|
|
interval: 15m
|
|
url: oci://ghcr.io/openova-io/bp-crossplane
|
|
---
|
|
apiVersion: helm.toolkit.fluxcd.io/v2
|
|
kind: HelmRelease
|
|
metadata:
|
|
name: bp-crossplane
|
|
namespace: flux-system
|
|
spec:
|
|
interval: 15m
|
|
releaseName: crossplane
|
|
targetNamespace: crossplane-system
|
|
dependsOn:
|
|
- name: bp-flux
|
|
chart:
|
|
spec:
|
|
chart: bp-crossplane
|
|
version: 1.0.0
|
|
sourceRef:
|
|
kind: HelmRepository
|
|
name: bp-crossplane
|
|
namespace: flux-system
|
|
install:
|
|
remediation:
|
|
retries: 3
|
|
upgrade:
|
|
remediation:
|
|
retries: 3
|