Configure Physical Tenants in Helm chart
This page describes Physical Tenants, the strong isolation model for separate teams or organizations within a single orchestration cluster. For the lightweight, tenant-ID based model, see Logical Tenants.
The Helm chart does not expose a dedicated physicalTenants.* values schema. Configure Physical Tenants by passing the same camunda.physical-tenants.<tenant-key>.* properties documented in the configuration reference, either as a raw application.yaml block, as a standalone extra configuration file, or as environment variables.
This page covers delivery: how to get tenant configuration into the Orchestration Cluster pod. Declaring a tenant also changes the shape of your deployment, because each tenant needs its own Optimize release and its own index prefixes, and adding or removing one is an ordered operation across several releases. For that, see configure Physical Tenants across releases.
Prerequisites
- A running Camunda 8 Self-Managed Helm deployment.
- Read the Physical Tenant isolation model and configuration reference first — this page only shows how to deliver that same configuration through Helm.
Configure via orchestration.configuration
Set orchestration.configuration to the full application.yaml content, including the root-level and per-tenant camunda.physical-tenants.* blocks:
orchestration:
configuration: |
camunda:
data:
secondary-storage:
rdbms:
url: jdbc:postgresql://db/default
document:
default-store-id: shared-s3
aws:
shared-s3:
bucket-name: company-docs-bucket
bucket-path: default/
security:
authentication:
method: oidc
providers:
oidc:
corp-idp:
issuer-uri: https://corp-idp.example.com/realms/camunda
client-id: camunda-client
client-secret: ${CORP_IDP_CLIENT_SECRET}
audiences:
- camunda-api
username-claim: preferred_username
physical-tenants:
default:
cluster:
partition-count: 3
document:
default-store-id: shared-s3
assigned:
- shared-s3
security:
authentication:
providers:
assigned:
- corp-idp
riskprod:
cluster:
partition-count: 3
data:
secondary-storage:
rdbms:
url: jdbc:postgresql://db/riskprod
document:
default-store-id: shared-s3
assigned:
- shared-s3
aws:
shared-s3:
bucket-path: riskprod/ # distinct path, no collision with default
security:
authentication:
providers:
assigned:
- corp-idp
initialization:
roles:
- roleId: riskprod-admin
name: Risk Production Admin
mappingRules:
- riskprod-admins-mapping
mappingrules:
- mapping-rule-id: riskprod-admins-mapping
claim-name: groups
claim-value: risk-admins
authorizations:
- ownerType: ROLE
ownerId: riskprod-admin
resourceType: RESOURCE
resourceId: "*"
permissions:
- CREATE
- ownerType: ROLE
ownerId: riskprod-admin
resourceType: PROCESS_DEFINITION
resourceId: "*"
permissions:
- CREATE_PROCESS_INSTANCE
- UPDATE_PROCESS_INSTANCE
- READ_PROCESS_INSTANCE
- READ_PROCESS_DEFINITION
Every explicitly configured tenant needs its own security.initialization block when authorization is enabled; it is not inherited from the root or from other tenants.
This is the same configuration shape as the configuration reference's application.yaml example — orchestration.configuration renders as-is into the pod's application.yaml.
Secrets referenced with ${VARIABLE} syntax (like ${CORP_IDP_CLIENT_SECRET} above) still resolve from the pod's environment. Supply them through orchestration.env or orchestration.envFrom alongside orchestration.configuration.
Configure via orchestration.extraConfiguration
If you'd rather keep the Physical Tenant configuration in its own file instead of folding it into a single orchestration.configuration block, use orchestration.extraConfiguration. Each entry mounts as its own file and, with springImport left at its default (true), is merged into the pod's Spring configuration alongside the base application.yaml:
orchestration:
extraConfiguration:
- file: physical-tenants.yaml
content: |
camunda:
physical-tenants:
default:
cluster:
partition-count: 3
document:
default-store-id: shared-s3
assigned:
- shared-s3
security:
authentication:
providers:
assigned:
- corp-idp
riskprod:
cluster:
partition-count: 3
data:
secondary-storage:
rdbms:
url: jdbc:postgresql://db/riskprod
document:
default-store-id: shared-s3
assigned:
- shared-s3
aws:
shared-s3:
bucket-path: riskprod/ # distinct path, no collision with default
security:
authentication:
providers:
assigned:
- corp-idp
initialization:
roles:
- roleId: riskprod-admin
name: Risk Production Admin
mappingRules:
- riskprod-admins-mapping
mappingrules:
- mapping-rule-id: riskprod-admins-mapping
claim-name: groups
claim-value: risk-admins
authorizations:
- ownerType: ROLE
ownerId: riskprod-admin
resourceType: RESOURCE
resourceId: "*"
permissions:
- CREATE
- ownerType: ROLE
ownerId: riskprod-admin
resourceType: PROCESS_DEFINITION
resourceId: "*"
permissions:
- CREATE_PROCESS_INSTANCE
- UPDATE_PROCESS_INSTANCE
- READ_PROCESS_INSTANCE
- READ_PROCESS_DEFINITION
Every explicitly configured tenant needs its own security.initialization block when authorization is enabled; it is not inherited from the root or from other tenants.
This still requires the base camunda.security.authentication and camunda.document configuration (shown in the orchestration.configuration example above) to be set elsewhere — through orchestration.configuration or your own base application.yaml — since extraConfiguration only adds to that configuration, it doesn't replace it.
Configure via environment variables
For a small number of overrides, set individual properties through orchestration.env instead of a full configuration block:
orchestration:
env:
- name: CAMUNDA_PHYSICALTENANTS_RISKPROD_DATA_SECONDARYSTORAGE_RDBMS_URL
value: jdbc:postgresql://db/riskprod
Environment variables and orchestration.configuration can be combined. Use the same normalized tenant key in both. See environment variable mapping for the full conversion rules.