Files
orca-platform/clusters/README.md
T
Sharang Parnerkar 8971152da0
ci / shared (pull_request) Successful in 23s
ci / validate (pull_request) Successful in 4s
refactor(iac): cluster split — 1 cluster per plane, breakpilot-* naming
Restructures the draft to reflect the 2026-06-30 cluster decision:

Three Orca clusters, each becoming its own Gitea repo at migration time:
- breakpilot-edge   → vm-edge       (Identity + Infra: KC, Gitea, Infisical, PowerDNS, Orca-Proxy)
- breakpilot-control → vm-control   (Portal, tenant-registry, ERPNext, MariaDB, Stalwart)
- breakpilot-app    → vm-app-prod + vm-app-stage (CERTifAI, compliance-*, Mongo, MinIO, Qdrant, LiteLLM)

Key model points encoded:
- Identity (Keycloak) co-tenant with Infra on vm-edge (1 VM core), per
  INFRASTRUCTURE.md §6 — heap pinned so it cannot starve PowerDNS/Infisical
- Stage and prod live in the same breakpilot-app cluster on different
  VMs. Stage authenticates via prod Keycloak under tenant.kind = "stage";
  no duplicated identity, no duplicated control plane (per §5).
- The existing CERTifAI Keycloak will be repurposed for breakpilot-edge
  rather than standing up a fresh one — same realm, same users.
- Multi-VM rollout gated on legal entity being established so we can sign
  SysEleven / Hetzner business contracts. Until then, single-VM ops
  continues via ~/workspace/orca-infra; this repo is design-only.

Mechanical changes:
- manifests/{vm-edge,vm-control,vm-data,stage}/ → clusters/{breakpilot-edge,breakpilot-control,breakpilot-app/services/{prod,stage}}/services/
- vm-data → vm-app-prod, stage → vm-app-stage in node references and headers
- overlays/{stage,prod}/overlay.toml point at the new cluster paths
- scripts/validate.sh now enforces a per-cluster node whitelist
  (breakpilot-edge → vm-edge, breakpilot-control → vm-control,
  breakpilot-app → {vm-app-prod, vm-app-stage}) instead of dir-name equality
- New READMEs at clusters/, clusters/breakpilot-edge/,
  clusters/breakpilot-control/, clusters/breakpilot-app/ documenting
  scope, SLA targets, co-tenant notes, and the future-repo split
- Top README rewritten to lead with the cluster-split decision and the
  legal-entity gate; per-milestone fill-in table re-pathed

Validation:
- make validate → 38 files OK (35 manifests + 3 overlays)
- make plan ENV=stage → 11 resolved manifests in .orca-out/stage/
- make plan ENV=prod  → 24 resolved manifests in .orca-out/prod/
2026-06-30 22:14:51 +02:00

3.9 KiB

Clusters

Each subdirectory under clusters/ is the manifest set for one Orca cluster. At migration time each will become its own Gitea repository under platform/ so the cluster boundary doubles as a repository boundary.

Subdir Future repo VMs Plane
breakpilot-edge/ platform/breakpilot-edge vm-edge (1) Identity + Infra
breakpilot-control/ platform/breakpilot-control vm-control (1) Control
breakpilot-app/ platform/breakpilot-app vm-app-prod + vm-app-stage (2) App (was "Data")

Why one cluster per plane

  • Independent failure domain. A runaway reconcile loop in breakpilot-app cannot restart Keycloak. An ERPNext migration on breakpilot-control does not stall portal logins.
  • Independent backup policy. Each cluster has its own [backup] block and its own S3 bucket so RPO targets in INFRASTRUCTURE.md §6 can be set per plane without cross-talk.
  • Independent IaC. Each future repo has its own CI, CODEOWNERS, and reconcile cadence. Touching identity does not gate a portal hotfix.
  • Same Orca everywhere. Per-node ingress (every Orca node binds 80/443 with its own ACME) means each cluster's services get A records pointing at their own VM. No central proxy SPOF.

Why this is still a single repo today

We hold the three-cluster design in this one staging repo until the legal entity is established and we can sign SysEleven / Hetzner business contracts to provision actual VMs. Until then, everything runs on the existing single VM under orca-infra and these manifests are design-only — make validate keeps them honest, make apply is a no-op for now.

When the entity lands the migration is mechanical: split each subdir into its own Gitea repo, point its cluster.toml at a real VM, run orca deploy.

VM topology after migration

breakpilot-edge   cluster  →  vm-edge        (Keycloak + Gitea + Infisical + PowerDNS + Orca-Proxy)
breakpilot-control cluster →  vm-control     (Portal + Tenant-Registry + ERPNext + MariaDB + Stalwart)
breakpilot-app    cluster  →  vm-app-prod    (CERTifAI + compliance-* + Mongo + MinIO + Qdrant + LiteLLM)
                          \→  vm-app-stage   (slim parallel set for staging)

vm-app-stage lives in the same Orca cluster as vm-app-prod and points at PROD breakpilot-edge Keycloak + PROD breakpilot-control tenant-registry, isolated by tenant.kind = "stage" per INFRASTRUCTURE.md §5. No duplicated identity, no duplicated control plane.

Identity is part of the core (single VM)

The May 18 INFRASTRUCTURE.md had Identity (Keycloak) co-tenant with Infra on vm-edge, with JVM heap pinned at 1.5 GB so it cannot starve PowerDNS / Infisical. That decision stands — Identity lives in breakpilot-edge on the same VM as the rest of infra. We will revisit splitting Keycloak onto its own VM only if the JVM vs. infra fight actually shows up in alerts.

Repurposing the existing Keycloak

benjamin_boenisch/certifai already runs a Keycloak instance. Plan is to repurpose that instance into breakpilot-edge/services/keycloak.toml rather than stand up a fresh one — same realm exports, same client configurations, same user database. Migration is a hostname swap and a realm export/import, not a re-bootstrap.

Adding a new service

Pick the plane, then drop the manifest into the right services/ dir:

clusters/breakpilot-<plane>/services/<service>.toml
# breakpilot-app extras:
clusters/breakpilot-app/services/{prod,stage}/<service>.toml

scripts/validate.sh enforces:

  • placement.node must match one of the cluster's declared VMs (vm-edge / vm-control / vm-app-prod / vm-app-stage)
  • resources.memory is mandatory (§8 rule 5)
  • no nested depends_on / extra_ports / cmd / mounts under [service.placement|resources|env|volume]