Using Helm

This guide walks you through installing and configuring a Midaz environment for Kubernetes using Helm. You’ll find instructions on setting up Ingress controllers, enabling observability, and managing dependencies.


Before you start


Before deploying Midaz with Helm, make sure you have the following in place:

  • Kubernetes (v1.30+) – You’ll need a running cluster to deploy into.
  • Helm 3+ – Helm must be installed and available. Run helm version to confirm.

Want a deeper understanding of how everything fits together? Head over to our Midaz architecture overview before you dive in.


How to deploy Midaz


To get Midaz up and running with Helm, run:

helm install midaz oci://registry-1.docker.io/lerianstudio/midaz-helm --version <version> -n midaz --create-namespace

This creates a namespace called midaz (if it doesn’t already exist) and deploys the chart.

To confirm the deployment went through:

helm list -n midaz

👍

Helm Chart Source

You’ll find the Helm chart used in this guide in our GitHub repository. Feel free to fork it, tweak values, or extend as needed.


Configuring ingress for different controllers


Midaz supports different ingress controllers for exposing services like Transaction, Ledger, and Console. You’ll need to have a controller set up in your cluster, and configure it in the values.yaml file.

Below are examples for the most common options:

NGINX ingress controller

ingress:
  enabled: true
  className: "nginx"
  annotations: {} 
  hosts:
    - host: midaz.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: midaz-tls
      hosts:
        - midaz.example.com

👍

Tip

Check the ingress-nginx official documentation for Nginx annotations reference.


AWS ALB (Application Load Balancer)

ingress:
  enabled: true
  className: "alb"
  annotations:
    alb.ingress.kubernetes.io/scheme: internal
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/group.name: "midaz"
    alb.ingress.kubernetes.io/healthcheck-path: "/healthz"
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
  hosts:
    - host: midaz.example.com
      paths:
        - path: /
          pathType: Prefix
  tls: []

Traefik Ingress Controller

ingress:
  enabled: true
  className: "traefik"
  annotations:
    traefik.ingress.kubernetes.io/router.entrypoints: "web, websecure"
    traefik.ingress.kubernetes.io/router.tls: "true"
  hosts:
    - host: midaz.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: midaz-tls
      hosts:
        - midaz.example.com

Configuring observability


Midaz uses Grafana Docker OpenTelemetry LGTM to power its observability stack—this setup collects and exports telemetry data such as traces and metrics.

Accessing the Grafana dashboard

To access the dashboard locally:

kubectl port-forward svc/midaz-grafana 3000:3000 -n midaz

Then head to: http://localhost:3000


Internal DNS access for Grafana

To expose Grafana within your cluster or private network via DNS, enable and configure Ingress like this:

grafana:
  enabled: true
  name: grafana

  ingress:
    enabled: true
    className: "nginx"
    annotations:
      nginx.ingress.kubernetes.io/rewrite-target: /
      nginx.ingress.kubernetes.io/whitelist-source-range: ""
    hosts:
      - host: "midaz-ote.example.com"
        paths:
          - path: /
            pathType: Prefix
    tls: []

Disabling observability

You can disable the observability stack entirely by setting:

grafana:
  enabled: false

Configuring dependencies


Midaz comes with default dependencies that are enabled out of the box. You can turn them off if you're using existing infrastructure.

Valkey

  • Version: 2.4.7
  • Repository: Bitnami
  • Disable: valkey.enabled = false

To use your own Redis/Valkey instance:

onboarding:
  configmap:
    REDIS_HOST: { your-host }
    REDIS_PORT: { your-port }
    REDIS_USER: { your-user }
  secrets:
    REDIS_PASSWORD: { your-password }

transaction:
  configmap:
    REDIS_HOST: { your-host }
    REDIS_PORT: { your-port }
    REDIS_USER: { your-user }
  secrets:
    REDIS_PASSWORD: { your-password }

PostgreSQL

  • Version: 16.3.0
  • Repository: Bitnami
  • Disable: postgresql.enabled = false

External PostgreSQL config example:

onboarding:
  configmap:
    DB_HOST: { your-host }
    DB_USER: { your-user }
    DB_PORT: { your-port }
    DB_REPLICA_HOST: { your-replica-host }
    DB_REPLICA_USER: { your-replica-user }
    DB_REPLICA_PORT: { your-replica-port }
  secrets:
    DB_PASSWORD: { your-password }
    DB_REPLICA_PASSWORD: { your-replica-password }

