Building Providers
Packaging & Deployment
The Helm chart shape, environment variables, Docker image, and publishing.
A provider ships as a container image plus a Helm chart. The quickstart provider’s chart (providers/quickstart/deploy/chart/) is the canonical copy-me template.
Chart shape
deploy/chart/
├── Chart.yaml
├── values.yaml
└── templates/
├── deployment.yaml # initContainer (init) + serve container
├── service.yaml # ClusterIP the hub proxies to
├── serviceaccount.yaml
└── catalogentry.yaml # renders manifest.yaml into a ConfigMap
The key wiring in deployment.yaml:
- initContainer runs your binary with
args: ["init"]. It mounts the hub-minted kubeconfig Secret (providerKubeconfig.secretName, defaultkedge-provider-kubeconfig, keykubeconfig) at/var/run/secrets/kedge/and the CatalogEntry ConfigMap at/etc/kedge/catalogentry/. The Secret mount is not optional — the pod naturally blocks until the hub’s provider reconciler has delivered it, which sequences bootstrap without any operator logic. - serve container runs the long-lived process: portal assets, backend API, controllers, MCP, heartbeat.
- The CatalogEntry goes into a ConfigMap, not the host cluster — it’s a kcp resource;
initapplies it into your provider workspace using the minted kubeconfig. In-cluster the chart pointsui.url/backend.urlat the Service DNS (http://<release>.<namespace>.svc.cluster.local:<port>).
values.yaml highlights: image.*, replicaCount (2 by default — drop to 1 only if you terminate revdial tunnels), service.port, hub.url, hub.tokenSecretRef, providerKubeconfig.secretName, catalogEntry.enabled.
Environment variables
The conventional contract your binary reads:
| Variable | Read by | Meaning |
|---|---|---|
KEDGE_PROVIDER_KUBECONFIG | init + serve | Path to the workspace kubeconfig |
KEDGE_SCHEMAS_DIR | init | APIResourceSchema directory (default /etc/kedge/schemas) |
KEDGE_CATALOGENTRY_FILE | init | CatalogEntry YAML to self-register (empty → skip) |
PORT | serve | HTTP listen port |
KEDGE_HUB_URL | serve | Hub URL for heartbeats |
KEDGE_PROVIDER_NAME | serve | CatalogEntry name used in the heartbeat path |
KEDGE_HUB_TOKEN / KEDGE_HUB_INSECURE | serve | Heartbeat auth / TLS toggle (dev) |
Providers with extra needs add their own namespaced vars (AGENTS_DATABASE_URL, GITHUB_OAUTH_*, …).
The Docker image
Three stages, mirroring the quickstart Dockerfile:
- Frontend —
npm ci && npm run buildproducesportal/dist. - Go build — the binary embeds
portal/distviago:embed(frontend must build first). - Runtime — distroless static, non-root, schemas baked at
/etc/kedge/schemas, entrypoint the binary.
Health, readiness, heartbeat
Serve /healthz → 200; the chart wires it into liveness and readiness probes, and the hub health-checks your backend.healthPath. Separately, heartbeat the hub every 30s — losing heartbeats (90s TTL) flips you Not-Ready: UI proxy 503s and your MCP tools drop out of federation.
Onboarding a provider to a hub
The admin-side steps, in order:
kubectl apply -f provider.yaml(theProviderobject) against the hub — provisions workspace, SA, kubeconfig Secret.- Copy the minted Secret (
<name>-kubeconfiginroot:kedge:system:providers) into the runtime cluster’s namespace where the chart expects it — or let your deployment tooling do it. helm installthe chart. Init bootstraps the API; serve starts heartbeating; the provider appears in the catalog.- If your export claims
*.faros.shgroups, supply the requiredidentityHashvalues from the hub admin view.
There’s also a fully self-supplied variant — you provide a workspace-admin kubeconfig yourself instead of the hub-minted one — useful for development or running a provider entirely outside the hub’s cluster. Everything downstream of the kubeconfig mount is identical.
Publishing
In the kedge monorepo each providers/<name> directory is split-mirrored (history preserved) to a standalone read-only repo faroshq/provider-<name>, and the provider’s go.mod module path is the mirror URL — so third parties can go get the code, while images and charts build from the monorepo CI. If you build out-of-tree, none of this applies to you: any repo that produces an image + chart with the contract above is a valid provider.