Annotated production-ready values.yaml reference for deploying Midaz on Kubernetes with Helm.
This page provides a complete, annotated values.yaml reference optimized for production deployments. Copy it, adapt the placeholders to your environment, and deploy.
This is a reference configuration. You must replace all placeholder values (marked with {...}) with your actual infrastructure details before deploying.
The ACCOUNT_TYPE_VALIDATION and TRANSACTION_ROUTE_VALIDATION environment variables have been deprecated and replaced by the Ledger Settings API. Use PATCH /v1/organizations/{org_id}/ledgers/{ledger_id}/settings to configure accounting validation per ledger.
# =============================================================================# Midaz Production Values Reference# =============================================================================# This file configures Midaz for a production Kubernetes environment with:# - Unified Ledger service (recommended over legacy onboarding/transaction)# - External databases (PostgreSQL, MongoDB, RabbitMQ, Valkey/Redis)# - Ingress with TLS# - Observability enabled# - CRM plugin enabled# - High availability with autoscaling# =============================================================================# -- Global name overridesnameOverride: "midaz"fullnameOverride: ""namespaceOverride: "midaz"# =============================================================================# GLOBAL: External database bootstrap jobs# =============================================================================# These jobs run once on install to create databases, users, and permissions.# Enable them when using external (non-bundled) databases.global: # -- Bootstrap job for external PostgreSQL externalPostgresDefinitions: enabled: true connection: host: "{your-postgres-host}" # e.g., "prod-postgres.example.com" port: "5432" postgresAdminLogin: # Recommended: use an existing Kubernetes Secret useExistingSecret: name: "{your-postgres-admin-secret}" # Must contain DB_USER_ADMIN and DB_ADMIN_PASSWORD keys # Alternative: inline credentials (NOT recommended for production) # username: "postgres" # password: "{your-admin-password}" midazCredentials: useExistingSecret: name: "{your-midaz-credentials-secret}" # Must contain DB_PASSWORD_MIDAZ key # Alternative: inline # password: "{your-midaz-password}" # -- Bootstrap job for external RabbitMQ externalRabbitmqDefinitions: enabled: true connection: protocol: "https" # Use "https" for production host: "{your-rabbitmq-host}" # e.g., "prod-rabbitmq.example.com" port: "15672" # HTTP management port portAmqp: "5672" # AMQP port rabbitmqAdminLogin: useExistingSecret: name: "{your-rabbitmq-admin-secret}" # Must contain RABBITMQ_ADMIN_USER and RABBITMQ_ADMIN_PASS appCredentials: useExistingSecret: name: "{your-rabbitmq-app-credentials}" # Must contain RABBITMQ_DEFAULT_PASS and RABBITMQ_CONSUMER_PASS# =============================================================================# LEDGER: Unified service (recommended for new installations)# =============================================================================# The Ledger service combines onboarding and transaction into a single# deployment. This is the recommended approach for all new installations.ledger: enabled: true # -- High availability: start with 3 replicas replicaCount: 3 image: repository: lerianstudio/midaz-ledger pullPolicy: IfNotPresent tag: "" # Defaults to Chart.AppVersion; pin a specific version for production # -- Security context (non-root, read-only filesystem) securityContext: runAsGroup: 1000 runAsUser: 1000 runAsNonRoot: true capabilities: drop: - ALL readOnlyRootFilesystem: true # -- PodDisruptionBudget: ensure at least 2 pods during disruptions pdb: enabled: true minAvailable: 2 maxUnavailable: 1 # -- Rolling update with zero downtime deploymentUpdate: type: RollingUpdate maxSurge: 1 maxUnavailable: 0 service: type: ClusterIP port: 3002 # -- Ingress with TLS ingress: enabled: true className: "{your-ingress-class}" # e.g., "nginx", "alb", "traefik" annotations: # NGINX example: nginx.ingress.kubernetes.io/proxy-body-size: "10m" nginx.ingress.kubernetes.io/proxy-read-timeout: "60" # AWS ALB example (uncomment if using ALB): # alb.ingress.kubernetes.io/scheme: internal # alb.ingress.kubernetes.io/target-type: ip # alb.ingress.kubernetes.io/group.name: "midaz" hosts: - host: "{your-midaz-api-domain}" # e.g., "api.midaz.example.com" paths: - path: / pathType: Prefix tls: - secretName: "{your-tls-secret}" # e.g., "midaz-api-tls" hosts: - "{your-midaz-api-domain}" # -- Resource limits for production # Adjust based on your workload. These are starting recommendations. resources: requests: cpu: "1000m" memory: "512Mi" limits: cpu: "2000m" memory: "2Gi" # -- Autoscaling autoscaling: enabled: true minReplicas: 3 maxReplicas: 10 targetCPUUtilizationPercentage: 70 targetMemoryUtilizationPercentage: 80 # -- Pod anti-affinity: spread across nodes for high availability affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchExpressions: - key: app.kubernetes.io/name operator: In values: - ledger topologyKey: kubernetes.io/hostname # -- External database configuration configmap: ENABLE_TELEMETRY: "true" # Auth Plugin (enable if using access management) PLUGIN_AUTH_ENABLED: "false" PLUGIN_AUTH_HOST: "" # Accounting Configuration # Managed via Ledger Settings API — see PATCH /v1/organizations/{org_id}/ledgers/{ledger_id}/settings # Request body: {"accounting": {"validateRoutes": true, "validateAccountType": true}} # -- PostgreSQL: Onboarding module DB_ONBOARDING_HOST: "{your-postgres-host}" DB_ONBOARDING_USER: "midaz" DB_ONBOARDING_NAME: "onboarding" DB_ONBOARDING_PORT: "5432" DB_ONBOARDING_REPLICA_HOST: "{your-postgres-replica-host}" DB_ONBOARDING_REPLICA_USER: "midaz" DB_ONBOARDING_REPLICA_NAME: "onboarding" DB_ONBOARDING_REPLICA_PORT: "5432" # -- MongoDB: Onboarding module MONGO_ONBOARDING_URI: "mongodb" MONGO_ONBOARDING_HOST: "{your-mongodb-host}" MONGO_ONBOARDING_NAME: "onboarding" MONGO_ONBOARDING_USER: "midaz" MONGO_ONBOARDING_PORT: "27017" # -- PostgreSQL: Transaction module DB_TRANSACTION_HOST: "{your-postgres-host}" DB_TRANSACTION_USER: "midaz" DB_TRANSACTION_NAME: "transaction" DB_TRANSACTION_PORT: "5432" DB_TRANSACTION_REPLICA_HOST: "{your-postgres-replica-host}" DB_TRANSACTION_REPLICA_USER: "midaz" DB_TRANSACTION_REPLICA_NAME: "transaction" DB_TRANSACTION_REPLICA_PORT: "5432" # -- MongoDB: Transaction module MONGO_TRANSACTION_URI: "mongodb" MONGO_TRANSACTION_HOST: "{your-mongodb-host}" MONGO_TRANSACTION_NAME: "transaction" MONGO_TRANSACTION_USER: "midaz" MONGO_TRANSACTION_PORT: "27017" # -- Redis/Valkey REDIS_HOST: "{your-redis-host}:6379" # -- RabbitMQ RABBITMQ_URI: "amqps" # Use "amqps" for TLS, "amqp" without RABBITMQ_HOST: "{your-rabbitmq-host}" RABBITMQ_PORT_HOST: "5672" RABBITMQ_PORT_AMQP: "15672" RABBITMQ_DEFAULT_USER: "transaction" RABBITMQ_CONSUMER_USER: "consumer" RABBITMQ_TRANSACTION_ASYNC: "false" # -- Audit AUDIT_LOG_ENABLED: "true" # Enable audit logging for production # -- Balance Sync Worker BALANCE_SYNC_BATCH_SIZE: "100" BALANCE_SYNC_FLUSH_TIMEOUT_MS: "1000" BALANCE_SYNC_POLL_INTERVAL_MS: "500" # -- Use existing Kubernetes Secrets (recommended) useExistingSecret: true existingSecretName: "midaz-ledger" # Create this secret manually before deploying: # kubectl create secret generic midaz-ledger \ # --from-literal=DB_ONBOARDING_PASSWORD='{password}' \ # --from-literal=DB_ONBOARDING_REPLICA_PASSWORD='{password}' \ # --from-literal=MONGO_ONBOARDING_PASSWORD='{password}' \ # --from-literal=DB_TRANSACTION_PASSWORD='{password}' \ # --from-literal=DB_TRANSACTION_REPLICA_PASSWORD='{password}' \ # --from-literal=MONGO_TRANSACTION_PASSWORD='{password}' \ # --from-literal=REDIS_PASSWORD='{password}' \ # --from-literal=RABBITMQ_DEFAULT_PASS='{password}' \ # --from-literal=RABBITMQ_CONSUMER_PASS='{password}' \ # -n midaz serviceAccount: create: true annotations: {}# =============================================================================# LEGACY SERVICES: Disabled when using Ledger# =============================================================================onboarding: enabled: falsetransaction: enabled: false# =============================================================================# CRM: Customer Relationship Management# =============================================================================crm: enabled: true replicaCount: 2 image: repository: lerianstudio/midaz-crm pullPolicy: IfNotPresent tag: "" # Defaults to Chart.AppVersion securityContext: runAsGroup: 1000 runAsUser: 1000 runAsNonRoot: true capabilities: drop: - ALL readOnlyRootFilesystem: true pdb: enabled: true minAvailable: 1 maxUnavailable: 1 service: type: ClusterIP port: 4003 ingress: enabled: true className: "{your-ingress-class}" hosts: - host: "{your-crm-api-domain}" # e.g., "crm.midaz.example.com" paths: - path: / pathType: Prefix tls: - secretName: "{your-crm-tls-secret}" hosts: - "{your-crm-api-domain}" resources: requests: cpu: "200m" memory: "256Mi" limits: cpu: "500m" memory: "512Mi" autoscaling: enabled: true minReplicas: 2 maxReplicas: 5 targetCPUUtilizationPercentage: 80 targetMemoryUtilizationPercentage: 80 configmap: ENV_NAME: "production" PLUGIN_AUTH_ENABLED: "false" PLUGIN_AUTH_ADDRESS: "" MONGO_HOST: "{your-mongodb-host}" MONGO_NAME: "crm" MONGO_PORT: "27017" MONGO_USER: "midaz" useExistingSecret: true existingSecretName: "midaz-crm" # Create this secret manually before deploying: # kubectl create secret generic midaz-crm \ # --from-literal=LCRYPTO_HASH_SECRET_KEY='{generate-a-random-64-hex-string}' \ # --from-literal=LCRYPTO_ENCRYPT_SECRET_KEY='{generate-a-random-64-hex-string}' \ # --from-literal=MONGO_PASSWORD='{password}' \ # -n midaz# =============================================================================# BUNDLED DEPENDENCIES: All disabled (using external databases)# =============================================================================# In production, use managed database services (AWS RDS, Atlas, etc.)# instead of bundled containers.postgresql: enabled: falsemongodb: enabled: falserabbitmq: enabled: falsevalkey: enabled: false# =============================================================================# OBSERVABILITY# =============================================================================grafana: enabled: true name: grafana ingress: enabled: true className: "{your-ingress-class}" annotations: {} hosts: - host: "{your-grafana-domain}" # e.g., "grafana.midaz.example.com" paths: - path: / pathType: Prefix tls: - secretName: "{your-grafana-tls-secret}" hosts: - "{your-grafana-domain}"# -- OpenTelemetry Collector (send telemetry to Lerian)otel-collector-lerian: enabled: true external: false opentelemetry-collector: config: processors: resource/add_client_id: attributes: - key: client.id value: "{your-company-name}" # Your company name for telemetry identification action: upsert extraEnvs: - name: OTEL_API_KEY valueFrom: secretKeyRef: name: otel-api-key key: api-key # Create this secret: # kubectl create secret generic otel-api-key \ # --from-literal=api-key='{your-otel-api-key}' \ # -n midaz exporters: otlphttp/server: endpoint: "https://telemetry.lerian.io:443" headers: x-api-key: "${OTEL_API_KEY}"
The unified ledger service is the recommended approach for all new installations. It combines both modules into a single deployment, reducing operational overhead:
Why use Kubernetes Secrets instead of inline passwords?
Inline passwords in values.yaml are visible in Helm release history and may be committed to version control. Using useExistingSecret: true with pre-created Kubernetes Secrets: