Skip to content

Helm Configuration Options

Configuration options for the huddo and huddo-cp Helm charts.


How values are structured

Both charts are umbrella charts — every service is an instance of the same subchart, so the same keys are available under every service block.

Key Applies to
global.env A map of environment variables added to every service
global.envArray A list of valueFrom environment variables (secrets, ConfigMaps) for every service
<service>.env Environment variables for one service, merged over global.env
<service>.envArray valueFrom entries for one service
<service>.replicaCount Number of pods for one service (default 2; wikishift, search-worker and attachments-indexer 1)
<service>.image.tag Pin one service to a specific image tag
<service>.ingress Ingress host, path, TLS and Traefik middleware for one service
<service>.resources CPU/memory requests and limits

Service names are core, acl, attachments, attachments-indexer, discussions, notifications, ideas, wikis, spaces, search, search-worker, editor, user, provider, licence, socketcluster, wikishift, and — when Boards is enabled — boards-core, boards-webfront, boards-app, boards-notification, boards-events. The huddo-cp chart adds s3; the huddo chart adds redis.

Warning

An entry in <service>.env overrides the same key from global.env, and both override the chart defaults. envArray entries shadowed by an env key of the same name are dropped.


Core options

Key Description
global.repository Container registry and organisation. Default quay.io/huddo
global.imageTag Image tag deployed for every service — see releases
global.imagePullSecret Name of the Kubernetes image pull secret. Default quay
global.env.HUDDO_URI Public base URL of Huddo, including the /huddo prefix and no trailing slash. Every app URL derives from it
global.env.APP_URI Deprecated fallback for HUDDO_URI. When Boards runs in the same release, set this to the Boards UI URL
global.env.API_GATEWAY Boards API URL. Only needed when Boards runs in the same release
global.env.URL_BOARDS URL of Huddo Boards, shown in the Huddo app switcher. Set it whether Boards is in this release or a separate one
global.env.SOCKET_CLUSTER_SECRET Shared secret signing real-time connections. Must be the same across every service
global.env.SOCKET_CLUSTER_HOST In-cluster hostname of the SocketCluster worker. Derived from the release name — override only if you rename the release

Products

Key Default Description
products.ideas.enabled true Deploys the ideas service
products.wikis.enabled true Deploys the wikis service. editor is always deployed and is not gated
products.spaces.enabled true Deploys the spaces service, Huddo Spaces
products.search.enabled true Deploys cross-app search — search, search-worker and the OpenSearch cluster. See Search
products.boards.enabled false Deploys Huddo Boards inside this release (boards-core, boards-webfront, boards-app, boards-notification, boards-events)
global.drawio.enabled false Deploys the self-hosted draw.io editor behind the Wikis diagram block. See Diagrams
wikishift.enabled false Deploys the Wikis migration utility
activity-migration.enabled false huddo-cp only. Connections Activities ➡️ Boards migration

Why draw.io sits under global

The other toggles live under products. Draw.io is one switch that has to move three things together — the editor deployment, its ingress, and the DRAWIO_ENABLED flag on the wikis app. That flag is environment on the wikis subchart, and a subchart can only read its own values plus global, so the switch lives there.

Shared services

The user, provider and licence services are shared between Huddo products. Both charts can either deploy them or alias them to an existing Huddo Boards release in the same namespace — see Adding Huddo to an existing Boards install.

Key Default Description
sharedServices.deploy true Deploy user, provider and licence. Set false when a Boards release already provides them
sharedServices.aliases per chart ExternalName targets used when deploy is false. Maps huddo-user, huddo-provider and huddo-licence onto the Boards service names

The alias defaults already match the Boards chart each one pairs with, so they normally need no override:

Chart Pairs with Default targets
huddo-cp huddo-boards-cp boards-user, boards-provider, boards-licence
huddo huddo-boards user, provider, licence

Note

Rendering fails if products.boards.enabled is true while sharedServices.deploy is false — the two describe conflicting deployments.