transaction:
  configmap:
    DB_HOST: { your-host }
    DB_USER: { your-user }
    DB_PORT: { your-port }
    DB_REPLICA_HOST: { your-replica-host }
    DB_REPLICA_USER: { your-replica-user }
    DB_REPLICA_PORT: { your-replica-port }
  secrets:
    DB_PASSWORD: { your-password }
    DB_REPLICA_PASSWORD: { your-replica-password }

MongoDB

  • Version: 15.4.5
  • Repository: Bitnami
  • Disable: mongodb.enabled = false

To connect to an external MongoDB:

onboarding:
  configmap:
    MONGO_HOST: { your-host }
    MONGO_NAME: { your-db-name }
    MONGO_USER: { your-user }
    MONGO_PORT: { your-port }
  secrets:
    MONGO_PASSWORD: { your-password }

transaction:
  configmap:
    MONGO_HOST: { your-host }
    MONGO_NAME: { your-db-name }
    MONGO_USER: { your-user }
    MONGO_PORT: { your-port }
  secrets:
    MONGO_PASSWORD: { your-password }

RabbitMQ

  • Version: 16.0.0
  • Repository: Bitnami
  • Disable: rabbitmq.enabled = false

If you're using an external RabbitMQ, remember that you must load the required definitions file. Without these queues, exchanges, and bindings, Midaz won’t function properly.

External config example:

onboarding:
  configmap:
    RABBITMQ_HOST: { your-host }
    RABBITMQ_DEFAULT_USER: { your-user }
    RABBITMQ_PORT_HOST: { your-port }
    RABBITMQ_PORT_AMQP: { your-amqp-port }
  secrets:
    RABBITMQ_DEFAULT_PASS: { your-password }

transaction:
  configmap:
    RABBITMQ_HOST: { your-host }
    RABBITMQ_DEFAULT_USER: { your-user }
    RABBITMQ_PORT_HOST: { your-port }
    RABBITMQ_PORT_AMQP: { your-amqp-port }
  secrets:
    RABBITMQ_DEFAULT_PASS: { your-password }

Midaz components


The Midaz system runs on four distinct layers that work together, distributed in segregated workloads:

Onboarding

ParameterDescriptionDefault Value
onboarding.nameService name."onboarding"
onboarding.replicaCountNumber of replicas for the onboarding service.2
onboarding.image.repositoryRepository for the onboarding service container image."lerianstudio/midaz-onboarding"
onboarding.image.pullPolicyImage pull policy."IfNotPresent"
onboarding.image.tagImage tag used for deployment."2.1.0"
onboarding.imagePullSecretsSecrets for pulling images from a private registry.[]
onboarding.nameOverrideOverrides the default generated name by Helm.""
onboarding.fullnameOverrideOverrides the full name generated by Helm.""
onboarding.podAnnotationsPod annotations for additional metadata.{}
onboarding.podSecurityContextSecurity context applied at the pod level.{}
onboarding.securityContext.runAsGroupDefines the group ID for the user running the process inside the container.1000
onboarding.securityContext.runAsUserDefines the user ID for the process running inside the container.1000
onboarding.securityContext.runAsNonRootEnsures the process does not run as root.true
onboarding.securityContext.capabilities.dropList of capabilities to drop.["ALL"]
onboarding.securityContext.readOnlyRootFilesystemDefines the root filesystem as read-only.true
onboarding.pdb.enabledSpecifies whether PodDisruptionBudget is enabled.true
onboarding.pdb.minAvailableMinimum number of available pods.1
onboarding.pdb.maxUnavailableMaximum number of unavailable pods.1
onboarding.pdb.annotationsAnnotations for the PodDisruptionBudget.{}
onboarding.deploymentUpdate.typeType of deployment strategy."RollingUpdate"
onboarding.deploymentUpdate.maxSurgeMaximum number of pods that can be created over the desired number of pods."100%"
onboarding.deploymentUpdate.maxUnavailableMaximum number of pods that can be unavailable during the update.0
onboarding.service.typeKubernetes service type."ClusterIP"
onboarding.service.portPort for the HTTP API.3000
onboarding.ingress.enabledSpecifies whether Ingress is enabled.false
onboarding.ingress.classNameIngress class name.""
onboarding.ingress.annotationsAdditional ingress annotations.{}
onboarding.ingress.hostsConfigured hosts for Ingress and associated paths.""
onboarding.ingress.tlsTLS configurations for Ingress.[]
onboarding.resources.limits.cpuCPU limit allocated for the pods."1500m"
onboarding.resources.limits.memoryMemory limit allocated for the pods."512Gi"
onboarding.resources.requests.cpuMinimum CPU request for the pods."768m"
onboarding.resources.requests.memoryMinimum memory request for the pods."256Mi"
onboarding.autoscaling.enabledSpecifies whether autoscaling is enabled.true
onboarding.autoscaling.minReplicasMinimum number of replicas for autoscaling.2
onboarding.autoscaling.maxReplicasMaximum number of replicas for autoscaling.5
onboarding.autoscaling.targetCPUUtilizationPercentageTarget CPU utilization percentage for autoscaling.80
onboarding.autoscaling.targetMemoryUtilizationPercentageTarget memory utilization percentage for autoscaling.80
onboarding.nodeSelectorNode selectors for pod scheduling.{}
onboarding.tolerationsTolerations for pod scheduling.{}
onboarding.affinityAffinity rules for pod scheduling.{}
onboarding.configmapAdditional configurations in ConfigMap.Find the default values in the configuration.
onboarding.secretsAdditional secrets for the service.Find the default values in the configuration.
onboarding.serviceAccount.createSpecifies whether the service account should be created.true
onboarding.serviceAccount.annotationsAnnotations for the service account.{}
onboarding.serviceAccount.nameService account name. If not defined, it will be generated automatically.""

