Skip to content

With helm-managed backends

You can find below 3 recommended deployment sized for your OCTI stack.

The sample are based on the following assumptions :

Warning

Please take time to review all credential values (such as admin password and tokens) to set them with a value of your own. Do not use the current values for sensitive fields as is.

Health Check Key

You can set APP__HEALTH_ACCESS_KEY from a secret (instead of plain values) by wiring envFromSecrets:

opencti:
  envFromSecrets:
    APP__HEALTH_ACCESS_KEY:
      secretName: opencti-config
      key: APP__HEALTH_ACCESS_KEY

Metrics

To enable metrics, set the following values:

opencti:
  env:
    APP__TELEMETRY__METRICS__ENABLED: true
    APP__TELEMETRY__METRICS__EXPORTER_PROMETHEUS: 14269

  worker:
    env:
      WORKER_TELEMETRY_ENABLED: true
      WORKER_PROMETHEUS_TELEMETRY_PORT: 14270
      WORKER_PROMETHEUS_TELEMETRY_HOST: 0.0.0.0

When enabled, the chart exposes a metrics port and adds Prometheus scrape annotations on front and worker services.

Dedicated ingress for Ingests

It is possible to expose ingests through an ingress, for example to allow external access for connectors. To do so, you can set the following values:

Warning

Make sure the host value doesn't conflict with the one used for the front. You can also use a different ingress class if needed by updating the className value.

opencti:
  ingest:
    ingress:
      enabled: true
      className: "nginx"
      hosts:
        - host: opencti-ingest.local
          paths:
            - path: /
              pathType: ImplementationSpecific

Connectors initContainers and volumes

Starting with 1.3.1, it is possible to configure initContainers and volumes for connectors. This can be useful to mount custom certificates or execute specific scripts for example. You also have the possibility to enable and configure the persistence of the connectors data if needed.

Example configuration for a CVE connector with initContainer and volume to mount custom certificates

opencti:
  connector:
    connectors:
      - name: cve
        enabled: true
        initContainers:
          - name: cert-init
            image: alpine:3.23.3
            command: ["sh", "-c"]
            volumeMounts:
              - name: certs
                mountPath: /etc/ssl/certs
              - name: cert-secret
                mountPath: /usr/share/ca-certificates/cert.pem
                subPath: cert.pem
            args:
              - |
                apk --no-cache add --no-check-certificate ca-certificates && update-ca-certificates
        volumes:
          - name: certs
            emptyDir: {}
          - name: cert-secret
            secret:
              defaultMode: 0640
              items:
                - key: cert.pem
                  path: cert.pem
              optional: false
              secretName: my-custom-cert
        volumeMounts:
          - name: certs
            mountPath: /etc/ssl/certs
        image:
          registry: "docker.io"
          repository: "opencti/connector-cve"
        env:
          OPENCTI_TOKEN: "UUID-TOKEN"
          CONNECTOR_TYPE: EXTERNAL_IMPORT
          CONNECTOR_NAME: Common Vulnerabilities and Exposures
          CONNECTOR_SCOPE: identity,vulnerability
          CONNECTOR_RUN_AND_TERMINATE: 'false'
          CONNECTOR_LOG_LEVEL: error
          CVE_BASE_URL: 'https://services.nvd.nist.gov/rest/json/cves'
          CVE_API_KEY: 'YOUR-API-KEY'
          CVE_INTERVAL: 2
          CVE_MAX_DATE_RANGE: 120
          CVE_MAINTAIN_DATA: 'true'
          CVE_PULL_HISTORY: 'false'
          CVE_HISTORY_START_YEAR: 2024

Example configuration for a CVE connector with persistence enabled

Warning

Connectors are not made to scale up with persistence enabled, if you enable persistence, ensure the replica count is set to 1.

opencti:
  connector:
    connectors:
      - name: cve 
        enabled: true
        persistence:
          enabled: true
          storageClassName: "my-storage-class"
          accessMode: ReadWriteOnce
          size: 1Gi
        image:
          registry: "docker.io"
          repository: "opencti/connector-cve"
        env:
          OPENCTI_TOKEN: "UUID-TOKEN"
          CONNECTOR_TYPE: EXTERNAL_IMPORT
          CONNECTOR_NAME: Common Vulnerabilities and Exposures
          CONNECTOR_SCOPE: identity,vulnerability
          CONNECTOR_RUN_AND_TERMINATE: 'false'
          CONNECTOR_LOG_LEVEL: error
          CVE_BASE_URL: 'https://services.nvd.nist.gov/rest/json/cves'
          CVE_API_KEY: 'YOUR-API-KEY'
          CVE_INTERVAL: 2
          CVE_MAX_DATE_RANGE: 120
          CVE_MAINTAIN_DATA: 'true'
          CVE_PULL_HISTORY: 'false'
          CVE_HISTORY_START_YEAR: 2024