MongoDB

huddo-cp reads the Component Pack MongoDB details from the connections-env ConfigMap and authenticates with X.509, so only MONGO_CERT_USER normally applies. The huddo chart needs the full connection details.

Key Description
global.env.MONGO_PROTOCOL mongodb (default) or mongodb+srv
global.env.MONGO_HOST host:port, or just the host for mongodb+srv
global.env.MONGO_USER Database user
global.env.MONGO_PASSWORD Database password
global.env.MONGO_PARAMS Extra connection string query parameters, e.g. retryWrites=true&w=majority
global.env.MONGO_REPLICA_SET_NAME Replica set name, appended to the query parameters
global.env.MONGO_CERT_USER X.509 certificate user for MONGODB-X509 auth. huddo-cp defaults to kudos-boards; set to '' to use username/password auth instead
<service>.env.MONGO_DB Database name for one service. Defaults are huddo-user, huddo-licence, huddo-attachments, huddo-discussions, huddo-notifications, huddo-ideas, huddo-wikis and huddo-spaces

S3 file storage

The huddo-cp chart deploys SeaweedFS and wires these up for you — see S3 storage. The huddo chart expects an external endpoint.

Key Description
global.env.S3_ENDPOINT Hostname of the S3 endpoint, no protocol
global.env.S3_PORT Port, e.g. 443
global.env.S3_SECURE 'true' to connect over TLS
global.env.S3_USE_SSL As above, read by the Boards services
global.env.S3_BUCKET Bucket name. Default huddo (Boards uses huddo-boards)
global.env.S3_ACCESS_KEY Access key
global.env.S3_SECRET_KEY Secret key

Cache

huddo-cp binds the Component Pack cache automatically from the connections-env ConfigMap and the cache-service-secret / redis-secret secrets. The huddo chart deploys its own Redis (huddo-redis).

Key Description
redis.enabled huddo chart only. Set false to use an existing cache
global.env.REDIS_CACHE_HOST Cache hostname
global.env.REDIS_CACHE_PORT Cache port
global.env.REDIS_CACHE_PASSWORD Cache password, if required

Cross-app search is three pieces: the search API, a search-worker running the BullMQ index queue on the same image, and an OpenSearch cluster deployed as the huddo-opensearch subchart. It is on by default — turning it off leaves the in-app search boxes returning nothing.

The other apps push documents to the search responder rather than calling the public API, so SEARCH_HOST points at an in-cluster ClusterIP service that is never exposed through the ingress.

Key Default Description
products.search.enabled true Deploys search, search-worker and OpenSearch
global.env.SEARCH_HOST http://huddo-search-internal In-cluster hostname of the search responder. Clear it alongside products.search.enabled=false, or every write logs a failed push to a host that no longer exists
global.env.SEARCH_PORT 23737 Responder port. Matches search.balancer.port
search.ingress.path /search Public path for the query API (/search/api). Under a prefix, set /huddo/search with traefik.stripPrefix.prefix: /huddo
search.env.OPENSEARCH_NODE http://huddo-opensearch:9200 OpenSearch endpoint. Point both search and search-worker at an external cluster to run one
opensearch.persistence.size 20Gi Index volume size
opensearch.persistence.storageClassName — Dynamic provisioner to claim from
opensearch.persistence.nfs.server / .path — NFS export to use instead of a provisioner
opensearch.persistence.retainOnDelete true Annotates the claim helm.sh/resource-policy: keep, so helm uninstall leaves the index behind. See Keeping the index
opensearch.nodeSelector / opensearch.tolerations — Pin the cluster to a node pool of its own. See Giving OpenSearch room
networkPolicy.enabled true NetworkPolicies restricting the responder (23737) to this release's apps and OpenSearch (9200) to search / search-worker

Storage before the first deploy

A Connections cluster usually has no dynamic provisioner, so the index needs an NFS export in the same layout as your other Component Pack volumes. Create the export before the first deploy — the chart's init container chowns it, but it will not create it.

