Quickstart — self-hosted cell
Bring up a single OpenDome cell that serves the OSL API, with no control-plane and no phone-home. This is the path a self-hoster takes; the managed/Enterprise product layers the central control-plane and console on top of the exact same charts.
Prerequisites
Section titled “Prerequisites”- A Kubernetes cluster (kind works) with:
- A CNI that enforces
NetworkPolicy— Cilium recommended. kind’s default kindnet does not enforce it. With Cilium, install it with--set 'policyCIDRMatchMode={nodes}'; without it, Cilium ignoresipBlockrules covering node/apiserver IPs and the bundled Postgres dead-locks at “Setting up primary”. (scripts/cluster-create.shdoes this for you on kind.) - An Ingress controller to reach the OSL API.
- A default StorageClass (for the bundled object store + Postgres PVCs).
- The CloudNativePG operator installed cluster-wide — only if you use the bundled Postgres.
- A CNI that enforces
helm≥ 3.12 andkubectl.
For ingress-nginx, install it stripping any client-supplied X-Actor-Roles at
the edge (defense in depth — the engine ignores the header in standalone anyway):
helm install ingress-nginx ingress-nginx/ingress-nginx \ -n ingress-nginx --create-namespace --version 4.11.3 \ --set-string 'controller.proxySetHeaders.X-Actor-Roles='If you use the bundled Postgres, install CloudNativePG first:
helm install cnpg cnpg/cloudnative-pg \ -n cnpg-system --create-namespace --version 0.27.1Bring up the cell
Section titled “Bring up the cell”-
The cell shell + bundled infra (object store + Postgres).
standard-tenantcreates the namespace, a deny-allNetworkPolicy(no control-plane allow rules), quotas, and — in the standalone profile — an in-namespace object store (RustFS) and CloudNativePG Postgres, plus thetenant-object-storageSecret.Ventana de terminal # The deny-all NetworkPolicy only lets pods reach the Kubernetes API through# this allowlist (CNPG's init needs it). Derive both addresses from YOUR# cluster — no per-distro guessing:APISERVER_VIP=$(kubectl get svc kubernetes -o jsonpath='{.spec.clusterIP}')APISERVER_EP=$(kubectl get endpoints kubernetes -o jsonpath='{.subsets[0].addresses[0].ip}')helm install demo charts/standard-tenant \-n tenant-demo --create-namespace \--set tenant=demo \--set "apiServerEgress.cidrs[0]=$APISERVER_VIP/32" \--set "apiServerEgress.endpointCidrs[0]=$APISERVER_EP/32"With no explicit values the chart mints random credentials on first install and reuses them on upgrades. Recover them any time:
Ventana de terminal kubectl -n tenant-demo get secret tenant-object-storage -o jsonpath='{.data.accessKey}' | base64 -dkubectl -n tenant-demo get secret postgres-postgresql -o jsonpath='{.data.password}' | base64 -d -
The OSL engine — the consumption surface.
Ventana de terminal helm install osl charts/tenant-semantic-api \-n tenant-demo \--set tenant.id=demo \--set ingress.host=osl.tenant-demo.127.0.0.1.nip.ioThis enables the opt-in Ingress and renders the OSL manifest locally from values. In the standalone profile the engine does not trust the
X-Actor-Rolesheader — a public Ingress caller cannot spoof roles. ACL’d access goes through the local token issuer: the chart generates a signing Secret and the engine validatesAuthorization: BearerHS256 tokens. -
Verify the cell is usable via its API — no control-plane.
Ventana de terminal HOST=osl.tenant-demo.127.0.0.1.nip.iocurl -fsS "http://$HOST/health" # {"status":"ok",...}curl -fsS "http://$HOST/osl/conformance" # engine + conformance levelscurl -fsS "http://$HOST/osl/schema" # compiled manifest (empty until you author facets) -
Mint a locally-signed token and make a governed call.
The token’s roles drive the ACL — facets honor them server-side.
Ventana de terminal TOKEN=$(scripts/osl-token.sh demo --roles analyst)curl -fsS -H "Authorization: Bearer $TOKEN" "http://$HOST/osl/schema"
If those return 200 with no opendome-system namespace present, the cell is
standalone-usable. Run scripts/oss-gate.sh to assert this end-to-end.
Optional layers
Section titled “Optional layers”- Structured leg (Trino + Nessie + Iceberg) —
charts/lakehouse. Defaults to in-namespace endpoints with credentials from thetenant-object-storageSecret; needs the bundled/external Postgres from step 1. - Config API (allowlist / pipeline / discovery) —
charts/tenant-config. Already standalone: uses the cell’s own Postgres + a directGET/PUT /config/{key}API. - Ingest / orchestration —
charts/dagster. Defaults: no control-plane callbacks, no upstream telemetry, Jobs run in this namespace.
Rebuilding images into your own registry
Section titled “Rebuilding images into your own registry”Released charts pin images by immutable digest (image.digest: sha256:…),
which takes precedence over the tag. That digest identifies OpenDome’s
published image — it is meaningless in any other registry. If you rebuild the
cell images into your own registry, clear the shipped digest or every pod
will ImagePullBackOff:
helm install osl charts/tenant-semantic-api \ --set image.repository=myreg.example/tenant-semantic-api \ --set image.digest="" # ← REQUIRED when you change the repositoryDo the same for tenant-mgmt-api.runnerImages.*. If you pull OpenDome’s
published images, leave the digest as shipped and cosign verify it.
Load real data
Section titled “Load real data”To serve real retrievals: create the bucket (tenant-demo) in your object
store, author OSL facets (UnstructuredFacet / JointEntity YAML under the
engine’s manifest.facets), and ingest Lance datasets to s3://tenant-demo/lance.
See Concepts for the manifest model and the
API reference for how retrieval is called.