sharang 6be727d404
ci / shared (push) Successful in 9s
ci / validate (push) Successful in 4s
refactor(iac): cluster split — 1 cluster per plane, breakpilot-* naming (#6)
3 Orca clusters (breakpilot-edge / breakpilot-control / breakpilot-app), 1 plane each. Single-VM core with Keycloak co-tenant on vm-edge. App cluster gets prod + stage VMs. Manifests reorganized into clusters/<name>/services/; validator now enforces per-cluster node whitelist. Multi-VM rollout gated on legal entity.
2026-06-30 20:30:14 +00:00
2026-05-19 09:35:02 +00:00
2026-05-19 09:35:02 +00:00

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: Architecture · Infrastructure · Implementation Plan

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.

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/<name>/ subdir into its own Gitea repo, point its cluster.toml at a real VM, run orca deploy. See 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=<env>` → .orca-out/<env>/
│   ├── apply.sh                    # `make apply ENV=<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-edgevm-edge
  • breakpilot-controlvm-control
  • breakpilot-appvm-app-prod or vm-app-stage

Run locally

IaC validation

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 for the full picture.

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=<env> Resolve manifests + overlay → .orca-out/<env>/
make apply ENV=<env> Push to Orca controller at $ORCA_API_URL (M1.2 brings this online)
make diff ENV=<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 — service name per individual container
  • On-call: oncall@breakpilot.com · runbooks at platform/docs/runbooks/

Contributing

See 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.

S
Description
IaC for VMs, Orca manifests, DNS, TLS, backups.
Readme
134 KiB
Languages
Shell 60.2%
Makefile 20.2%
JavaScript 12.2%
Go Template 7.4%