> For the complete documentation index, see [llms.txt](https://docs.catalyx.solutions/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.catalyx.solutions/catalyx-blockchain-manager/canton-network/version-2.0/installation-instructions-canton/platform-installation.md).

# 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

{% stepper %}
{% step %}
**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.

```bash
kubectl create namespace <namespace>
```

{% endstep %}

{% step %}
**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](/catalyx-blockchain-manager/canton-network/version-2.0/installation-instructions-canton/keycloak-realm-setup.md) if that realm and its clients don't exist yet.

```bash
# 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>
```

{% hint style="danger" %}
`catalyx-api-credentials` is **not optional**. The API pod will not start without it — it fails with `CreateContainerConfigError`.
{% endhint %}
{% endstep %}

{% step %}
**Create the TLS secret**

The chart does not create a TLS certificate unless you enable cert-manager. The default name is `catalyx-app-tls`.

```bash
kubectl create secret tls catalyx-app-tls \
  --cert=<path-to-cert.pem> --key=<path-to-key.pem> \
  -n <namespace>
```

{% hint style="warning" %}
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.
{% endhint %}
{% endstep %}

{% step %}
**Create the image pull secret**

```bash
kubectl create secret docker-registry intellecteu-jfrog-access \
  --docker-server=intellecteu-catbp-docker.jfrog.io \
  --docker-username=<username> --docker-password=<token> \
  -n <namespace>
```

{% endstep %}
{% endstepper %}

***

## Install

```bash
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-tls
```

Contact IntellectEU support for the Helm repository URL and credentials.

Verify the rollout:

```bash
kubectl -n <namespace> get deploy
kubectl -n <namespace> wait --for=condition=Available deployment \
  -l app.kubernetes.io/instance=catalyx-canton --timeout=180s
```

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.

<table><thead><tr><th width="330">Value</th><th>Purpose</th></tr></thead><tbody><tr><td><code>ingress.host</code></td><td>Hostname the UI and API are served on. When empty, ingress routes match on path only, with no host clause.</td></tr><tr><td><code>ingress.tls.secretName</code></td><td>TLS secret for the UI and API routes.</td></tr><tr><td><code>operatorRuntime.baseHostname</code></td><td>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.</td></tr><tr><td><code>operatorRuntime.tlsSecretName</code></td><td>TLS secret used by every ingress route the operator creates. Default <code>catalyx-app-tls</code>.</td></tr><tr><td><code>api.auth.jwksUri</code></td><td>JWKS endpoint the API validates UI tokens against.</td></tr><tr><td><code>ui.oidc.authority</code></td><td>OIDC issuer the UI redirects browser logins to.</td></tr><tr><td><code>ui.oidc.clientId</code></td><td>Public OIDC client for the UI. Default <code>catalyx-canton-ui</code>.</td></tr><tr><td><code>ui.oidc.redirectUri</code></td><td>Where the identity provider returns the browser after login. Must match a redirect URI registered on the client.</td></tr><tr><td><code>image.tag</code></td><td>Pin to a release tag. Default is <code>latest</code>.</td></tr><tr><td><code>image.pullSecrets</code></td><td>Pull secret for the IntellectEU registry.</td></tr></tbody></table>

## Managed authentication values

Required only if you intend to use `managedKeycloak: true` on any validator.

<table><thead><tr><th width="380">Value</th><th>Purpose</th></tr></thead><tbody><tr><td><code>operator.keycloak.serverUrl</code></td><td>Identity provider base URL.</td></tr><tr><td><code>operator.keycloak.realm</code></td><td>Realm the operator provisions into. Must already exist.</td></tr><tr><td><code>operator.keycloak.adminClientId</code></td><td>Admin client the operator authenticates as. Must exist <strong>in that realm</strong>.</td></tr><tr><td><code>operator.keycloak.adminClientSecretRef.name</code> / <code>.key</code></td><td>Secret holding the admin client secret. Key defaults to <code>admin-client-secret</code>.</td></tr><tr><td><code>operator.keycloak.apiClientId</code></td><td>The client that per-validator Ledger API scopes are attached to. Default <code>catalyx-api</code>.</td></tr></tbody></table>

## Component values

<table><thead><tr><th width="300">Value</th><th width="150">Default</th><th>Notes</th></tr></thead><tbody><tr><td><code>operator.replicaCount</code></td><td><code>1</code></td><td><strong>Must remain 1.</strong> The operator has no leader election; a second replica double-reconciles every resource.</td></tr><tr><td><code>api.replicaCount</code></td><td><code>1</code></td><td><strong>Must remain 1.</strong> Canton console sessions are held in process, so they do not survive being load-balanced across replicas.</td></tr><tr><td><code>ui.replicaCount</code></td><td><code>2</code></td><td>The UI is stateless and runs highly available by default, with a pod disruption budget and topology spread.</td></tr><tr><td><code>api.namespace</code></td><td>release namespace</td><td>Namespace the API reads validators from. The API's RBAC is namespaced to the release namespace, so pointing this elsewhere produces authorisation errors.</td></tr><tr><td><code>operator.rbac.clusterAdmin</code></td><td><code>false</code></td><td>Leave <code>false</code>. When <code>true</code>, the operator service account is bound to <code>cluster-admin</code> instead of the chart's least-privilege role.</td></tr><tr><td><code>ui.grafana.baseUrl</code></td><td>—</td><td>Base URL for the Grafana deep links in the UI. See <a href="/catalyx-blockchain-manager/canton-network/version-2.0/console-guide-canton/grafana-dashboards.md">Grafana Links</a>.</td></tr><tr><td><code>monitoring.serviceMonitor.enabled</code></td><td><code>false</code></td><td>Set <code>true</code> to have Prometheus scrape validator component metrics. Requires the Prometheus Operator CRDs.</td></tr><tr><td><code>certManager.enabled</code></td><td><code>false</code></td><td>Set <code>true</code>, with <code>certManager.certificate.create</code> and <code>certManager.certificate.dnsNames</code>, to have cert-manager issue the platform certificate.</td></tr></tbody></table>

{% hint style="warning" %}
**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.
{% endhint %}

***

## Upgrading

```bash
helm upgrade catalyx-canton catalyx/catalyx-canton -n <namespace> -f my-values.yaml
```

{% hint style="danger" %}
**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:

```bash
kubectl apply -f <chart>/crds
```

{% endhint %}

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.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.catalyx.solutions/catalyx-blockchain-manager/canton-network/version-2.0/installation-instructions-canton/platform-installation.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
