Skip to main content
Version: V2-Next

Component Configuration

How to create and configure components for deployment in Civitas.

Creating/Updating components

Create a new component

make new-component

Update existing components to the latest template versions

make update-components

Folder Structure

A component includes:

components/<component>/
├── civitas-component.yaml # Component definition
├── charts.yaml # Helm chart sources and versions
├── default-environment.yaml.gotmpl # Calues, which can/should be set per environment
├── helmfile.yaml.gotmpl # Helmfile (auto-generated, usually no changes needed)
├── images.yaml # Container image definitions
├── values/ # Helm values per component part
│ ├── <part> # e.g., app, ui, worker
│ │ ├── base-values.yaml.gotmpl # Helm Values common to all environments
│ │ ├── development-values.yaml.gotmpl # Development-specific overrides
│ │ └── production-values.yaml.gotmpl # Production-specific overrides
│ └── ...
├── charts/ # Custom Helm charts (optional)
├── databases.yaml # Database configuration (optional)
├── secrets.yaml # Secret generation config (optional)
└── README.md # Component documentation

Configuring values

We work with Helm charts and therefore must primarily configure the components via Helm values. These values are set components/<component>/values/<part>/<profile>-values.yaml.gotmpl files.

Using Defaults

Some value settings are used in multiple components and have default values defined. These defaults can be found in the defaults/environments/.yaml.gotmpl files. For example for security there is security.yaml.gotmpl with securityDefaults object. You can access these defaults in your component values files like this:

securityContext:
{{ .Values.securityDefaults.securityContext | toYaml | nindent 2 }}

podSecurityContext:
{{ .Values.securityDefaults.podSecurityContext | toYaml | nindent 2 }}

Connect with Keycloak (OIDC/OAuth2)

You can configure other components to connect to Keycloak by constructing the Keycloak URL based on the configured subdomain and path prefix.

{{- $keycloakHost := printf "%s.%s" (default "" .Values.keycloak.app.subdomain) $global.domain | trimPrefix "." }}
{{- $keycloakPath := .Values.keycloak.app.pathPrefix -}}
{{- $keycloakUrl := printf "https://%s%s" $keycloakHost $keycloakPath -}}
{{- $realmName := $global.instanceSlug }}
authServerUrl: "{{ $keycloakUrl }}realms/{{ $realmName }}"

Registering a Keycloak Client

To register a Keycloak client for a component, create a keycloak-clients.yaml file at the component root (components/<my-component>/keycloak-clients.yaml). The Keycloak config job picks it up automatically.

Each top-level key is a Keycloak client ID. Any reference to this client elsewhere in the configuration — secrets, APISIX routes, etc. — must use the same value. At minimum, provide name, subdomain, and redirectPath:

# components/<my-component>/keycloak-clients.yaml
my-client:
name: My Component
description: My component's Keycloak client
subdomain: my-component
redirectPath: /callback
Client Roles

You can optionally define client roles alongside the client configuration. Client roles represent application-specific roles (e.g. admin, viewer) that are scoped to this client. Keycloak includes them in the token when a user authenticates against the client, and the application can then use those role claims to make authorization decisions.

Add a roles key to the client entry:

# components/<my-component>/keycloak-clients.yaml
my-client:
name: My Component
description: My component's Keycloak client
subdomain: my-component
redirectPath: /callback
roles:
- name: admin
description: Full administrative access
- name: viewer
description: Read-only access

The roles list is passed through verbatim as Keycloak client role definitions. Each entry must at minimum have a name field.

note

Roles are created during the Keycloak config job run. If you rename or remove a role, the old role is not automatically deleted from an existing Keycloak client — handle that manually if needed.

Connecting to Kafka Cluster

bootstrapServers: "{{ .Values.kafka.cluster.bootstrapService }}:{{ .Values.kafka.cluster.bootstrapPort }}"
warning

Currently, there is no standard way to configure Kafka authentication and TLS settings.

Connecting to Database

Create a file in components/<component>/databases.yaml with the following content:

keycloak:
name: 'keycloak'
embedded: true # set to false, if an external database is used
user: 'keycloak'
secret:
name: 'db-keycloak'
key: 'password'
generate: true # indicates that this value should be generated
host: 'postgres-cluster-rw' # set to external hostname, if an external database is used
port: 5432
warning

Currently multi namespaces do not yet work. Namespace of the cluster is not known, when rendering this.

You can access the credentials and connection details via the .Values.databases.<component> object like this:

database:
vendor: postgres
hostname: {{ .Values.databases.keycloak.host }}
port: {{ .Values.databases.keycloak.port }}
database: {{ .Values.databases.keycloak.name }}
username: {{ .Values.databases.keycloak.user }}
existingSecret: {{ .Values.databases.keycloak.secret.name }}
existingSecretKey: "password"

Setting Docker Images

To adjust/set where a docker image is pulled from and which version is used, create a file in components/<component>/images.yaml with content like this:

keycloak:
app:
repository: 'quay.io/keycloak/keycloak'
tag: '26.4.0'
configCli:
repository: 'docker.io/adorsys/keycloak-config-cli'
tag: '6.4.0-26'

You can access these values via the .Values.images.<component>.<imageKey> object like this:

image:
repository: {{ .Values.images.keycloak.app.repository }}
tag: {{ .Values.images.keycloak.app.tag }}

Generating Secrets

For generating and using secrets in a component, create a file in components/<component>/secrets.yaml with content like this:

---
keycloak:
app:
keycloak-admin-user: # name of the secret in kubernetes
password: # key in the secret
length: 16
generate: true # indicates that this value should be generated
warning

Currently, you have to ensure that the secret name and key match what the component expects or is set in the values files.

Exposing UIs and APIs

In the components/<component>/default-environment.yaml.gotmpl file add two new values under the part which is exposed:

kafka:
ui:
enabled: true
namespace: {{ include "civitas.namespace" (dict "global" .Values.global "suffix" "kafka") }}
# subdomain to use for accessing the UI. Can be null/empty to use the base domain with path
# pathPrefix is expected to start and end with /
subdomain: kafka-ui
pathPrefix: /

You can access these values via the .Values.<component>.<part> object like this:

ingress:
enabled: {{ $global.ingress.enabled }}
annotations:
cert-manager.io/cluster-issuer: {{ $global.ingress.clusterIssuer }}
{{- $host := printf "%s.%s" (default "" $this.subdomain) $global.domain | trimPrefix "." }}
host: {{ $host }}
path: '{{ $this.pathPrefix }}'
ingressClassName: {{ $global.ingress.ingressClass }}

Configuring Resources

For now: Set resource requests and limits directly in the <part>-values.yaml.gotmpl file of the component with sensible defaults. Defaults should be appropriate for a development and test environment and not much more.

Creating custom Helm charts

When creating a helm chart ensure that all deployment requirements can be fulfilled either by setting directly or via values. The helm chart should be opinionated, since only we use it in this specific context. It is important to follow standards across this project and helm charts in general how which values are set if possible. This way we can define global defaults and use them across multiple components.

The following (incomplete) list shows some of the values which should be supported in the helm chart:

  • In general
    • labels/annotations
  • Deployment/StatefulSet
    • resource requests/limits
    • securityContext/podSecurityContext
    • liveness/readiness probes (can be set directly)
    • image repository/tag/pullPolicy
    • rollingUpdate
    • replicas
    • podDisruptionBudget
    • autoscaling
    • importing self-signed TLS certificates (if applicable)
  • Service
    • type/port named (can be set directly)
  • ServiceAccount
    • create/name/annotations
  • Ingress
    • enabled
    • host/path
    • ingressClassName/annotations
    • tls

Setting other values

Here some guidelines which should help setting other values:

  • Prefer sensible defaults directly in the <part>-values.yaml.gotmpl file over setting many values in the default-environment.yaml.gotmpl These values can be overridden in the environment via <component>.<part>.rawValues if needed. We want to avoid too many values being set in the environment files to keep them clean and easy to read.
  • Security relevant values must be secure by default. E.g. if TLS can be enabled/disabled, it must be enabled by default.
  • Use the global values for settings which are relevant for multiple components.