Transaction

ParameterDescriptionDefault Value
transaction.nameService name."transaction"
transaction.replicaCountNumber of replicas for the transaction service.1
transaction.image.repositoryRepository for the transaction service container image."lerianstudio/midaz-transaction"
transaction.image.pullPolicyImage pull policy."IfNotPresent"
transaction.image.tagImage tag used for deployment."2.1.0"
transaction.imagePullSecretsSecrets for pulling images from a private registry.[]
transaction.nameOverrideOverrides the default generated name by Helm.""
transaction.fullnameOverrideOverrides the full name generated by Helm.""
transaction.podAnnotationsPod annotations for additional metadata.{}
transaction.podSecurityContextSecurity context for the pod.{}
transaction.securityContext.runAsGroupDefines the group ID for the user running the process inside the container.1000
transaction.securityContext.runAsUserDefines the user ID for the process running inside the container.1000
transaction.securityContext.runAsNonRootEnsures the process does not run as root.true
transaction.securityContext.capabilities.dropList of Linux capabilities to drop.["ALL"]
transaction.securityContext.readOnlyRootFilesystemDefines the root filesystem as read-only.true
transaction.pdb.enabledEnable or disable PodDisruptionBudget.true
transaction.pdb.minAvailableMinimum number of available pods.2
transaction.pdb.maxUnavailableMaximum number of unavailable pods.1
transaction.pdb.annotationsAnnotations for the PodDisruptionBudget.{}
transaction.deploymentUpdate.typeType of deployment strategy."RollingUpdate"
transaction.deploymentUpdate.maxSurgeMaximum number of pods that can be created over the desired number of pods."100%"
transaction.deploymentUpdate.maxUnavailableMaximum number of pods that can be unavailable during the update.0
transaction.service.typeKubernetes service type."ClusterIP"
transaction.service.portPort for the HTTP API.3001
transaction.ingress.enabledEnable or disable ingress.false
transaction.ingress.classNameIngress class name.""
transaction.ingress.annotationsAdditional ingress annotations.{}
transaction.ingress.hostsConfigured hosts for ingress and associated paths.[{host: "", paths: [{path: "/", pathType: "Prefix"}]}]
transaction.ingress.tlsTLS configuration for ingress.[]
transaction.resources.limits.cpuCPU limit allocated for the pods."2000m"
transaction.resources.limits.memoryMemory limit allocated for the pods."512Gi"
transaction.resources.requests.cpuMinimum CPU request for the pods."768m"
transaction.resources.requests.memoryMinimum memory request for the pods."256Mi"
transaction.autoscaling.enabledEnable or disable horizontal pod autoscaling.true
transaction.autoscaling.minReplicasMinimum number of replicas for autoscaling.3
transaction.autoscaling.maxReplicasMaximum number of replicas for autoscaling.9
transaction.autoscaling.targetCPUUtilizationPercentageTarget CPU utilization percentage for autoscaling.70
transaction.autoscaling.targetMemoryUtilizationPercentageTarget memory utilization percentage for autoscaling.80
transaction.nodeSelectorNode selector for scheduling pods on specific nodes.{}
transaction.tolerationsTolerations for scheduling on tainted nodes.{}
transaction.affinityAffinity rules for pod scheduling.{}
transaction.configmapConfigMap for environment variables and configurations.Find the default values in the configuration.
transaction.secretsSecrets for storing sensitive data.Find the default values in the configuration.
transaction.serviceAccount.createSpecifies whether a ServiceAccount should be created.true
transaction.serviceAccount.annotationsAnnotations for the ServiceAccount.{}
transaction.serviceAccount.nameName of the service account.""