S(mall)

Recommended for PoV, dev environments (like Minikube single node cluster)

opencti:
  env:
    # OpenCTI
    APP__ENCRYPTION_KEY: "ChangeMe"
    APP__BASE_URL: "http://opencti.local"
    APP__ADMIN__EMAIL: admin@opencti.io
    APP__ADMIN__PASSWORD: WhatA_Strong-P4ssword*!
    APP__ADMIN__TOKEN: d99208c3-0eca-4c65-9633-42be3b9c6bb8
    APP__HEALTH_ACCESS_KEY: RANDOM_ACCESS_KEY
    # MinIO
    MINIO__ENDPOINT: "minio"
    MINIO__PORT: "80"
    MINIO__BUCKET_NAME: opencti
    MINIO__USE_AWS_ROLE: "false"
    MINIO__USE_SSL: "false"
    # Elasticsearch
    ELASTICSEARCH__URL: "https://es-data-nodes:9200"
    ELASTICSEARCH__NUMBER_OF_REPLICAS: '0'
    ELASTICSEARCH__SSL__REJECT_UNAUTHORIZED: "false"
    ELASTICSEARCH__USERNAME: "elastic"
    # RabbitMQ
    RABBITMQ__HOSTNAME: rabbitmq
    RABBITMQ__PORT: 5672
    RABBITMQ__QUEUE_TYPE: quorum
    RABBITMQ__USE_SSL: "false"
    RABBITMQ__PORT_MANAGEMENT: 15672
    RABBITMQ__MANAGEMENT_SSL: "false"
    RABBITMQ__HOSTNAME_MANAGEMENT: rabbitmq

    # REDIS
    REDIS__TRIMMING: 10000
    REDIS__ACTIVITY_TRIMMING: 50000
    REDIS__NOTIFICATION_TRIMMING: 50000
    REDIS__NAMESPACE: opencti
    REDIS__USE_SSL: "false"

  envFromSecrets:
    ELASTICSEARCH__PASSWORD:
      key: elastic
      secretName: elasticsearch-es-elastic-user
    MINIO__ACCESS_KEY:
      key: accessKey
      secretName:  minio-credentials
    MINIO__SECRET_KEY:
      key: secretKey
      secretName: minio-credentials
    RABBITMQ__USERNAME:
      key: username
      secretName: rabbitmq-default-user
    RABBITMQ__PASSWORD:
      key: password
      secretName: rabbitmq-default-user

  front:
    ingress:
      enabled: true
      className: "nginx"
      hosts:
        - host: opencti.local
          paths:
            - path: /
              pathType: Prefix
    resources:
      limits:
        cpu: "0.5"
        memory: 1024Mi
      requests:
        cpu: "0.25"
        memory: 512Mi
  ingest:
    replicaCount: 1
    resources:
      limits:
        cpu: "0.5"
        memory: 1024Mi
      requests:
        cpu: "0.25"
        memory: 512Mi
  worker:
    env:
      OPENCTI_URL: http://opencti-ingest:80
      OPENCTI_TOKEN: d99208c3-0eca-4c65-9633-42be3b9c6bb8
    replicaCount: 1
    resources:
      limits:
        cpu: "0.5"
        memory: 1024Mi
      requests:
        cpu: "0.5"
        memory: 512Mi

elasticsearch:
  enabled: true
  clusterName: elasticsearch
  disableDowngradeValidation: "true"
  masterNodes:
    replicas: 1
  dataNodes:
    replicas: 1
  allowMmap: false
  enableXpackML: false
  threadPoolSearchQueueSize: 5000
  loggerDiscoveryLevel: ERROR
  storageSize: 20Gi
  dataNodeJavaOpts: -Xms2g -Xmx2g -Xlog:disable -Xlog:all=warning:stderr:utctime,level,tags -Xlog:gc=debug:stderr:utctime
  resources:
    limits:
      cpu: "1"
      memory: 3072Mi
    requests:
      cpu: "1"
      memory: 2048Mi
  service:
    name: es-data-nodes
    port: 9200
    targetPort: 9200
  kibana:
    enabled: true
    name: kibana
    elasticsearchRequestTimeout: 1800000
    serverSocketTimeout: 1800000
    telemetryOptIn: false
    telemetryAllowChangingOptInStatus: false
    ingress:
      enabled: true
    http:
      tls:
        selfSignedCertificate:
          disabled: true

rabbitmq:
  enabled: true
  replicas: 3
  storageSize: 5Gi
  resources:
    limits:
      cpu: "1"
      memory: 1024Mi
    requests:
      cpu: "0.5"
      memory: 256Mi
  ingress:
    enabled: true