opensearch:
  persistence:
    nfs:
      server: '[NFS_SERVER_IP]'
      path: /pv-connections/huddo-opensearch

Note

NetworkPolicies are only enforced by a CNI that implements them. Where the CNI ignores them, the ClusterIP boundary remains the floor — neither port is ever published through the ingress.

Health also matters on rollout: search reports not-ready with a 503 until OpenSearch is reachable, so a deploy waits for a serviceable index rather than serving empty results.

Giving OpenSearch room

OpenSearch requests 200m CPU and 2Gi of memory, with a 1g heap and a memory limit equal to its request. It is by some margin the largest pod in the release, and on a small cluster it is the one that will fail to schedule: if no single node has 2Gi free, the pod stays Pending, and because search reports not-ready until the index answers, the whole deploy waits and then times out.

Check what a node actually has free before the first deploy — kubectl describe node reports requested, not used, and the scheduler only looks at requests:

kubectl describe nodes | grep -A5 'Allocated resources'

Where the cluster is tight, give the index a node of its own. Label and taint a node pool, then point OpenSearch at it:

opensearch:
  nodeSelector:
    pool: search
  tolerations:
    - key: dedicated
      operator: Equal
      value: search
      effect: NoSchedule

The taint is what makes it stick — without one, other workloads fill the node and the index is homeless again. Pin OpenSearch alone: search and search-worker carry no resource requests and schedule anywhere, and leaving them on the general pool keeps search's two replicas spread by their pod anti-affinity, which a single-node pool would defeat.

Sizing note: a node advertises less than its machine type suggests. A 2 vCPU / 4 GB node typically offers around 940m CPU and 2.73Gi to the scheduler once the kubelet reservation is taken, and daemonsets take a few hundred Mi more — enough for a 2Gi pod, with little left for a larger heap.

Keeping the index across an uninstall

The index claim is annotated helm.sh/resource-policy: keep by default, so helm uninstall leaves the PersistentVolumeClaim — and the data — in place. Reinstalling the same release name into the same namespace adopts the claim and finds the index intact.

This matters on a cloud provisioner: most default StorageClasses reclaim Delete, so without the annotation an uninstall would take the underlying disk with it. Installs on an NFS PV are unaffected either way, since that volume is Retain over an export that outlives the release.

Set opensearch.persistence.retainOnDelete: false to have the volume torn down with the release. The same switch exists on SeaweedFS as s3.persistence.retainOnDelete, where the stakes are higher — that volume holds attachment binaries rather than a rebuildable index.

Tip

The index is derived data. If it is ever lost, the worker rebuilds it from the service databases — you lose search results until the reindex completes, not content.


Per-service options

User

Key Description
user.env.JWT_SECRET Recommended: random string of at least 32 characters used to sign sessions
user.env.CONNECTIONS_* etc. Authentication provider settings — see below

Licence

Key Description
licence.env.LICENCE Licence key from the Huddo Store. Must cover the products you deploy (huddo.wikis, huddo.ideas)

Notifications (email)

Email transport is chosen in this order: Ethereal (development preview) ➡️ SendGrid ➡️ generic SMTP. If none is configured, email delivery is disabled and everything else keeps working.

Key Description
notifications.env.EMAIL_HOST SMTP gateway hostname
notifications.env.EMAIL_PORT Optional: SMTP port.
Default 25, or 587 when EMAIL_USERNAME is set
notifications.env.EMAIL_USERNAME Optional: SMTP username. Setting it enables SMTP auth
notifications.env.EMAIL_PASSWORD Optional: SMTP password
notifications.env.EMAIL_FROM Address emails are sent from. Without it, delivery is skipped
notifications.env.EMAIL_FROM_NAME Optional: display name on outbound email
notifications.env.EMAIL_OPTIONS Optional: extra NodeMailer options as JSON, e.g. '{"requireTLS":true}'. If your SMTP gateway presents a private certificate, add it to the internal CA bundle rather than disabling verification here
notifications.env.SENDGRID_API_KEY Optional: use SendGrid instead of SMTP
notifications.env.EMAIL_ETHEREAL Optional: 'true' routes all mail to a throwaway Ethereal inbox for testing. Credentials are printed in the pod logs at startup