Console

ParameterDescriptionDefault Value
console.nameService name."console"
console.enabledEnable or disable the console service.true
console.replicaCountNumber of replicas for the deployment.1
console.image.repositoryDocker image repository for Console."lerianstudio/midaz-console"
console.image.pullPolicyDocker image pull policy."IfNotPresent"
console.image.tagDocker image tag used for deployment."1.25.1"
console.imagePullSecretsSecrets for pulling Docker images from a private registry.[]
console.nameOverrideOverrides the resource name.""
console.fullnameOverrideOverrides the full resource name.""
console.podAnnotationsAnnotations for the pods.{}
console.podSecurityContextSecurity context applied at the pod level.{}
console.securityContext.runAsGroupDefines the group ID for the user running the process inside the container.1000
console.securityContext.runAsUserDefines the user ID for the process running inside the container.1000
console.securityContext.runAsNonRootEnsures the process does not run as root.true
console.securityContext.capabilities.dropList of Linux capabilities to drop.["ALL"]
console.securityContext.readOnlyRootFilesystemDefines the root filesystem as read-only.true
console.pdb.enabledSpecifies whether PodDisruptionBudget is enabled.false
console.pdb.minAvailableMinimum number of available pods for PodDisruptionBudget.1
console.pdb.maxUnavailableMaximum number of unavailable pods for PodDisruptionBudget.1
console.pdb.annotationsAnnotations for the PodDisruptionBudget.{}
console.deploymentUpdate.typeType of deployment strategy."RollingUpdate"
console.deploymentUpdate.maxSurgeMaximum number of pods that can be created over the desired number of pods."100%"
console.deploymentUpdate.maxUnavailableMaximum number of pods that can be unavailable during the update.0
console.service.typeKubernetes service type."ClusterIP"
console.service.portService port.8081
console.ingress.enabledSpecifies whether Ingress is enabled.false
console.ingress.classNameIngress class name.""
console.ingress.annotationsAdditional annotations for Ingress.{}
console.ingress.hostsConfigured hosts for Ingress and associated paths.[{ "host": "", "paths": [{ "path": "/", "pathType": "Prefix" }] }]
console.ingress.tlsTLS configurations for Ingress.[]
console.resources.limits.cpuCPU limit allocated for the pods."200m"
console.resources.limits.memoryMemory limit allocated for the pods."256Mi"
console.resources.requests.cpuMinimum CPU request for the pods."100m"
console.resources.requests.memoryMinimum memory request for the pods."128Mi"
console.autoscaling.enabledSpecifies whether horizontal pod autoscaling is enabled.true
console.autoscaling.minReplicasMinimum number of replicas for autoscaling.1
console.autoscaling.maxReplicasMaximum number of replicas for autoscaling.3
console.autoscaling.targetCPUUtilizationPercentageTarget CPU utilization percentage for autoscaling.80
console.autoscaling.targetMemoryUtilizationPercentageTarget memory utilization percentage for autoscaling.80
console.nodeSelectorNode selectors for pod scheduling.{}
console.tolerationsTolerations for pod scheduling.{}
console.affinityAffinity rules for pod scheduling.{}
console.configmapAdditional configurations in ConfigMap.Find the default values in the configuration.
console.secretsAdditional secrets for the service.{}
console.serviceAccount.createSpecifies whether the service account should be created.true
console.serviceAccount.annotationsAnnotations for the service account.{}
console.serviceAccount.nameService account name. If not defined, it will be generated automatically.""