redis:
  enabled: true
  mode: standalone
  data:
    storageSize: 4Gi
    resources:
      requests:
        cpu: "0.5"
        memory: 2Gi
      limits:
        memory: 2Gi
minio:
  enabled: true
  standardClass: 0
  standardPool:
    serversCount: 1
    storageSize: 5G
    resources:
      requests:
        cpu: "0.2"
        memory: 256Mi
      limits:
        memory: 1Gi
  certificate:
    requestAutoCert: false
  podManagementPolicy: Parallel
  logging:
    anonymous: true
    json: true
    quiet: true
  ingress:
    enabled: true

M(edium)

Recommended as a standard production deployment.

opencti:
  env:
    # OpenCTI
    APP__ENCRYPTION_KEY: "ChangeMe"
    APP__BASE_URL: "http://opencti:8080"
    APP__ADMIN__EMAIL: admin@opencti.io
    APP__ADMIN__PASSWORD: WhatA_Strong-P4ssword*!
    APP__ADMIN__TOKEN: "d99208c3-0eca-4c65-9633-42be3b9c6bb8"
    APP__HEALTH_ACCESS_KEY: "8b55aac644e9e6f2701805584cc391ff81d3ecec"
    # MinIO
    MINIO__BUCKET_NAME: opencti
    MINIO__USE_AWS_ROLE: "false"
    MINIO__USE_SSL: "false"
    # Elasticsearch
    ELASTICSEARCH__URL: "https://es-data-nodes:9200"
    ELASTICSEARCH__SSL__REJECT_UNAUTHORIZED: "false"
    ELASTICSEARCH__USERNAME: "elastic"
    ELASTICSEARCH__INDEX_PREFIX: "opencti"
    # RabbitMQ
    RABBITMQ__QUEUE_TYPE: quorum
    RABBITMQ__USE_SSL: "false"
    RABBITMQ__MANAGEMENT_SSL: "false"
    # REDIS
    REDIS__TRIMMING: 10000
    REDIS__ACTIVITY_TRIMMING: 50000
    REDIS__NOTIFICATION_TRIMMING: 50000
    REDIS__NAMESPACE: opencti
    REDIS__USE_SSL: "false"
    REDIS__MODE: "sentinel"
    REDIS__SENTINEL_MASTER_NAME: "myMaster"
    REDIS__SENTINEL_UPDATE_SENTINELS: "false"
    REDIS__SENTINEL_FAILOVER_DETECTOR: "true"
    REDIS__HOSTNAMES: '["redis-sentinel-sentinel:26379"]'

  envFromSecrets:
    ELASTICSEARCH__PASSWORD:
      key: elastic
      secretName: elasticsearch-es-elastic-user
    MINIO__ACCESS_KEY:
      key: accessKey
      secretName:  minio-credentials
    MINIO__SECRET_KEY:
      key: secretKey
      secretName: minio-credentials
    RABBITMQ__USERNAME:
      key: username
      secretName: rabbitmq-default-user
    RABBITMQ__PASSWORD:
      key: password
      secretName: rabbitmq-default-user
  front:
    resources:
    requests:
      cpu: 1
      memory: 4Gi
    limits:
      memory: 8Gi
    ingress:
      enabled: true
      className: "nginx" # Update it to reflect your environment
      hosts:
        - host: opencti.local # Update it to reflect your environment
          paths:
            - path: /
              pathType: Prefix

  ingest:
    replicaCount: 3
    resources:
      requests:
        cpu: 1
        memory: 1Gi
      limits:
        memory: 2Gi

  worker:
    replicaCount: 9
    env:
      OPENCTI_TOKEN: "d99208c3-0eca-4c65-9633-42be3b9c6bb8"
    resources:
      limits:
        memory: 1Gi
      requests:
        cpu: "1"
        memory: 512Mi

elasticsearch:
  enabled: true
  masterNodes:
    replicas: 3
  dataNodes:
    replicas: 5
    storageSize: 200Gi
    javaOpts: -Xms8g -Xmx8g -Xlog:disable -Xlog:all=warning:stderr:utctime,level,tags -Xlog:gc=debug:stderr:utctime
    resources:
      requests:
        memory: 16Gi
        cpu: 2
      limits:
        memory: 18Gi
  kibana:
    http:
      tls:
        selfSignedCertificate:
          disabled: true

rabbitmq:
  enabled: true
  replicas: 3
  storageSize: 20Gi
  resources:
    limits:
      memory: 4Gi
    requests:
      cpu: 256m
      memory: 2Gi

