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/
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-appcannot restart Keycloak. An ERPNext migration onbreakpilot-controldoes not stall portal logins. - Independent backup policy. Each cluster has its own
[backup]block and its own S3 bucket so RPO targets inINFRASTRUCTURE.md §6can 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.nodemust match one of the cluster's declared VMs (vm-edge/vm-control/vm-app-prod/vm-app-stage)resources.memoryis mandatory (§8 rule 5)- no nested
depends_on/extra_ports/cmd/mountsunder[service.placement|resources|env|volume]