- Shell 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
pipeline/ci trusted release-prepare: version bump + changelog on already-CI'd trunk code; no CI needed
|
||
| apis | ||
| crossplane-rbac | ||
| docs | ||
| instances | ||
| instances-post | ||
| tests | ||
| .gitattributes | ||
| CHANGELOG.md | ||
| LICENSE | ||
| NOTICE | ||
| README.md | ||
| VERSION | ||
platform-seanfarm
Crossplane XRDs and Compositions for the SeanFarm platform.
This repository is consumed by the seanfarm cluster: Flux pulls the apis/ and instances/ directories and Crossplane materialises the platform when claims are applied.
Layout
| Path | Purpose |
|---|---|
apis/<name>/ |
One XRD + Composition + Kustomization per platform API |
crossplane-rbac/ |
ClusterRoles aggregated into Crossplane (e.g. openbao.sean.farm/* permissions) |
instances/ |
Cluster claims — Cluster, Platform, Stack, PlatformUser, PlatformGroup, GitMirror |
package/ |
Reserved for future Crossplane Configuration packaging |
docs/ |
Crossplane primer and other API-level reference |
Compositions
Layered roughly from cluster-wide down to per-user:
| Layer | API kind | Purpose |
|---|---|---|
| Cluster | XCluster |
Tier-1 shared infra: openebs-zfs, cert-manager, cnpg, external-secrets, minio-operator, alloy, openbao-operator, etc. — wired via Flux Kustomizations. |
| Platform singleton | XPlatform |
Instantiated exactly once (Platform/seanfarm). Owns the SHARED stateful backends + cluster-wide secrets/TLS authority: the XPostgres/XMinIO singletons below, the OpenBao consumer CRs (internal-CA PKI root+intermediate, transit/cosign key, policies), and the GCP secrets-engine mount. Goes Ready before the tenant Stacks. |
| Platform → backend | XPostgres |
The SHARED CNPG Cluster — instantiated once by XPlatform as name=platform → cnpg-platform (5 instances). Per-tenant DBs are logical slices via TenantDatabase. |
| Platform → backend | XMinIO |
The SHARED MinIO Tenant — instantiated once by XPlatform as name=platform → minio (5 servers × 1 volume, EC:3+2). Per-tenant buckets are logical slices via TenantBucket. |
| Stack (per-tenant fan-out) | XStack |
Top-level per-tenant claim that fans out into the per-tenant logical slices + app components below. |
| Stack → slice | XTenantDatabase |
Per-tenant {tenant}_{app} databases + OpenBao-rotated roles in the shared CNPG. |
| Stack → slice | XTenantBucket |
Per-tenant {tenant}-* buckets + a scoped MinIO key in the shared MinIO. |
| Stack | XOIDCProvider |
Hydra + Kratos + Ory UI + Oathkeeper proxy + per-tenant ESO. |
| Stack | XPortal |
Portal nginx + per-tenant edge Gateway with all olly/forgejo/argocd/registry/workflows certs. |
| Stack | XForgejo |
Forgejo Deployment + admin bootstrap + OIDC config Job + admin token. |
| Stack | XMetrics |
VictoriaMetrics StatefulSet with per-tenant metric_relabel_configs. |
| Stack | XLogs |
Loki StatefulSet. |
| Stack | XTraces |
Tempo StatefulSet. |
| Stack | XGrafana |
Grafana Deployment with per-tenant VM/Loki/Tempo datasources. |
| Stack | XKomoplane |
Komoplane Crossplane-graph webui behind oathkeeper. |
| Stack | XTektonDashboard |
Tekton dashboard behind oathkeeper. |
| Stack | XRegistry |
Zot OCI registry behind oathkeeper. |
| Stack | XArgoCD |
ArgoCD Server/Controller + OIDC config. |
| Stack | XWorkflows |
Argo Workflows + shared-MinIO artifact repo + OIDC gate. |
| Per-user | XPlatformUser |
KratosIdentity + ForgejoUser per (user, stack). |
| Per-group | XPlatformGroup |
ForgejoTeam per (group, stack). |
| Per-repo | XGitMirror |
ForgejoRepository import + ForgejoPushMirror back to upstream. |
| Per-site | XStaticSite |
Public static-HTTP site (Deployment + Service + Cert + HTTPRoutes). |
OpenBao (the cluster secrets backend, successor to HashiCorp Vault as of
2026-06-03) has no Crossplane composition — its server is deployed by Flux
from the seanfarm repo (kubernetes/flux/infrastructure/openbao) into
openbao (+ per-tenant openbao-{tenant}). XPlatform only owns the
OpenBao consumer CRs (the shared OpenBaoConnection address record + PKI,
transit, policy, database, GCP CRs).
Lifecycle
Bootstrap order is Cluster → Platform → Stacks (enforced at the Flux layer):
XCluster lands the operators, then the Platform/seanfarm singleton brings up
the shared backends + CA, then each tenant Stack fans out its slices + apps.
Cluster claim (instances/seanfarm-cluster.yaml)
└─> XCluster/seanfarm → operators + Flux-wired tier-1 infra
Platform claim (instances/platform.yaml)
└─> XPlatform/seanfarm
├─> XPostgres/platform → cnpg-platform (shared CNPG, 5 instances)
├─> XMinIO/platform → minio (shared MinIO, EC:3+2)
├─> shared OpenBaoConnection + internal-CA PKI + transit/cosign + GCP mount
└─> (OpenBao SERVER itself is Flux-deployed, not Crossplane)
Stack claim (instances/alice.yaml)
└─> XStack/alice
├─> XTenantDatabase/alice → alice_{app} DBs in the shared CNPG
├─> XTenantBucket/alice → alice-* buckets in the shared MinIO
├─> XOIDCProvider/alice → ory-alice
├─> XPortal/alice → portal-alice
├─> XForgejo/alice → forgejo
├─> XMetrics/alice, XLogs/alice, XTraces/alice, XGrafana/alice → olly-alice
├─> XKomoplane/alice, XTektonDashboard/alice → olly-alice
├─> XRegistry/alice → registry-alice
├─> XArgoCD/alice → argocd-alice
└─> XWorkflows/alice → workflows-alice
Each XR's Composition runs the function-patch-and-transform pipeline against a static base: manifest with literal placeholder sentinels overwritten by patches:. See docs/CROSSPLANE-PRIMER.md for how patches and the placeholder pattern work.
Iterating
# In the cluster repo (~/src/seanfarm)
cd ~/src/platform-seanfarm
$EDITOR apis/oidc/composition.yaml
git commit -am "fix(oidc): ..." && git push
# Back in the cluster repo
cd ~/src/seanfarm
KUBECONFIG=./kubeconfig flux reconcile source git platform-seanfarm
KUBECONFIG=./kubeconfig flux reconcile kustomization platform-seanfarm-apis
If a schema removal leaves orphan fields on existing XRs (the validation will refuse to bind), nudge each affected claim:
kubectl annotate <claim>/<name> crossplane.io/paused=false --overwrite
Prerequisites
Already installed in the seanfarm cluster — listed here for reference:
- Crossplane v2.x
function-patch-and-transformprovider-kubernetes(with a defaultProviderConfig)provider-gcpfor theXCluster-managed cert-manager / external-dns paths- openbao-operator (manages
openbao.sean.farm/*CRDs that postgres + ESO consume) - forgejo-operator (manages
ForgejoRepository,ForgejoUser,ForgejoTeam, etc.) - kratos-identity-operator (manages
KratosIdentity)
License
MIT
This repo flows through the pipeline (gitops-flux, 2026-07-02)
Like seanfarm, this repo is a gitops-flux project: Forgejo sean/platform-seanfarm is the
writable head; codeberg stays the LIVE flux source + rebuild seed, advanced only by the
deploy's ff-only push. Routine flow:
git push forgejo feat/x
make -C ../seanfarm land PROJECT=platform-seanfarm BRANCH=feat/x
The deploy gates on this repo's 4 flux Kustomizations (apis / instances / instances-post /
rbac) reaching Ready@sha. Break-glass codeberg pushes still work (flux applies them) and are
caught by the next deploy's drift gate — recover with make -C ../seanfarm seanfarm-resync REPO=platform-seanfarm.