# orca-platform IaC staging for the Breakpilot Platform: per-cluster Orca service manifests, per-env overlays, DNS zones, backup/restore tooling, and the `make plan` / `make apply` wrappers. > Part of the **Breakpilot Platform**. For the big picture see [`platform/docs`](https://gitea.meghsakha.com/platform/docs): > [Architecture](https://gitea.meghsakha.com/platform/docs/src/branch/main/PLATFORM_ARCHITECTURE.md) · > [Infrastructure](https://gitea.meghsakha.com/platform/docs/src/branch/main/INFRASTRUCTURE.md) · > [Implementation Plan](https://gitea.meghsakha.com/platform/docs/src/branch/main/IMPLEMENTATION_PLAN.md) ## What this is The staging area for the future per-cluster Gitea repos. Every change to prod infrastructure will eventually flow through one of `platform/breakpilot-{edge,control,app}` — until those repos exist, every change to the *design* flows through this one. **Plane:** Infra (design only — no live cluster yet) **Owner:** @sharang **Status:** pre-alpha — manifests reflect the 2026-06-30 cluster-split decision; real values land per the milestone schedule below ## The cluster split (decided 2026-06-30) Three Orca clusters, each becoming its own Gitea repo at migration time: | Cluster | Future repo | VMs (steady state) | 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 | Identity (Keycloak) is part of `breakpilot-edge` on the **same VM** as the rest of infra — single-VM core, JVM heap pinned so it cannot starve PowerDNS/Infisical. The Keycloak instance already running for CERTifAI will be repurposed for `breakpilot-edge` rather than standing up a new one. Stage and prod share the **same** `breakpilot-app` cluster but live on **different VMs** (`vm-app-stage` is a small Hetzner CX22-class box). Same orca config, no config drift; physically isolated, no "oops touched prod" accidents. Stage authenticates via prod Keycloak and reads tenant config from prod `tenant-registry` under `tenant.kind = "stage"` — no duplicated identity, no duplicated control plane. ### Gate: legal entity Multi-VM rollout is gated on the legal entity being established so we can sign SysEleven / Hetzner business contracts. Until then, everything runs on the existing single VM via the `~/workspace/orca-infra` repo and the manifests in this repo are design-only. `make validate` keeps the design honest; `make apply` is a no-op for now. When the entity lands the migration is mechanical: split each `clusters//` subdir into its own Gitea repo, point its `cluster.toml` at a real VM, run `orca deploy`. See [`clusters/README.md`](./clusters/README.md) for the migration order. ## Directory layout ``` . ├── clusters/ # one subdir per future cluster repo │ ├── README.md the cluster split + migration plan │ ├── breakpilot-edge/ Identity + Infra (vm-edge) │ │ ├── README.md │ │ └── services/ (8 services) │ ├── breakpilot-control/ Control plane (vm-control) │ │ ├── README.md │ │ └── services/ (7 services) │ └── breakpilot-app/ App plane (vm-app-prod + vm-app-stage) │ ├── README.md │ └── services/ │ ├── prod/ (9 services on vm-app-prod) │ └── stage/ (11 services on vm-app-stage) ├── overlays/ # per-env sparse deltas │ ├── dev/overlay.toml no-op; dev runs docker-compose per-service │ ├── stage/overlay.toml → clusters/breakpilot-app/services/stage │ └── prod/overlay.toml → all three clusters' prod paths ├── dns/ │ └── breakpilot.com.zone.template PowerDNS zone — body lands in M0.3 ├── cluster.toml.tmpl # cluster-level template (acme_email, backup, ai) ├── scripts/ │ ├── validate.sh # `make validate` — TOML + per-cluster node check │ ├── plan.sh # `make plan ENV=` → .orca-out// │ ├── apply.sh # `make apply ENV=` (no-op until M1.2) │ └── restore-drill.sh.template # M1.3 placeholder ├── dev/ # local docker-compose for product devs └── Makefile # validate / plan / apply / diff / clean ``` `scripts/validate.sh` enforces that every service's `placement.node` matches one of the cluster's declared VMs: - `breakpilot-edge` → `vm-edge` - `breakpilot-control` → `vm-control` - `breakpilot-app` → `vm-app-prod` or `vm-app-stage` ## Run locally ### IaC validation ```bash make validate # check all manifests parse + have required fields + cluster-correct nodes make plan ENV=stage # resolve manifests for stage → .orca-out/stage/ make plan ENV=prod # same for prod make apply ENV=stage # no-op until M1.2 stands up the Orca controller ``` `make validate` runs in CI on every PR. ### Dev stack `platform/orca-platform` doubles as the home for the local-dev compose stack so a developer can clone this repo, run `make dev-up`, and immediately work against a real Keycloak realm + Postgres / Redis / Mongo / MinIO. See [`dev/README.md`](./dev/README.md) for the full picture. ```bash make dev-up # Keycloak (:8080) + Postgres (:5432) + Redis (:6379) + Mongo (:27017) + MinIO (:9000) make dev-down # stop, keep volumes make dev-reset # stop, wipe, fresh ``` Seed user: `test@breakpilot.dev` / `test` (tenant `acme`, products `certifai` + `compliance`). ## Per-milestone fill-in schedule Each stub manifest carries a header comment naming the milestone that finalises its real values. Summary: | Milestone | What it fills in | |---|---| | **M0.3** | `breakpilot-edge/services/powerdns-auth.toml`, DNS zone body, orca-proxy routes | | **M1.2** | VM provisioning (Terraform/OpenStack in a separate repo); brings `make apply` online | | **M1.3** | Backup cron services + `scripts/restore-drill.sh` | | **M2.1** | `breakpilot-edge/services/{keycloak,pg-keycloak}.toml` (repurposed from CERTifAI Keycloak) | | **M3.1** | `breakpilot-edge/services/{infisical,pg-infisical,redis-infisical}.toml` | | **M3.2** | `breakpilot-control/services/stalwart.toml` | | **M4.1** | `breakpilot-control/services/tenant-registry.toml` + `breakpilot-app/services/prod/pg-app.toml` | | **M5.1** | `breakpilot-control/services/customer-portal.toml` + stage equivalents | | **M6.x** | `breakpilot-app/services/prod/{certifai-dashboard,mongodb,litellm}.toml` | | **M7.x** | compliance services on `breakpilot-app/services/{prod,stage}/` | | **M8.1** | `breakpilot-control/services/{erpnext,mariadb,redis-erpnext}.toml` | | **M9.1** | `breakpilot-control/services/frappe-hd.toml` | Until the milestone PR lands, the stub still parses and `make validate` stays green — but `apply` will refuse a stub that hasn't replaced its `placeholder` image tag (gate to be added with the first real image). ## Endpoints / surface | Target | What it does | |---|---| | `make validate` | Parse + structural check + per-cluster node check (no cluster contact) | | `make plan ENV=` | Resolve manifests + overlay → `.orca-out//` | | `make apply ENV=` | Push to Orca controller at `$ORCA_API_URL` (M1.2 brings this online) | | `make diff ENV=` | Alias for `plan` | | `make clean` | Remove `.orca-out/` | ## Deployment | Env | Apply path | Trigger | |---|---|---| | dev | `docker-compose` in each product repo | dev's machine | | stage | `make apply ENV=stage` against the `breakpilot-app` Orca controller | CI on merge to main + image build | | prod | `make apply ENV=prod` against the `breakpilot-app` Orca controller | release tag `vX.Y.Z` + sign-off | `apply` for prod will be gated by the production-promotion gate (24h stage soak + manual sign-off) per `IMPLEMENTATION_PLAN.md §1.6`. Wiring lands in M1.2. ## Observability - Traces, logs, metrics: [SigNoz](https://signoz.meghsakha.com) — service name per individual container - On-call: `oncall@breakpilot.com` · runbooks at `platform/docs/runbooks/` ## Contributing See [`CONTRIBUTING.md`](./CONTRIBUTING.md). Every PR touching `clusters/` MUST keep `make validate` green; CI enforces it. ## License Proprietary — all rights reserved. Copyright (c) 2026 Sharang Parnerkar and Benjamin Boenisch. See [`LICENSE`](./LICENSE).