Skip to main content
Version: v1.4.8
Not interested in using Kubernetes?

There are two flavours of Control Plane deployments - Remote and Kubernetes. This guide will focus on deploying a Control Plane on a Kubernetes cluster. Go to Remote - Deploy Control Plane to deploy the Control Plane on a Linux host instead. Keep in mind that in such case, it will be necessary to prepare the host for Controller as well.

Also, this guide will use Helm to deploy the Control Plane on the cluster. To use potctl instead, go to Kubernetes - Deploy Control Plane Using potctl.

Kubernetes - Deploy Control Plane Using Helm

In this tutorial, we will install the Datasance PoT (Proof of Technology) Control Plane on Kubernetes using Helm.

The Helm Chart deploys the PoT operator (iofog-operator) and creates a ControlPlane custom resource instance automatically. The Operator consumes this CRD and creates deployments for the Controller and Router, as well as associated services.

Prerequisites

Add the Helm Repository

Add the Datasance Helm repotsitory to your local index:

helm repo add datasance https://datasance.github.io/helm
helm repo update

Install the Chart

Install the Chart while specifying the required authentication configuration. The chart requires Keycloak/OpenID Connect authentication settings. You can provide these values either via a values file or using --set flags.

Quick Install with Flags

helm install pot-operator datasance/pot -n pot --create-namespace \
--set controlplane.spec.auth.url=https://keycloak.example.com \
--set controlplane.spec.auth.realm=pot \
--set controlplane.spec.auth.realmKey=master \
--set controlplane.spec.auth.ssl=true \
--set controlplane.spec.auth.controllerClient=pot-controller \
--set controlplane.spec.auth.controllerSecret=supersecret \
--set controlplane.spec.auth.viewerClient=pot-viewer

Install with Values File

Create a myvalues.yaml file with your configuration:

operator:
image: ghcr.io/datasance/operator:3.5.4
controlplane:
spec:
# Database is optional; if omitted, the controller uses internal SQLite.
# When using SQLite, keep controller replicas at 1.
database:
provider: postgres
host: db
port: 5432
user: pot
password: changeme
databaseName: pot
ssl: false
auth:
url: https://keycloak.example.com
realm: pot
realmKey: master
ssl: true
controllerClient: pot-controller
controllerSecret: supersecret
viewerClient: pot-viewer

Then install using the values file:

helm install pot-operator datasance/pot -n pot --create-namespace \
-f myvalues.yaml

The install creates:

  • CRDs for controlplanes.datasance.com
  • The PoT operator (iofog-operator) Deployment + RBAC + ServiceAccount
  • One ControlPlane instance (toggle with controlplane.create)

Verify Installation

To list all Helm releases, run:

helm list -n pot

The result should look like this:

NAME          REVISION  UPDATED                   STATUS    CHART        APP VERSION  NAMESPACE
pot-operator 1 Tue Dec 8 21:34:42 2025 DEPLOYED pot-3.5.4 3.5.4 pot

Configuration

The Helm chart supports extensive configuration through values. You can view the complete default values.yaml file.

Required Values

The following authentication values must be set via values.yaml or --set:

  • controlplane.spec.auth.url - Keycloak/OpenID Connect server URL
  • controlplane.spec.auth.realm - Keycloak realm name
  • controlplane.spec.auth.realmKey - Realm key (typically "master")
  • controlplane.spec.auth.ssl - Enable SSL (true/false)
  • controlplane.spec.auth.controllerClient - Controller OIDC client ID
  • controlplane.spec.auth.controllerSecret - Controller OIDC client secret
  • controlplane.spec.auth.viewerClient - Viewer OIDC client ID

Common Configuration Options

Operator Configuration

# Operator image and replicas
--set operator.image=ghcr.io/datasance/operator:3.5.4
--set operator.replicaCount=1
--set operator.imagePullPolicy=Always

# Resource limits
--set operator.resources.requests.cpu=100m
--set operator.resources.requests.memory=128Mi
--set operator.resources.limits.cpu=500m
--set operator.resources.limits.memory=512Mi

# Node scheduling
--set operator.nodeSelector.kubernetes.io/os=linux
--set operator.tolerations[0].key=node-role.kubernetes.io/master
--set operator.tolerations[0].effect=NoSchedule

ControlPlane Metadata

--set controlplane.create=true
--set controlplane.name=pot
--set controlplane.namespace=pot

Database Configuration (Optional)

If omitted, the controller uses internal SQLite (keep controller replicas at 1):

--set controlplane.spec.database.provider=postgres
--set controlplane.spec.database.host=db
--set controlplane.spec.database.port=5432
--set controlplane.spec.database.user=pot
--set controlplane.spec.database.password=changeme
--set controlplane.spec.database.databaseName=pot
--set controlplane.spec.database.ssl=false

