Platform Installation
Install the CAT-BM operator, API, and UI with Helm.
The catalyx-canton Helm chart installs three components — the operator, the API, and the CatalyX UI component — plus the two custom resource definitions they depend on.
Before you install
Create the namespace
Create a namespace for the platform — any name works. This guide uses <namespace> as a placeholder throughout; substitute your own choice everywhere you see it.
kubectl create namespace <namespace>Create the identity provider secrets
Two secrets are required, both live in the release namespace, and both hold client secrets from an existing Keycloak realm — see Keycloak Realm Setup if that realm and its clients don't exist yet.
# The operator's Keycloak admin client secret
kubectl create secret generic catalyx-operator-keycloak \
--from-literal=admin-client-secret=<keycloak-admin-client-secret> \
-n <namespace>
# The API's Keycloak confidential client secret
kubectl create secret generic catalyx-api-credentials \
--from-literal=client-secret=<catalyx-api-client-secret> \
-n <namespace>catalyx-api-credentials is not optional. The API pod will not start without it — it fails with CreateContainerConfigError.
Create the TLS secret
The chart does not create a TLS certificate unless you enable cert-manager. The default name is catalyx-app-tls.
kubectl create secret tls catalyx-app-tls \
--cert=<path-to-cert.pem> --key=<path-to-key.pem> \
-n <namespace>This secret name is used by every ingress route the operator creates for validators, not just by the UI and API. If it does not exist, validator UIs will fail to serve over HTTPS even if you never set ingress.tls.secretName yourself.
Create the image pull secret
kubectl create secret docker-registry intellecteu-jfrog-access \
--docker-server=intellecteu-catbp-docker.jfrog.io \
--docker-username=<username> --docker-password=<token> \
-n <namespace>Install
helm install catalyx-canton catalyx/catalyx-canton \
-n <namespace> \
--set image.tag=v2.0.0 \
--set 'image.pullSecrets[0].name=intellecteu-jfrog-access' \
--set operator.keycloak.serverUrl=https://keycloak.example.com \
--set operator.keycloak.realm=my-realm \
--set operator.keycloak.adminClientId=catalyx-operator-admin \
--set operator.keycloak.adminClientSecretRef.name=catalyx-operator-keycloak \
--set api.auth.jwksUri=https://keycloak.example.com/realms/my-realm/protocol/openid-connect/certs \
--set ui.oidc.authority=https://keycloak.example.com/realms/my-realm \
--set ui.oidc.redirectUri=https://validators.example.com \
--set operatorRuntime.baseHostname=validators.example.com \
--set ingress.host=validators.example.com \
--set ingress.tls.secretName=catalyx-app-tlsContact IntellectEU support for the Helm repository URL and credentials.
Verify the rollout:
The UI is then available at https://<ingress.host>/, and the API at https://<ingress.host>/api.
Values you must set
These have defaults that are only suitable for local development. Every production install should override all of them.
ingress.host
Hostname the UI and API are served on. When empty, ingress routes match on path only, with no host clause.
ingress.tls.secretName
TLS secret for the UI and API routes.
operatorRuntime.baseHostname
Base hostname for every per-validator hostname the operator generates, and for the identity provider redirect URIs it registers. Changing it later rewrites those redirect URIs on the next reconcile.
operatorRuntime.tlsSecretName
TLS secret used by every ingress route the operator creates. Default catalyx-app-tls.
api.auth.jwksUri
JWKS endpoint the API validates UI tokens against.
ui.oidc.authority
OIDC issuer the UI redirects browser logins to.
ui.oidc.clientId
Public OIDC client for the UI. Default catalyx-canton-ui.
ui.oidc.redirectUri
Where the identity provider returns the browser after login. Must match a redirect URI registered on the client.
image.tag
Pin to a release tag. Default is latest.
image.pullSecrets
Pull secret for the IntellectEU registry.
Managed authentication values
Required only if you intend to use managedKeycloak: true on any validator.
operator.keycloak.serverUrl
Identity provider base URL.
operator.keycloak.realm
Realm the operator provisions into. Must already exist.
operator.keycloak.adminClientId
Admin client the operator authenticates as. Must exist in that realm.
operator.keycloak.adminClientSecretRef.name / .key
Secret holding the admin client secret. Key defaults to admin-client-secret.
operator.keycloak.apiClientId
The client that per-validator Ledger API scopes are attached to. Default catalyx-api.
Component values
operator.replicaCount
1
Must remain 1. The operator has no leader election; a second replica double-reconciles every resource.
api.replicaCount
1
Must remain 1. Canton console sessions are held in process, so they do not survive being load-balanced across replicas.
ui.replicaCount
2
The UI is stateless and runs highly available by default, with a pod disruption budget and topology spread.
api.namespace
release namespace
Namespace the API reads validators from. The API's RBAC is namespaced to the release namespace, so pointing this elsewhere produces authorisation errors.
operator.rbac.clusterAdmin
false
Leave false. When true, the operator service account is bound to cluster-admin instead of the chart's least-privilege role.
monitoring.serviceMonitor.enabled
false
Set true to have Prometheus scrape validator component metrics. Requires the Prometheus Operator CRDs.
certManager.enabled
false
Set true, with certManager.certificate.create and certManager.certificate.dnsNames, to have cert-manager issue the platform certificate.
Harden the OpenAPI endpoints before exposing the platform publicly. The chart publishes /swagger-ui and /v3/api-docs on the same hostname as the API, and both are served without authentication. If that is not acceptable in your environment, restrict them with a Traefik middleware via api.ingress.middlewares, or block them at your edge.
Upgrading
Helm does not upgrade CRDs. helm upgrade never touches the chart's crds/ directory. When a release changes the Validator or Application schema, apply the CRDs explicitly before upgrading:
Existing validators are re-reconciled after an upgrade. The operator applies rolling updates to component deployments, so a component with more than one replica is updated without downtime.
Last updated
Was this helpful?