ACL

Key Default Description
acl.env.L1_CACHE_TTL 600 In-memory cache TTL in seconds
acl.env.L2_CACHE_TTL 3600 Redis cache TTL in seconds

Attachments

Key Description
attachments.env.UNSPLASH_ACCESS_KEY Optional: Unsplash access key. Without it, cover image search is disabled

Wikis

Key Description
wikis.env.NEXT_PUBLIC_BASE_PATH Path Wikis is served from. Set to match wikis.ingress.path (e.g. /huddo/wikis)

Diagrams (draw.io)

Wikis has an inline diagram block backed by a self-hosted draw.io editor. The editor is a container of its own, framed by the wikis page and talking to it over postMessage only — no third-party framing, and no diagram content leaving the deployment.

Turn it on with the single switch, and give the ingress the same host Wikis is served from:

global:
  drawio:
    enabled: true

drawio:
  ingress:
    hosts:
      - '[HUDDO_HOST]'
    path: /huddo/drawio   # /drawio where the release has no path prefix
Key Default Description
global.drawio.enabled false Deploys the editor, publishes it at drawio.ingress.path, and sets DRAWIO_ENABLED on wikis
drawio.ingress.hosts — Must be the same host as wikis.ingress.hosts
drawio.ingress.path /drawio Include the release's path prefix, e.g. /huddo/drawio
drawio.image jgraph/drawio Image reference. Point at your mirror for an air-gapped install
drawio.imageTag pinned Pinned deliberately — draw.io releases often and its embed protocol is not versioned
drawio.imagePullSecret '' Only needed when pulling from a mirror that requires credentials
drawio.networkPolicy.enabled true Denies egress off the cluster from the editor pod. In-cluster egress and DNS stay open

Same origin is required, not cosmetic

Wikis derives the editor URL from HUDDO_URI, the same way it derives the editor and SocketCluster paths — so a release whose HUDDO_URI ends in /huddo looks for draw.io at /huddo/drawio. Serving it from another host reintroduces exactly the cross-origin framing and third-party-cookie problems that self-hosting exists to avoid.

stripPrefix defaults to the ingress path, so Tomcat keeps serving the editor at its own root whichever path you choose.

The image comes from Docker Hub

This is the only image in the stack that is not ours. The release's global.imagePullSecret holds Quay credentials and is deliberately not applied to this pod.

For an air-gapped or Component Pack install, mirror the image alongside the quay.io/huddo ones and point the chart at your copy. Anonymous Docker Hub pulls are rate-limited per source IP, so mirroring is worth it even where egress exists.

drawio:
  image: registry.internal/mirror/jgraph/drawio
  imagePullSecret: mirror-pull-secret

Turning it off again is safe

Gating is presentational only. The diagram node stays registered in the editor schema, so pages that already contain diagrams keep rendering them in both read and edit mode, and saving a page does not strip them — users simply cannot create or edit diagrams. Rendering fails if you enable draw.io with products.wikis.enabled: false, since nothing would frame it.

The pod is stateless: no database, no volume, no auth, no secrets. Wikis owns persistence — in embed mode the editor never talks to a server of its own.


Ingress

Every service block takes the same ingress options.

Key Description
<service>.ingress.enabled Default true for services with a public route
<service>.ingress.hosts List of hostnames (no protocol)
<service>.ingress.path Path the service is served from
<service>.ingress.pathType Default Prefix
<service>.ingress.ingressClassName cnx-ingress-traefik in huddo-cp, traefik in huddo
<service>.ingress.tls List of {hosts, secretName} — only if certificates are resolved in Kubernetes
<service>.ingress.traefik.stripPrefix.enabled Creates a Traefik StripPrefix middleware and attaches it to the Ingress
<service>.ingress.traefik.stripPrefix.prefix Prefix to strip. Defaults to ingress.path when blank — set it to /huddo for the services served under the shared prefix
<service>.ingress.traefik.stickyCookie Session affinity for the services that need it (ideas, boards-core)
socketcluster.ingress.prefixedPath.enabled Serves the WebSocket at /huddo/socketcluster as well as /socketcluster, so one front-proxy location /huddo block covers everything. On by default