redis:
  enabled: true
  mode: sentinel
  data:
    storageSize: 16Gi
    resources:
      limits:
        cpu: "2"
        memory: 12Gi
      requests:
        cpu: "1"
        memory: 8Gi

minio:
  enabled: true
  standardPool:
    storageSize: 30Gi
    resources:
      limits:
        memory: 4Gi
      requests:
        cpu: 200m
        memory: 1Gi
  exposeServices:
    console: true

L(arge)

Recommended for production instances with many feeds, connectors...

opencti:
  env:
    # OpenCTI
    APP__ENCRYPTION_KEY: "ChangeMe"
    APP__BASE_URL: "http://opencti:8080"
    APP__ADMIN__EMAIL: admin@opencti.io
    APP__ADMIN__PASSWORD: WhatA_Strong-P4ssword*!
    APP__ADMIN__TOKEN: "d99208c3-0eca-4c65-9633-42be3b9c6bb8"
    APP__HEALTH_ACCESS_KEY: "8b55aac644e9e6f2701805584cc391ff81d3ecec"
    # MinIO
    MINIO__BUCKET_NAME: opencti
    MINIO__USE_AWS_ROLE: "false"
    MINIO__USE_SSL: "false"
    # Elasticsearch
    ELASTICSEARCH__URL: "https://es-data-nodes:9200"
    ELASTICSEARCH__SSL__REJECT_UNAUTHORIZED: "false"
    ELASTICSEARCH__USERNAME: "elastic"
    ELASTICSEARCH__INDEX_PREFIX: "opencti"
    # RabbitMQ
    RABBITMQ__QUEUE_TYPE: quorum
    RABBITMQ__USE_SSL: "false"
    RABBITMQ__MANAGEMENT_SSL: "false"
    # REDIS
    REDIS__TRIMMING: 10000
    REDIS__ACTIVITY_TRIMMING: 50000
    REDIS__NOTIFICATION_TRIMMING: 50000
    REDIS__NAMESPACE: opencti
    REDIS__USE_SSL: "false"
    REDIS__MODE: "sentinel"
    REDIS__SENTINEL_MASTER_NAME: "myMaster"
    REDIS__SENTINEL_UPDATE_SENTINELS: "false"
    REDIS__SENTINEL_FAILOVER_DETECTOR: "true"
    REDIS__HOSTNAMES: '["redis-sentinel-sentinel:26379"]'

  envFromSecrets:
    ELASTICSEARCH__PASSWORD:
      key: elastic
      secretName: elasticsearch-es-elastic-user
    MINIO__ACCESS_KEY:
      key: accessKey
      secretName:  minio-credentials
    MINIO__SECRET_KEY:
      key: secretKey
      secretName: minio-credentials
    RABBITMQ__USERNAME:
      key: username
      secretName: rabbitmq-default-user
    RABBITMQ__PASSWORD:
      key: password
      secretName: rabbitmq-default-user
  front:
    resources:
    requests:
      cpu: 1
      memory: 4Gi
    limits:
      memory: 8Gi
    ingress:
      enabled: true
      className: "nginx" # Update it to reflect your environment
      hosts:
        - host: opencti.local # Update it to reflect your environment
          paths:
            - path: /
              pathType: Prefix

  ingest:
    replicaCount: 6
    resources:
      requests:
        cpu: 1
        memory: 1Gi
      limits:
        memory: 2Gi

  worker:
    replicaCount: 12
    env:
      OPENCTI_TOKEN: "d99208c3-0eca-4c65-9633-42be3b9c6bb8"
    resources:
      limits:
        memory: 1Gi
      requests:
        cpu: "1"
        memory: 512Mi

elasticsearch:
  enabled: true
  masterNodes:
    replicas: 3
  dataNodes:
    replicas: 7
    storageSize: 500Gi
    javaOpts: -Xms16g -Xmx16g -Xlog:disable -Xlog:all=warning:stderr:utctime,level,tags -Xlog:gc=debug:stderr:utctime
    resources:
      requests:
        memory: 32Gi
        cpu: 2
      limits:
        memory: 36Gi
  kibana:
    http:
      tls:
        selfSignedCertificate:
          disabled: true

rabbitmq:
  enabled: true
  replicas: 3
  storageSize: 50Gi
  resources:
    limits:
      memory: 8Gi
    requests:
      cpu: 256m
      memory: 2Gi

redis:
  enabled: true
  mode: sentinel
  data:
    storageSize: 30Gi
    resources:
      limits:
        cpu: "2"
        memory: 20Gi
      requests:
        cpu: "1"
        memory: 15Gi

minio:
  enabled: true
  standardPool:
    storageSize: 50Gi
    resources:
      limits:
        memory: 4Gi
      requests:
        cpu: 200m
        memory: 1Gi
  exposeServices:
    console: true