This repository contains a Helm chart for deploying an Eclipse BaSyx Go based environment on Kubernetes.
The chart installs the BaSyx Go backend services, a PostgreSQL database, optional Keycloak-based authentication, optional ABAC authorization, ingress resources, certificates, the AAS Web UI and optional supporting runtime tests.
The repository follows the common Helm multi-chart layout:
charts/basyx/ Helm chart for BaSyx Go
values/ Custom values examples and deployment overlays
The main chart is located at charts/basyx. All commands below are written from the repository root.
The basyx chart can deploy these components:
| Component | Purpose |
|---|---|
keycloak |
Identity provider for the Web UI and secured BaSyx services |
aasDiscovery |
AAS discovery service |
aasRegistry |
AAS registry service |
aasRepository |
AAS repository service |
submodelRegistry |
Submodel registry service |
submodelRepository |
Submodel repository service |
cdRepository |
Concept description repository |
companyLookup |
Company endpoint directory for dataspace participants |
digitalTwinRegistry |
Digital twin registry |
aasWebGui |
Web UI for browsing and uploading AAS data |
database |
PostgreSQL cluster managed by CloudNativePG |
configurationService |
One-shot BaSyx Go job that initializes and migrates the PostgreSQL schema |
A deployment is one Helm release, usually named basyx, installed into one Kubernetes namespace.
The default chart values live in:
charts/basyx/values.yaml
Custom values files live outside the chart, for example:
values/values.example.yaml
values/values.secured.example.yaml
A custom values file usually defines the public host, enabled services, image tags, TLS settings, and optional security settings such as Keycloak users or ABAC rules.
You need:
- A Kubernetes cluster and a working
kubectlcontext - Helm 3
- An ingress controller, usually nginx ingress
- cert-manager, because the chart renders
cert-manager.io/v1resources - CloudNativePG, because the chart renders
postgresql.cnpg.io/v1database clusters - Optional:
helm-unittestfor local chart tests
Check the current cluster context before installing:
kubectl config current-context
kubectl get nodesIf you work with multiple clusters, pass the context explicitly:
--kube-context custom-rkeInstall CloudNativePG if it is not already installed:
helm repo add cnpg https://cloudnative-pg.github.io/charts
helm repo update
helm upgrade --install cnpg cnpg/cloudnative-pg \
--namespace cnpg-system \
--create-namespaceInstall cert-manager if it is not already installed:
helm repo add jetstack https://charts.jetstack.io --force-update
helm repo update
helm upgrade --install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.19.3 \
--set crds.enabled=trueVerify the required CRDs are available:
kubectl api-resources | grep cert-manager.io
kubectl api-resources | grep postgresql.cnpg.ioStart by copying one of the provided example values files:
# Unsecured deployment without Keycloak and ABAC.
cp values/values.example.yaml values/values.my-environment.yaml
# Secured deployment with Keycloak and ABAC.
cp values/values.secured.example.yaml values/values.my-secured-environment.yamlThe unsecured example enables the core BaSyx Go services and the Web UI:
instanceName: example
host: basyx.example.com
tls:
enabled: true
hosts:
- basyx.example.com
ingress:
issuer: internal-issuer
internal:
certificateIssuer:
name: internal-issuer
autocreateCa: true
autocreateCaSecretName: internal-issuer-ca
keycloak:
enabled: false
aasDiscovery:
enabled: true
aasRegistry:
enabled: true
aasRepository:
enabled: true
submodelRegistry:
enabled: true
submodelRepository:
enabled: true
cdRepository:
enabled: true
companyLookup:
enabled: false
aasWebGui:
enabled: true
infrastructureConfig:
infrastructures:
default: main
main:
security:
type: None
abac:
enabled: falseThe aasWebGui.infrastructureConfig...security.type: None override is intentional for unsecured deployments. Without it, the Web UI would inherit the chart's secured default configuration.
Use values/values.secured.example.yaml when you want authentication and authorization enabled from the start. It enables Keycloak, initializes an example admin user and enables ABAC with the chart default rule that grants full access to users with token claim role=admin.
Do not publish production passwords or client secrets. For public examples, use placeholders and inject real credentials through your deployment pipeline or an external secret management solution.
Always render the chart before the first install. This catches schema errors and missing CRDs early:
helm lint charts/basyx -f values/values.example.yaml
helm lint charts/basyx -f values/values.secured.example.yaml
helm template basyx charts/basyx \
-n basyx-custom \
-f values/values.example.yamlIf you use chart-local custom certificates, render from the repository root so the chart can read files under charts/basyx/config-files/.
Install the release:
helm upgrade --install basyx charts/basyx \
--kube-context custom-rke \
-n basyx-custom \
--create-namespace \
-f values/values.example.yamlIf you are already on the correct Kubernetes context, --kube-context is optional:
helm upgrade --install basyx charts/basyx \
-n basyx-custom \
--create-namespace \
-f values/values.example.yamlCheck the Helm release:
helm --kube-context custom-rke status basyx -n basyx-custom
helm --kube-context custom-rke history basyx -n basyx-customCheck Kubernetes resources:
kubectl --context custom-rke get pods,svc,ingress \
-n basyx-customWait for a service rollout:
kubectl --context custom-rke rollout status \
deployment/basyx-aas-registry \
-n basyx-customCheck logs:
kubectl --context custom-rke logs \
-n basyx-custom \
deploy/basyx-aas-registry \
-c aas-registryRun runtime Helm tests:
helm --kube-context custom-rke test basyx \
-n basyx-custom \
--logsWith the default paths, services are exposed below one host:
| Service | URL pattern |
|---|---|
| AAS Web UI | https://<host>/aas-gui/ |
| Keycloak | https://<host>/identity-management |
| AAS Discovery | https://<host>/aas-discovery |
| AAS Registry | https://<host>/aas-registry |
| AAS Repository | https://<host>/aas-repository |
| Submodel Registry | https://<host>/submodel-registry |
| Submodel Repository | https://<host>/submodel-repo or your custom override |
| Concept Description Repository | https://<host>/cd-repository |
| Company Lookup | https://<host>/company-lookup/companies |
Company Lookup intentionally has no resource at the bare /company-lookup path. Use /company-lookup/companies, /company-lookup/description, /company-lookup/swagger or /company-lookup/health.
Change the custom values and run:
helm upgrade basyx charts/basyx \
--kube-context custom-rke \
-n basyx-custom \
-f values/values.example.yamlFor safer upgrades, render first and optionally use the Helm diff plugin:
helm diff upgrade basyx charts/basyx \
--kube-context custom-rke \
-n basyx-custom \
-f values/values.example.yamlUninstall the Helm release:
helm uninstall basyx \
--kube-context custom-rke \
-n basyx-customCloudNativePG database PVCs and manually created secrets may need separate cleanup, depending on your cluster retention policy.
| Value | Description |
|---|---|
instanceName |
Logical deployment name. Useful for templated certificate paths and UI labels. |
host |
Public DNS host used by ingress, Keycloak issuer URLs and Web UI URLs. |
nameOverride |
Overrides the chart name used in generated resource names. |
fullnameOverride |
Overrides the generated release name. |
paths.* |
Public URL paths for the services. All paths should start with /. |
environment.common.* |
Shared environment variables loaded by BaSyx backend services. |
| Value | Description |
|---|---|
tls.enabled |
Enables TLS-related mounts and ingress TLS rendering. |
tls.hosts |
Hosts included in rendered TLS resources. |
ingress.issuer |
Existing namespaced cert-manager issuer for ingress certificates. |
ingress.clusterIssuer |
Existing cluster issuer for ingress certificates. |
internal.certificateIssuer.autocreateCa |
Creates an internal self-signed CA and issuer. |
internal.certificateIssuer.name |
Internal issuer name used by generated certificates. |
The chart sets spec.privateKey.rotationPolicy: Always on the generated CA certificate to avoid cert-manager v1.18+ default-change warnings.
BaSyx services sometimes need to call HTTPS endpoints that use private CAs. Add those CAs with internal.CACertificates.trustStore.
Inline certificate bundle:
internal:
CACertificates:
trustStore:
additionalCACertificates: |-
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----Chart-local certificate directory:
instanceName: custom
internal:
CACertificates:
trustStore:
chartFileDirectory: /config-files/certs/{{ .Values.instanceName }}Expected directory inside the chart:
charts/basyx/config-files/certs/custom/
partner-root-ca.crt
external-service-ca.crt
The chart projects configured certificate sources into the pods and updates SSL_CERT_DIR automatically.
The chart creates a CloudNativePG cluster:
database:
clusterName: basyx-database
database: basyx
owner: basyx
instances: 3
storage:
size: 10GiFor smaller development deployments, reduce the number of database instances and storage size:
database:
instances: 1
storage:
size: 5GiCurrent BaSyx Go snapshots require the database schema to be prepared before DB-backed services start. The chart enables configurationService by default for this. It renders a Kubernetes Job using eclipsebasyx/basyxconfigurationservice-go and the same CloudNativePG application secret as the runtime services.
The Configuration Service image is versioned independently from the BaSyx runtime service images. Set configurationService.image.tag or, preferably for reproducible deployments, configurationService.image.digest explicitly when a schema migration image changes.
The default job runs as a Helm hook:
configurationService:
enabled: true
image:
tag: SNAPSHOT
waitForDatabase:
enabled: true
hook:
enabled: true
events:
- post-install
- pre-upgradepre-upgrade runs schema migrations before updated runtime pods are rolled out. post-install is used for fresh installs because the PostgreSQL cluster is created by the same chart and must exist before the job can connect.
On fresh installs, CloudNativePG may need some time before the database accepts connections. The chart therefore adds a wait-for-database init container that polls PostgreSQL with pg_isready before starting the Configuration Service. This avoids slow Kubernetes Job backoff loops when the database is simply not ready yet.
After deployment, verify the job and logs with:
kubectl -n basyx-custom get job basyx-configuration
kubectl -n basyx-custom logs job/basyx-configurationThe successful database state is stored in the basyxsystem table with state=clean.
Keycloak is disabled in the unsecured example and enabled in values/values.secured.example.yaml. When enabling it, configure at least admin and client credentials:
keycloak:
enabled: true
realm: basyx
secrets:
admin:
username: admin
password: change-me
client:
name: basyx-ui
clientPassword: change-meThe chart can also create roles, clients, protocol mappers and users through keycloak.initialization.*.
Each backend service has a similar values structure:
aasRepository:
enabled: true
replicaCount: 1
image:
repository: eclipsebasyx/aasrepository-go
tag: SNAPSHOT
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: "8080"
ingress:
enabled: trueSupported service blocks:
aasDiscoveryaasRegistryaasRepositorysubmodelRegistrysubmodelRepositorycdRepositorycompanyLookupdigitalTwinRegistry
Most service blocks support enabled, replicaCount, image.*, imagePullSecrets, service.*, ingress.*, resources, nodeSelector, tolerations, affinity, podAnnotations, podLabels, podSecurityContext, securityContext, volumes, volumeMounts and optional service-local abac overrides.
Enable the Web UI with:
aasWebGui:
enabled: true
image:
tag: SNAPSHOTThe Web UI infrastructure is rendered from aasWebGui.infrastructureConfig. The defaults derive service URLs from host and paths.*.
Logo files are read from the chart-local config-files/logos directory.
ABAC is controlled globally with:
abac:
enabled: trueThe default rule grants full access to users with token claim role=admin.
You can override rules globally:
abac:
accessRules: |
{
"AllAccessPermissionRules": {
"DEFATTRIBUTES": [],
"DEFOBJECTS": [],
"DEFACLS": [],
"DEFFORMULAS": [],
"rules": []
}
}Or per service:
aasRepository:
abac:
enabled: true
accessRules: |
{ }
trustList: |
[ ]The default trust list is derived from host, paths.keycloak, keycloak.realm and environment.common.OIDC_AUDIENCE.
Network Policies are not included in this chart. For production deployments, restrict east-west traffic between pods by deploying NetworkPolicy resources separately. Your cluster must have a Network Policy controller installed (e.g. Calico, Cilium, or Weave). Standard managed Kubernetes offerings (GKE, EKS, AKS) support this natively.
Recommended rules:
- Allow ingress controller → all BaSyx services (HTTP)
- Allow all BaSyx services → PostgreSQL (port 5432)
- Allow all BaSyx services → Keycloak (port 8080, when enabled)
- Deny all other ingress by default
Example policy restricting ingress to the AAS Registry:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-to-aas-registry
namespace: basyx-custom
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: aas-registry
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
ports:
- port: 8080Install the Helm unittest plugin once:
helm plugin install https://github.com/helm-unittest/helm-unittest --verify=falseRun local chart checks:
helm lint charts/basyx
helm unittest charts/basyxRun lint with custom values:
helm lint charts/basyx -f values/values.example.yaml
helm lint charts/basyx -f values/values.secured.example.yamlRuntime smoke tests after deployment:
helm test basyx -n <namespace> --logsMany BaSyx images are intentionally slim. Prefer ephemeral debug containers:
kubectl -n <namespace> debug -it pod/<pod-name> \
--image=nicolaka/netshoot \
--target=<container-name>| Symptom | What to check |
|---|---|
no matches for kind "Certificate" |
cert-manager CRDs are missing. Install cert-manager with CRDs enabled. |
no matches for kind "Cluster" in version "postgresql.cnpg.io/v1" |
CloudNativePG CRDs are missing. Install CloudNativePG. |
| Ingress returns 404 | Check host, paths.*, ingress class and whether the service itself has a route for that path. |
| Pods cannot verify Keycloak TLS | Check the internal CA secret, custom CA mounts and SSL_CERT_DIR. |
Token verification failed: expected audience ... |
Check Keycloak protocol mappers and environment.common.OIDC_AUDIENCE. |
ABAC(model): NO_MATCH |
Check token claims, ABAC object definitions, route patterns and whether pods rolled after config changes. |
| Custom CA not visible in pod | Run helm test <release> -n <namespace> --logs and inspect /etc/ssl/certs/custom. |
| Upgrade targets the wrong cluster | Pass --kube-context <context> explicitly. |
charts/basyx/ Helm chart
charts/basyx/Chart.yaml Chart metadata
charts/basyx/values.yaml Default chart values
charts/basyx/templates/ Kubernetes templates
charts/basyx/tests/ helm-unittest suites
charts/basyx/config-files/ Chart-local files such as logos and optional certs
values/ Custom values overlays
Before publishing publicly:
- Keep real deployment values, passwords, client secrets and private certificates out of the public repository.
- Provide sanitized example values instead of production overlays.
- Prefer fixed image tags or digests over mutable
SNAPSHOTtags for reproducible deployments. - Review ABAC defaults and document deployment-specific rule sets outside the public chart when needed.
This README follows the deployment-oriented structure of the Eclipse BaSyx Helm chart documentation while adapting it for the BaSyx Go chart and its current dependencies.
- Eclipse BaSyx charts: https://github.com/eclipse-basyx/charts
- Helm documentation: https://helm.sh/docs/
- CloudNativePG: https://cloudnative-pg.io/
- cert-manager: https://cert-manager.io/