Warning

Do not also set traefik.ingress.kubernetes.io/router.middlewares in ingress.annotations — the chart injects it when stripPrefix or stickyCookie is enabled.


Secrets & certificates

These options control the secrets the chart can create or mount. All are optional — the chart behaves exactly as before when they are left unset.

Image pull secret

When registry, username and password are all set, the chart creates the image pull secret automatically, named after global.imagePullSecret so the deployments reference it with no further configuration. Leave them empty to manage the secret yourself. Supply the password via --set or an encrypted values file rather than committing it.

Key Description
imageCredentials.registry Container registry hostname, e.g. quay.io
imageCredentials.username Registry username
imageCredentials.password Registry password / token

Internal CA bundle

Mounts a CA bundle into every service and sets NODE_EXTRA_CA_CERTS so the apps trust internal TLS endpoints (a reverse proxy, MongoDB, S3, etc). Provide either existingSecret (you manage the secret) or pem (the chart creates it) — not both.

Key Description Default
global.internalCa.existingSecret Name of an existing secret holding the CA bundle to mount. The chart does not create or own it —
global.internalCa.pem Alternatively, the CA bundle (PEM) itself — the chart creates the secret named secretName from it —
global.internalCa.key Filename/key within the secret. NODE_EXTRA_CA_CERTS is set to <mountPath>/<key> cert.pem
global.internalCa.secretName Name of the secret to create when pem is set internal-ca
global.internalCa.mountPath Directory the bundle is mounted at in every service /etc/ssl/internal-ca

Additional resources

Key Description
extraObjects List of additional Kubernetes resource manifests to create alongside the chart (e.g. ConfigMaps, Secrets)

Pod annotations

Adds annotations to the pods the chart creates — most commonly to opt Huddo into a service mesh such as Linkerd or Istio. All are empty by default, so leaving them unset renders exactly as before.

Key Description
global.podAnnotations Annotations added to every pod in the release
<service>.podAnnotations Annotations for one service only, merged on top of global.podAnnotations (the service's own keys win)
s3.jobPodAnnotations huddo-cp only. Annotations for the S3 Job pods (bucket setup), layered last so they override the two above
global:
  podAnnotations:
    linkerd.io/inject: enabled

core:
  podAnnotations:
    config.linkerd.io/proxy-cpu-limit: "1"

Exclude the S3 Job pods from the mesh

A meshed Job pod never completes — the proxy sidecar keeps running after the main container exits, so the Job hangs instead of finishing. If you enable mesh injection release-wide on huddo-cp, opt the S3 Jobs back out:

s3:
  jobPodAnnotations:
    linkerd.io/inject: disabled

Note

Changing these values changes the pod spec, so the affected pods are recreated on the next helm upgrade.


Provider specific options

Authentication is handled by the shared user service — the same service Huddo Boards uses. The provider keys are identical, under user.env:

Note

Register a separate OAuth client for Huddo with a callback of https://[HUDDO_URL]/auth/<provider>/callback — unless you are installing alongside an existing Boards release with sharedServices.deploy: false, in which case Huddo rides the Boards client and callback.

The provider service takes one Connections-specific option:

Key Description
provider.env.WIDGET_ID Optional: ID of the Community widget configured in this step

Logging

Key Description
<service>.env.DEBUG Debug namespaces for the Huddo apps, e.g. 'wikis:*,shared:*,prisma:*'
<service>.env.LOGGER_LEVEL Log level for the user, provider and licence services: error, warn, info, log, debug