Controller Configuration

--set controlplane.spec.replicas.controller=1
--set controlplane.spec.controller.logLevel=info
--set controlplane.spec.controller.https=false
--set controlplane.spec.controller.secretName=tls-secret

Service Configuration

--set controlplane.spec.services.controller.type=LoadBalancer
--set controlplane.spec.services.router.type=LoadBalancer

Ingress Configuration

--set controlplane.spec.ingresses.controller.host=controller.example.com
--set controlplane.spec.ingresses.controller.ingressClassName=nginx
--set controlplane.spec.ingresses.controller.annotations.cert-manager.io/cluster-issuer=letsencrypt-prod

Image Configuration

--set controlplane.spec.images.controller=ghcr.io/datasance/controller:3.5.11
--set controlplane.spec.images.routerAdaptor=ghcr.io/datasance/router-adaptor:3.5.2
--set controlplane.spec.images.router=ghcr.io/datasance/router:3.5.2
--set controlplane.spec.images.pullSecret=my-registry-secret

Events Configuration

--set controlplane.spec.events.auditEnabled=true
--set controlplane.spec.events.retentionDays=14
--set controlplane.spec.events.cleanupInterval=86400
--set controlplane.spec.events.captureIpAddress=true

Complete Values File Reference

For the complete list of all configurable properties, refer to the values.yaml file in the Helm chart repotsitory.

Get Values Configuration File

wget -q -O - "https://raw.githubusercontent.com/Datasance/helm/refs/heads/main/charts/pot/values.yaml" > pot-operator-values.yaml

The values file structure includes:

Global Configuration

nameOverride: "iofog-operator"
fullnameOverride: "iofog-operator"
imagePullSecrets: []

CRD and RBAC

crds:
install: true

rbac:
create: true

Operator Configuration

operator:
replicaCount: 1
image: ghcr.io/datasance/operator:3.5.4
imagePullPolicy: Always
serviceAccount:
create: true
name: "iofog-operator"
resources: {}
nodeSelector: {}
tolerations: []
affinity: {}
extraEnv: []
extraArgs: []

ControlPlane Configuration

controlplane:
create: true
name: pot
namespace: ""
annotations: {}
labels: {}
spec:
replicas:
controller: 1
# database:
# provider: postgres
# user: ""
# host: ""
# port: 5432
# password: ""
# databaseName: ""
# ssl: false
# ca: ""
auth:
# REQUIRED: set all auth fields (Keycloak / OpenID Connect Client identity)
url: ""
realm: ""
realmKey: ""
ssl: ""
controllerClient: ""
controllerSecret: ""
viewerClient: ""
events:
auditEnabled: true
retentionDays: 14
cleanupInterval: 86400
captureIpAddress: true
images:
# pullSecret: ""
controller: "ghcr.io/datasance/controller:3.5.11"
routerAdaptor: "ghcr.io/datasance/router-adaptor:3.5.2"
router: "ghcr.io/datasance/router:3.5.2"
services:
controller:
type: LoadBalancer
# address: ""
# annotations: {}
router:
type: LoadBalancer
# address: ""
# annotations: {}
controller:
# pidBaseDir: ""
# ecnViewerPort: 0
# ecnViewerUrl: ""
https: false
# secretName: ""
logLevel: "info"
# ingresses:
# controller:
# annotations: {}
# ingressClassName: ""
# host: ""
# secretName: ""
# router:
# address: ""
# messagePort: 5671
# interiorPort: 55671
# edgePort: 45671

See the complete values.yaml file for all available options and their default values.

Upgrade

To upgrade an existing installation:

helm upgrade pot-operator datasance/pot -n pot -f myvalues.yaml

Uninstall

To uninstall the PoT Control Plane:

helm uninstall pot-operator -n pot

Note: CRDs remain by default after uninstallation. Remove them manually if desired:

kubectl delete crd controlplanes.datasance.com

Connection to Installed Control Plane

Once the installation is complete, you can connect to the Controller using potctl. Make sure the --namespace matches the one used during helm install:

Connect to Installed Control Plane as a KubernetesControlPlane

potctl create namespace pot
potctl connect --email foo.bar@example.com --kube ~/.kube/config --namespace pot

Connect to Installed Control Plane as a RemoteControlPlane

potctl create namespace pot
potctl connect --email foo.bar@example.com --name pot --ecn-addr <http://controller-endpoint:51121> -n pot

You will need to authenticate using your Keycloak credentials configured during installation.

Where to go from here?

Having our Control Plane up and running, we can now go to Setup Agents guide to deploy our Agents and finalize the ECN deployment.

Group 3See anything wrong with the document? Help us improve it!