Skip to Content

Helm values reference

This reference comes from the README of the released Arcade Helm chart version 1.11.2. Later chart releases replace it automatically.

Set these values in a values.yaml file, or pass them with --set, when you install or upgrade the chart. For installation steps, see Self-host Arcade with Helm.

Every configurable value, grouped. Defaults are in values.yaml.

Image pulls

KeyRequired?What it changes
dockerRegistry.enabledNoCreates the image-pull Secret.
dockerRegistry.existingSecretNoName of a pre-existing kubernetes.io/dockerconfigjson Secret in the release namespace. When set, the chart skips generating a Secret and references this one. username, token, server, and secretName are ignored.
dockerRegistry.serverNoDocker registry hostname (default Docker Hub). Ignored when existingSecret is set.
dockerRegistry.usernameIf no existingSecretRegistry username. Ignored when existingSecret is set.
dockerRegistry.tokenIf no existingSecretRegistry token (Docker Hub OAuth Access Token). Ignored when existingSecret is set.
dockerRegistry.secretNameNoName of the chart-generated image-pull Secret. Ignored when existingSecret is set.

To reuse a pre-provisioned image-pull Secret instead of passing credentials inline:

YAML
dockerRegistry: existingSecret: my-dockerhub-pull-secret # must already exist, type: kubernetes.io/dockerconfigjson

Support images

Init containers pull two support images. Override the repository to mirror them off Docker Hub for private-registry or air-gapped installs — this is the only way to keep the migration/seed/reconcile Helm hooks off Docker Hub, since Helm doesn’t run post-renderers over hook manifests. Defaults pull from Docker Hub.

KeyRequired?What it changes
supportImages.busybox.repositoryNoImage for the generate-env-file init container. Default busybox.
supportImages.busybox.tagNoTag for the busybox image. Default 1.36.
supportImages.busybox.pullPolicyNoPull policy for the busybox image. Default IfNotPresent.
supportImages.curl.repositoryNoImage for the wait-for-workers init container (a real curl image). Default curlimages/curl.
supportImages.curl.tagNoTag for the curl image. Default 8.5.0.
supportImages.curl.pullPolicyNoPull policy for the curl image. Default IfNotPresent.

Networking

KeyRequired?What it changes
global.bindAddressNoAddress every pod’s HTTP server binds to. Default 0.0.0.0 (IPv4). Set to :: for IPv6 or dual-stack.
global.ipFamilyPolicyNoSets spec.ipFamilyPolicy on every Arcade Service. SingleStack / PreferDualStack / RequireDualStack. Unset → cluster default (usually IPv4 single-stack).
global.ipFamiliesNoSets spec.ipFamilies on every Arcade Service, e.g. [IPv4, IPv6]. Order picks the primary ClusterIP. Unset → cluster default.

bindAddress controls what the pod listens on; ipFamilyPolicy / ipFamilies control which ClusterIP families the Service exposes. For IPv6 traffic to reach the pods you typically need both — bindAddress: '::' plus a dual-stack policy:

YAML
global: bindAddress: "::" ipFamilyPolicy: PreferDualStack ipFamilies: [IPv4, IPv6]

On Linux, :: accepts IPv4 via IPv4-mapped IPv6. The opentelemetry-collector subchart isn’t templated by the parent chart — override its receiver/exporter endpoints to [::]:port directly if you need IPv6 there.

Networking and security

KeyRequired?What it changes
podSecurityContext.enabledNoApply podSecurityContext.* (minus enabled) as the pod securityContext on every workload and Job. Enable to satisfy Pod Security Standards “restricted”.
containerSecurityContext.enabledNoApply containerSecurityContext.* on every app and init container; dashboard nginx gains writable emptyDir mounts so it tolerates readOnlyRootFilesystem.
networkPolicy.enabledNoRender a default-deny plus allow-ingress/allow-egress NetworkPolicy for Arcade pods. egressCIDRs, ingressNamespaceLabels, ingressPodLabels widen the allows.
ssrfAllowlistNoDestinations a user-created worker / MCP server may sit on despite the engine’s private-IP block. Entries are scheme://host[:port], '*.domain', a CIDR/IP, or '*'. Empty (default) keeps the block.
pluginSsrfAllowlistNoSame entry shapes, for plugin webhook hook URLs — which also must be https unless listed. Defaults to ['*'], i.e. the gate is off, so an upgrade doesn’t stop existing hooks on internal or plaintext addresses. Narrow it to your real hook destinations, or [] if none are internal.

Availability

KeyRequired?What it changes
pdb.enabledNoRender a PodDisruptionBudget for each long-running Deployment.
pdb.minAvailableNominAvailable applied to every PDB the chart renders. Integer or percentage string ('25%'). Default 1.

Jobs

KeyRequired?What it changes
jobs.activeDeadlineSecondsNoOverride activeDeadlineSeconds on the migration/seed/reconcile Jobs. 0 keeps each Job’s built-in default (300s / 600s).

Public catalog

GET /v1/public/tool_catalog and GET /v1/public/tools serve the deployment’s default catalog with no credential and no . They are off by default and only served when you turn them on:

YAML
engine: publicCatalog: enabled: true

Understand what this publishes before enabling it. On Arcade’s hosted platform the “default catalog” is Arcade’s own shipped toolkits. In a self-hosted install it is whatever workers you configured, so turning this on publishes their tool names, descriptions, and input/output schemas to anyone who can reach the engine. It never exposes -scoped toolkits, secret values, OAuth tokens, or per- readiness — but the operator’s own static workers are fair game. That is why the default is off and why enabling it is a deliberate act.

Once enabled:

  • Responses are shared-cacheable for one hour (Cache-Control: public, max-age=3600, must-revalidate) and carry an ETag, so a CDN in front of the engine absorbs the traffic. Nothing in the engine rate-limits these routes; if you expose them to the open internet, put a rate limit at your edge.
  • The catalog is built once and reused for engine.publicCatalog.cacheTtl (default 30s), so cost does not scale with request volume. A change to the default catalog becomes visible within that window without any manual step.
  • The catalog is populated by arcade reconcile, which the chart runs on install/upgrade (engine.reconcile.enabled). If reconcile has never run the endpoints answer with an empty catalog rather than an error.

To turn it off again, set enabled: false. The endpoints then respond as if they do not exist, and that response is non-cacheable, so caches converge to the off state on their next revalidation rather than serving a prior copy.

Branded catalog through the experience-api

The engine’s two routes carry operational data only — name, description, version, tool_count, and requirements. Icons, labels, categories, and pro/BYOC classifications belong to the design-system catalog. The experience-api serves GET /api/public/tool_catalog and GET /api/public/tools, which merge the two so a docs or marketing page gets one branded read instead of stitching them client-side.

This half is off by default too, and needs both flags on:

YAML
engine: publicCatalog: enabled: true experienceApi: publicCatalog: enabled: true

Turning on only one side is a misconfiguration: with just the experience-api flag, the engine refuses the upstream read and the BFF answers 503; with just the engine flag, the engine’s own two routes work and the BFF’s answer 404.

Once both are on:

  • Both sources are cached in-process, so a request costs no upstream work during the freshness window. One snapshot feeds both routes, so a toolkit’s tool_count never disagrees with the listed for it. limit / offset (both routes) and toolkit (/tools only) match the engine’s public catalog: default limit=100, max 1000. Responses are shared-cacheable (max-age=60, s-maxage=300, stale-while-revalidate=600) and carry an ETag. Like the engine’s routes, nothing here rate-limits anonymous traffic — put a rate limit at your edge.
  • A branding-source outage degrades to metadata: null rather than failing the read, so the catalog stays available when the design-system CDN is not.
  • Cross-origin reads are allowed from arcade.dev and bosslevel.dev (and their subdomains) without credentials, in addition to whatever CORS_ORIGIN already trusts.
  • experienceApi.publicCatalog.metadataUrl and .engineUrl point the two sources at hosts you control. A private deployment that opts in should set metadataUrl, since the default is an Arcade-hosted CDN.
  • Each replica holds the whole catalog in memory, and a refresh briefly holds the outgoing snapshot alongside the incoming one. On a large catalog that is tens of megabytes per replica, so check experienceApi.resources.limits.memory (default 512Mi) before enabling.

Gateway API

The chart emits one HTTPRoute per service, attached to a Gateway you manage outside the chart. TLS terminates at the Gateway listener — no TLS config lives on the routes. Controller-agnostic: works with AWS Gateway API Controller, Traefik, Envoy Gateway, and others.

When gateway.parentRefs is empty, no HTTPRoutes render — this is the chart’s out-of-the-box state.

KeyRequired?What it changes
gateway.enabledNoRender HTTPRoutes. Default true.
gateway.parentRefsYes when gateway.enabledShared parentRefs for every HTTPRoute. Empty means no routes render.
gateway.apiVersionNoHTTPRoute apiVersion. Override for controllers pinned to v1beta1.
gateway.hostnameYes (or ingress.hostname)Base hostname; every service URL derives from this. Falls back to ingress.hostname.
gateway.protocolNohttps or http for generated service URLs. Falls back to ingress.protocol.
gateway.subdomains.apiNoSubdomain label for the engine. Default api.
gateway.subdomains.coordinatorNoSubdomain label for the coordinator. Default coordinator.
gateway.subdomains.dashboardNoSubdomain label for the dashboard. Default dashboard.
gateway.subdomains.experienceApiNoSubdomain label for the experience API. Default experience.
gateway.engine.parentRefsNoPer-service override for the engine route.
gateway.coordinator.parentRefsNoPer-service override for the coordinator routes.
gateway.dashboard.parentRefsNoPer-service override for the dashboard route.
gateway.experienceApi.parentRefsNoPer-service override for the experience-api route.

Ingress and TLS (deprecated)

The legacy Ingress path is kept as a fallback during migration. Prefer gateway.* above. ingress.enabled defaults to false; the hostname/subdomain/URL settings remain in use by both paths.

KeyRequired?What it changes
ingress.enabledNoCreates Ingress resources. Default false.
ingress.hostnameYesBase hostname; every service URL derives from this.
ingress.protocolNohttps or http for generated service URLs.
ingress.subdomains.apiNoSubdomain label for the engine. Default api.
ingress.subdomains.coordinatorNoSubdomain label for the coordinator. Default coordinator.
ingress.subdomains.dashboardNoSubdomain label for the dashboard. Default dashboard.
ingress.subdomains.experienceApiNoSubdomain label for the experience API. Default experience.
ingress.typeNoprivate (self-signed TLS) or public (Let’s Encrypt). Default private.
ingress.publicIngressClassNoIngressClass when type: public.
ingress.privateIngressClassNoIngressClass when type: private.
ingress.publicAnnotationsNoAnnotations applied to every public Ingress.
ingress.privateAnnotationsNoAnnotations applied to every private Ingress.
ingress.letsEncrypt.enabledNoRequests Let’s Encrypt certs via cert-manager.
ingress.letsEncrypt.clusterIssuerIf letsEncrypt.enabledName of the ClusterIssuer.
ingress.letsEncrypt.secretNameNoName of the generated TLS Secret.
ingress.letsEncrypt.annotationsNoAdditional annotations for the Let’s Encrypt flow.
ingress.selfSignedIssuer.enabledNoCreates a self-signed ClusterIssuer for private TLS. Default true.
ingress.selfSignedIssuer.nameNoName of the generated ClusterIssuer.
ingress.selfSignedIssuer.caNamespaceNoNamespace the self-signed CA Certificate lives in.

Authentication

Both signing secrets are auto-generated on first install and persisted across upgrades. Point the ExistingSecret fields at a pre-created Secret in the release namespace to source them from an external vault instead.

KeyRequired?What it changes
auth.gatewayStateSigningKeyExistingSecretNoName of a Secret to read the MCP gateway OAuth state HMAC key from.
auth.gatewayStateSigningKeyExistingSecretKeyNoKey within that Secret. Default INTERMEDIATE_AS_STATE_SIGNING_KEY.
auth.dashboardSessionSecretsExistingSecretNoName of a Secret to read the Better Auth dashboard session cookie signing key from.
auth.dashboardSessionSecretsExistingSecretKeyNoKey within that Secret. Default BETTER_AUTH_SECRETS. Format <version>:<value>, 32+ chars.

Upstream IdP (post-install seeding)

A post-install/post-upgrade Job registers the upstream OIDC provider for the user’s organization. On a fresh install (no orgs yet) it bootstraps an organization + ; on subsequent runs it attaches the IdP to the first existing organization.

The Job reads credentials from a Kubernetes Secret named in auth.upstreamIdp.secretName (default upstream-idp-creds). Create it before helm install:

Terminal
kubectl create secret generic upstream-idp-creds \ --namespace arcade \ --from-literal=UPSTREAM_NAME='Acme Okta' \ --from-literal=UPSTREAM_ISSUER='https://acme.okta.com' \ --from-literal=UPSTREAM_CLIENT_ID='0oa...' \ --from-literal=UPSTREAM_CLIENT_SECRET='...'
KeyRequired?What it changes
auth.upstreamIdp.secretNameNoName of the Secret holding upstream OIDC credentials.
auth.upstreamIdp.bootstrapOrgNameNoOrg name created on fresh install. Ignored on upgrades.
auth.upstreamIdp.bootstrapProjectNameNoProject name created on fresh install. Ignored on upgrades.

Gateway login

The Gateway “Arcade Auth” flow ( clients with auth_type: arcade_oauth) authenticates via a single platform-wide “static” . By default that row points at the coordinator-hosted Arcade Identity service at {coordinatorBase}/signin/oidc, which federates to the customer’s upstream IdP via the auth.upstreamIdp config above.

Set auth.gatewayLogin.issuer to point the Gateway login flow at an external IdP directly, skipping Arcade Identity. The same Okta (or Auth0, etc.) app used for dashboard SSO can serve both flows — just register both redirect URIs on it:

  • {coordinatorBase}/signin/oidc/callback — dashboard SSO
  • {coordinatorBase}/oauth2/intermediate_callback — Gateway login

When auth.gatewayLogin.existingSecret is unset (the default), the chart reuses auth.upstreamIdp.secretName and reads the existing UPSTREAM_CLIENT_ID / UPSTREAM_CLIENT_SECRET keys — no extra Secret needed.

KeyRequired?What it changes
auth.gatewayLogin.issuerNoOIDC issuer URL of the external IdP. Empty (default) = use coordinator-hosted Arcade Identity.
auth.gatewayLogin.existingSecretIf issuer setSecret with the OIDC client credentials. Default reuses auth.upstreamIdp.secretName.
auth.gatewayLogin.clientIdKeyNoKey within the Secret for the client_id. Default UPSTREAM_CLIENT_ID.
auth.gatewayLogin.clientSecretKeyNoKey within the Secret for the client_secret. Default UPSTREAM_CLIENT_SECRET.
auth.cliRedirectUrisNoLoopback callback URIs accepted for arcade login. Defaults match arcade-cli’s hardcoded 127.0.0.1:9905; override only if you ship a CLI build that binds elsewhere.

When to set a distinct existingSecret: leaving it empty silently reuses auth.upstreamIdp.secretName. That’s the right default when one IdP app serves both flows, but it means rotating auth.upstreamIdp’s Secret will affect Gateway login in lockstep. Set auth.gatewayLogin.existingSecret to a separate Secret when you need independent rotation, distinct IdP apps for SSO vs. Gateway login, a phased IdP migration, or different sub-claim mappings.

URL overrides

Every URL under arcade.* auto-derives from ingress.hostname and ingress.subdomains.*. Override these only for split-horizon DNS or external proxy routing.

KeyRequired?What it changes
arcade.engineUrlNoPublic engine URL.
arcade.coordinatorUrlNoPublic coordinator URL (with /api/v1).
arcade.coordinatorBaseUrlNoPublic coordinator base URL (no /api/v1).
arcade.dashboardUrlNoPublic dashboard URL.
arcade.experienceApiUrlNoPublic experience API URL.
arcade.identityIssuerUrlNoIssuer URL for Arcade Identity. Defaults to <coordinatorBaseUrl>/signin/oidc.
arcade.identityRedirectUriNoOverride the OIDC redirect URI for dashboard login (experience-api OAuth callback). Defaults to <experienceApiUrl>/api/auth/oauth2/callback/oidc.
arcade.identityFederationClientIdNoFederation client ID for multi-instance deployments.
arcade.engineIdNoEngine UUID. Auto-generated on first install if empty.
arcade.engineSlugNoEngine slug. Derived from engineId if empty.

Features

KeyRequired?What it changes
features.chatEnabledNoEnables the Chat feature in the dashboard. Requires a provider key for at least one model in playground.models (e.g. playground.apiKey or playground.openaiApiKey). Default true.
features.deniedPassthroughHeadersNoHeader names a gateway may not declare in allowed_passthrough_headers, matched case-insensitively when a gateway is created, updated, or patched. Gateways that already persisted a listed header keep passing it through. Set to [] to allow any header. Default [Authorization].
features.auditLog.enabledNoEnables audit logging. Default true.
features.auditLog.publishMethodNoHow the engine publishes audit events: http (signed coordinator endpoint, default) or redis (write the audit stream directly). Default http.
features.auditLog.retentionDaysNoDays to retain persisted audit events before cleanup (1–3650). Default 30.
features.auditLog.streamMaxLenNoMax entries buffered in the Redis audit stream. Applied by both the coordinator and the engine Redis publisher. Default 100000.
features.auditLog.cleanupWindow.startHourNoOff-peak UTC hour the expired-event purge starts (0–23). Must differ from endHour. Default 2.
features.auditLog.cleanupWindow.endHourNoOff-peak UTC hour the expired-event purge ends (0–23). Must differ from startHour. Default 4.

Operator RBAC (OpenFGA)

Fine-grained, per-organization authorization. Always deployed and always enforced: the coordinator decides every organization- and -scoped admin route against this policy decision point, and fails closed — HTTP 503 — when it cannot reach one. There is no configuration in which the platform runs without it, and no legacy membership-check fallback.

[!IMPORTANT] Upgrading a deployment that already has organizations requires a one-time step on chart 1.9.8 before you upgrade to this release. See Upgrading from 1.9.x.

KeyRequired?What it changes
rbac.openfga.image.repositoryNoOpenFGA image repository. Default arcadedev/openfga.
rbac.openfga.image.tagNoOpenFGA image tag. Defaults to the chart’s appVersion. The authorization model ships inside this image — keep it in step with coordinator.image.tag, and at or above the chart default.
rbac.openfga.image.pullPolicyNoImage pull policy.
rbac.openfga.apiUrlNoIn-cluster PDP URL for the coordinator and bootstrap job. Defaults to http://<release>-openfga:8080.
rbac.openfga.storeNameNoName of the OpenFGA store the bootstrap job provisions and the coordinator resolves by. Default arcade-operator-rbac.
rbac.openfga.storeIdNoServer-minted store id. Normally leave empty — the coordinator resolves it by name at startup. Set only to use a pre-existing store id.
rbac.openfga.modelIdNoServer-minted model id. Normally leave empty — the coordinator waits for the model shipped in the OpenFGA image and pins that id at pod start. Set only to pin a specific model and skip that wait.
rbac.openfga.tokenExistingSecretNoSecret holding the preshared API token shared by the PDP and coordinator. When empty the chart generates and persists one.
rbac.openfga.tokenExistingSecretKeyNoKey within tokenExistingSecret that holds the token. Default openfga-api-token.
rbac.openfga.allowUnauthenticatedNoInsecure — runs the PDP with authentication disabled. Local/eval only. Default false.
rbac.openfga.replicaCountNoNumber of OpenFGA pods. Default 2.
rbac.openfga.database.nameNoOpenFGA’s logical database on the shared Postgres. Default openfga.
rbac.openfga.database.createNoRun CREATE DATABASE for the openfga database if absent. Default true.
rbac.openfga.database.migrationsNoRun the OpenFGA schema migration on install/upgrade. On by default — the PDP serves nothing until its schema exists. Set false only to migrate out-of-band.
rbac.openfga.resources.requestsNoCPU/memory requests.
rbac.openfga.resources.limitsNoCPU/memory limits.

The bootstrap job creates the store and writes the authorization model; the coordinator blocks startup until the store exists and its latest model is the one shipped in the OpenFGA image, then pins that model id for the pod’s lifetime — no manual step, no restart.

Waiting for the model, not just the store, is what keeps an upgrade that adds new relations from crash-looping the coordinator: without it a rolling pod can resolve the store instantly, read the still-current pre-upgrade model, and fail its startup consistency check while the bootstrap job is mid-write. Pinning the id also stops a later write from swapping the model out from under a pod that already booted.

The bootstrap job is a plain Job, not a hook, so it and the coordinator are applied together and converge; helm --wait is safe. Making it a hook would deadlock — hooks are deferred until Deployments are Ready, and the coordinator is not Ready until the job it is waiting on has run.

Upgrading from 1.9.x (operator-RBAC prerequisite)

A fresh install needs nothing here. Organizations created on this release get their authorization grants written as they are created.

An existing deployment does. Organizations created before RBAC became mandatory have no grants, and nothing in this release creates them: the bootstrap job provisions the store and writes the authorization model, not grants. The role-management API cannot bootstrap the first one either, because calling it already requires a grant. Upgrading straight to this release leaves every organization- and project-scoped admin route returning 403/404 to everyone — projects, members, invitations, API keys, , audit logs, billing.

The commands that write those grants do not exist in this release’s coordinator image. They ship in 1.9.8. So the upgrade runs in four steps, in this order:

  1. On chart 1.9.8, set rbac.enabled: true and upgrade. 1.9.8 ships it false, so a stock install has no policy decision point at all — no OpenFGA Deployment, no OPENFGA_API_URL — and the backfill below has nothing to write grants into. Wait for the bootstrap Job to provision the store and write the authorization model before continuing.

  2. Backfill grants, once per organization. Both commands are dry-run until --commit — run each without it first and read the plan:

    Terminal
    kubectl exec -n <namespace> deploy/<release>-coordinator -c coordinator -- \ python -m arcade.cli enable-operator-authz --org-id <org-id> --commit kubectl exec -n <namespace> deploy/<release>-coordinator -c coordinator -- \ python -m arcade.cli repair-operator-authz --org-id <org-id> --commit

    enable-operator-authz --all covers every organization at once, but refuses unless the operator-authz-new-orgs system flag is already on — set it with python -m arcade.cli set-system-flag first, or enrol one --org-id at a time. repair-operator-authz takes a repeatable --account <uuid> to restrict the grant set; use it when the dry-run plan lists whose access was deliberately revoked.

  3. Verify administration works for a non-owner member on 1.9.8.

  4. Remove rbac.enabled from your values and upgrade to this release. The chart refuses to render while the key is present, because it is silently ignored otherwise.

If you have already upgraded and are locked out, roll back to 1.9.8, set rbac.enabled: true there, run the backfill, and upgrade again. Writing tuples directly against OpenFGA is break-glass only — see the openfga-tuples runbook.

Raise helm --timeout past the hook waits

Helm’s default --timeout is 5m, but this release’s hooks can legitimately wait longer: the seed-idp hook budgets ~19m for the policy decision point to come up, and a concurrent index build on a large tool_execution can outlast 5m too. Helm kills the release at its own timeout regardless of a Job’s activeDeadlineSeconds, so the release fails while the work is still healthy. Pass --timeout 30m on the upgrade. Raising jobs.activeDeadlineSeconds without raising --timeout widens the gap rather than closing it.

[!WARNING] If you pin rbac.openfga.modelId, clear it before this upgrade. This release adds relations to the authorization model, and a pinned id skips the resolver that waits for the new model — leaving the coordinator asking for relations the pinned model does not define. Leave it empty and the coordinator pins the right id itself.

Dashboard

KeyRequired?What it changes
dashboard.enabledNoDeploys the dashboard.
dashboard.replicaCountNoNumber of dashboard pods.
dashboard.image.repositoryNoDashboard image repository.
dashboard.image.tagNoDashboard image tag. Defaults to the chart’s appVersion.
dashboard.image.pullPolicyNoImage pull policy.
dashboard.service.typeNoService type.
dashboard.service.portNoService port.
dashboard.service.healthCheckPathNoALB target-group health-check path (Gateway API TargetGroupConfiguration). Default /health.
dashboard.resources.requestsNoCPU/memory requests.
dashboard.resources.limitsNoCPU/memory limits.
dashboard.experienceApiUrlNoOverride for the experience API URL exposed to the browser.
dashboard.accountUiUrlNoURL users are redirected to for account registration.
dashboard.csp.includeIngressHostnameNoAdds ingress.hostname to the dashboard’s CSP origins.
dashboard.csp.additionalOriginsNoExtra origins for script-src, connect-src, frame-src, etc.

Engine

KeyRequired?What it changes
engine.replicaCountNoNumber of engine pods.
engine.database.nameNoEngine database name. Default arcade_engine. The scalar form engine.database: <name> is still accepted as a fallback.
engine.database.createNoRun CREATE DATABASE on startup. Set to false when the database is provisioned out-of-band (e.g., managed Postgres). Default true.
engine.database.migrationsNoRun engine DB migrations on install/upgrade. Defaults to true when unset.
engine.image.repositoryNoEngine image repository.
engine.image.tagNoEngine image tag. Defaults to the chart’s appVersion.
engine.image.pullPolicyNoImage pull policy.
engine.service.typeNoService type.
engine.service.portNoService port.
engine.service.healthCheckPathNoALB target-group health-check path (Gateway API TargetGroupConfiguration). Default /v1/health.
engine.resources.requestsNoCPU/memory requests.
engine.resources.limitsNoCPU/memory limits.
engine.cache.apiKeyTTLNoAPI-key cache TTL.
engine.cache.workerTTLNoWorker registry cache TTL.
engine.cache.toolRegistryTTLNoTool registry cache TTL.
engine.hpa.enabledNoCreates a HorizontalPodAutoscaler.
engine.hpa.minReplicasIf hpa.enabledHPA minimum replicas.
engine.hpa.maxReplicasIf hpa.enabledHPA maximum replicas.
engine.hpa.targetCPUUtilizationPercentageIf hpa.enabledHPA CPU target.
engine.migration.enabledNoDeprecated — use engine.database.migrations. Only honored when engine.database.migrations is unset.
engine.reconcile.enabledNoRuns arcade reconcile post-install/upgrade to fetch each worker’s tool catalog into the engine DB. Disable only if you trigger reconcile out-of-band.
engine.gatewayBootstrap.enabledNoRuns arcade bootstrap-gateways in a <release>-engine-gateway-bootstrap Job after the release is applied, reconciling the static gateway configuration ahead of engine seeding, identity seeding and worker reconcile. Independent of engine.database.migrations. Default false.
engine.internalCoordinatorUrlNoOverride for service-to-service calls. Defaults to in-cluster service DNS.
engine.publicCatalog.enabledNoServe the credential-free public catalog endpoints. Default false. See Public catalog before turning it on.
engine.publicCatalog.cacheTtlNoHow long a built public catalog is reused before the next read rebuilds it. Default 30s.
engine.toolsListPageSizeNoTools returned per MCP tools/list page. 0 (default) keeps the engine’s own default of 100. Raise it so clients make fewer round trips over a large catalog. Needs a chart value because it sits under a config block engine.extraConfig cannot reach.
engine.manageAuthorization.enabledNoList the System_ManageAuthorization built-in on every gateway that can reach a tool needing end-user authorization, with guidance ahead of the gateway’s MCP instructions. Default true.
engine.manageAuthorization.instructionNoReplaces that guidance. Unset keeps the engine’s built-in text; '' adds none.
engine.extraConfigNoYAML appended verbatim to engine.yaml. ${env:VAR} evaluated at runtime.
engine.extraEnvFromNoExtra envFrom sources, appended after chart-managed entries.
engine.extraEnvNoExtra env entries (raw EnvVar), appended last.

OAuth providers

Top-level oauthProviders block. Each entry renders an auth.providers row in the engine config with id: arcade-<id>, provider_id: <id>, and env-var refs <ID>_CLIENT_ID / <ID>_CLIENT_SECRET resolved from the Secret named in oauthProviders.existingSecret. Defaults to empty — operators add only the providers they want to enable.

KeyRequired?What it changes
oauthProviders.existingSecretNoName of a Secret holding <PROVIDER>_CLIENT_ID / <PROVIDER>_CLIENT_SECRET keys. The engine pod envFroms it.
oauthProviders.providers[]NoList of providers to render. Defaults to [] — nothing rendered, no upstream OAuth flows possible.

Per-entry shape:

FieldDefaultWhat it changes
idrequiredProvider id (e.g. airtable, github).
enabledtrueWhen false, row stays in config but the engine won’t initiate OAuth flows.
descriptionArcade's default <Title> providerDisplay name. Set explicitly for non-titlecase names (GitHub, ClickUp) or product renames (Square←squareup).
oauth2unsetOverrides layered over the bundled configuration for this provider_id — scope_delimiter, pkce, and the authorize_request / token_request / refresh_request blocks. Fields left out keep their bundled values.

Create the credentials Secret yourself — the chart doesn’t generate it. Each enabled provider needs two keys: <PROVIDER_ID_UPPERCASE>_CLIENT_ID and <PROVIDER_ID_UPPERCASE>_CLIENT_SECRET.

Terminal
kubectl create secret generic arcade-engine-oauth-providers -n arcade \ --from-literal=GOOGLE_CLIENT_ID=<...> \ --from-literal=GOOGLE_CLIENT_SECRET=<...> \ --from-literal=GITHUB_CLIENT_ID=<...> \ --from-literal=GITHUB_CLIENT_SECRET=<...>

Then list the providers in values.yaml (four per-entry shapes shown):

YAML
oauthProviders: existingSecret: arcade-engine-oauth-providers providers: - id: google - id: github description: "Arcade's default GitHub provider" # override titlecase - id: dropbox enabled: false # row rendered but engine won't initiate flows - id: microsoft oauth2: # authorize against one Entra tenant instead of /common authorize_request: endpoint: https://login.microsoftonline.com/<tenant>/oauth2/v2.0/authorize token_request: endpoint: https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token refresh_request: endpoint: https://login.microsoftonline.com/<tenant>/oauth2/v2.0/token

Dashboard playground

KeyRequired?What it changes
playground.apiKeyIf features.chatEnabledAnthropic API key for the dashboard playground. Enables anthropic/* models.
playground.existingAnthropicApiKeySecretNoName of a Secret to read the Anthropic key from instead of the inline value.
playground.existingAnthropicApiKeySecretKeyNoKey within that Secret. Default ANTHROPIC_API_KEY.
playground.openaiApiKeyNoOpenAI API key. Enables openai/* models in the chat model selector.
playground.existingOpenaiApiKeySecretNoName of a Secret to read the OpenAI key from instead of the inline value.
playground.existingOpenaiApiKeySecretKeyNoKey within that Secret. Default OPENAI_API_KEY.
playground.modelsNoComma-separated models in the chat selector (<provider>/<model>); first is the default. A model shows only if its provider key is set. Default anthropic/claude-sonnet-4-6.
playground.titleModelNoModel for chat-title generation. Empty uses a cheap default (anthropic/claude-haiku-4-5), falling back to the default chat model if that provider’s key isn’t set.
playground.providerBaseUrlsNoMap of <PROVIDER>_BASE_URL env-var name to base URL for custom provider endpoints (proxy / self-hosted / OpenAI-compatible). Keys must end in _BASE_URL. Default {}.

Workers

workers is a list. Each entry creates its own Deployment, Service, Secret, and HPA. At least one entry must be enabled.

arcadedev/worker runs a supervisor: one isolated runtime per offered toolkit version, so one worker can serve several versions of a toolkit. The supervisor.* keys configure it.

Upgrading from an eager worker

Charts up to 1.11.0 ship arcadedev/worker as the eager image: every toolkit imported into one process. From this release it is the supervisor, so an upgrade changes how each worker pod runs, with no values change needed:

  • are served by one child runtime per toolkit version, started on first call or at boot for supervisor.prewarmToolkits. The first call to a cold toolkit waits for its runtime to start.
  • The image also carries the pinned older toolkit versions, so one worker serves every version it offers.
  • toolPackages (or ARCADE_MCP_TOOL_PACKAGE in extraEnv) still scopes a worker to those toolkits; supervisor.serveToolkits is the supervisor’s own setting.
  • WORKERS has no effect and is logged as such; concurrency comes from supervisor.maxChildren.

The eager image last shipped with chart 1.11.0; to keep a worker on it, stay on that chart.

KeyRequired?What it changes
workers[].idYesWorker identifier.
workers[].enabledNoDeploys this worker.
workers[].replicaCountNoNumber of pods for this worker.
workers[].image.repository / .tag / .pullPolicyNoImage for this worker. The tag defaults to the chart’s appVersion.
workers[].service.type / .portNoService for this worker.
workers[].resources.requests / .limitsNoCPU/memory for this worker.
workers[].secretNoShared auth secret the engine uses to call this worker. Auto-generated and preserved across upgrades if empty.
workers[].existingSecretNoName of a Secret to read the worker auth secret from instead of workers[].secret.
workers[].existingSecretKeyNoKey within that Secret. Default ARCADE_WORKER_SECRET.
workers[].timeoutNoRequest timeout in seconds.
workers[].retryNoRetry count.
workers[].hpa.enabled / .minReplicas / .maxReplicas / .targetCPUUtilizationPercentageNoAutoscaling for this worker.
workers[].toolPackagesNoToolkit packages this worker loads, e.g. [arcade_math], rendered as ARCADE_MCP_TOOL_PACKAGE. Empty loads every toolkit installed in the image. On the supervisor image it narrows what is served when supervisor.serveToolkits is *.
workers[].probes.startup / .liveness / .readinessNoProbe settings (periodSeconds, timeoutSeconds, failureThreshold, …) merged over the defaults. The startup probe gates the other two and gives the worker 300s to come up by default.
workers[].extraEnvNoExtra env (raw EnvVar list) appended last to the worker container. Defaults from workerDefaults.extraEnv.
workers[].supervisor.prewarmToolkitsNoComma-separated toolkits started at boot and kept warm (the highest offered version of each). The worker reports ready only once they are running.
workers[].supervisor.serveToolkitsNoComma-separated toolkits this worker serves. Default * (all). A toolkit left off is refused and left out of the tools the worker publishes.
workers[].supervisor.idleTtlSecondsNoStop a runtime idle this many seconds. Default 600; 0 never stops one. Pre-warmed runtimes are exempt.
workers[].supervisor.maxChildrenNoMost runtimes running at once. Default 15; 0 is unbounded. Each running runtime costs about 100 MB.
workers[].supervisor.capacityWaitSecondsNoHow long a call waits for a free runtime slot at maxChildren before failing with a retryable error. Default 30.
workers[].supervisor.venvsSizeLimitNoSize limit of the scratch volume for runtimes installed at runtime. Default 2Gi.
workers[].supervisor.peerRouting.enabledNoReplicas agree on which one starts each toolkit version and hand cold calls to it, through a headless peers Service. Default false.
workers[].supervisor.peerRouting.promoteAfterForwardsNoHand-offs of one version from a replica before it starts its own runtime for it. Default 10.

Experience API

KeyRequired?What it changes
experienceApi.replicaCountNoNumber of pods.
experienceApi.database.nameNoExperience API database name. Default arcade_experience. The scalar form experienceApi.database: <name> is still accepted as a fallback.
experienceApi.database.createNoRun CREATE DATABASE on startup. Set to false when the database is provisioned out-of-band. Default true.
experienceApi.database.migrationsNoRun experience-api DB migrations on install/upgrade. Defaults to true when unset.
experienceApi.image.repository / .tag / .pullPolicyNoImage. The tag defaults to the chart’s appVersion.
experienceApi.service.type / .portNoService.
experienceApi.service.healthCheckPathNoALB target-group health-check path (Gateway API TargetGroupConfiguration). Default /.
experienceApi.resources.requests / .limitsNoCPU/memory.
experienceApi.hpa.enabled / .minReplicas / .maxReplicas / .targets / .behaviorNoAutoscaling.
experienceApi.migration.enabledNoDeprecated — use experienceApi.database.migrations. Only honored when experienceApi.database.migrations is unset.
experienceApi.coordinatorUrlNoOverride the in-cluster coordinator URL.
experienceApi.engineUrlNoOverride the in-cluster engine URL.
experienceApi.crossSiteCookiesNoSets SameSite=None on session cookies (staging/preview only).
experienceApi.oidcDiscoveryUrlNoOverride the URL where the experience-api fetches the OIDC discovery doc (see below).
experienceApi.publicCatalog.enabledNoServe the branded public catalog endpoints. Default false. See Public catalog.
experienceApi.publicCatalog.metadataUrlNoWhere toolkit branding metadata JSON is fetched. Defaults to the Arcade design-system CDN.
experienceApi.publicCatalog.engineUrlNoOverride the engine base URL used for the public catalog fetch. Empty reuses the engine URL the BFF already talks to.

experienceApi.oidcDiscoveryUrl

Use when the public issuer hostname isn’t reachable from inside pods (split-horizon DNS). Only the fetch path is rewritten — published URLs in the discovery doc keep using the public hostname. Full URL, ends in /.well-known/openid-configuration. In-cluster example: http://arcade-coordinator:8001/signin/oidc/.well-known/openid-configuration.

Coordinator

KeyRequired?What it changes
coordinator.replicaCountNoNumber of pods.
coordinator.database.nameNoCoordinator database name. Default arcade. The scalar form coordinator.database: <name> is still accepted as a fallback.
coordinator.database.createNoRun CREATE DATABASE on startup. Set to false when the database is provisioned out-of-band. Default true.
coordinator.database.migrationsNoRun coordinator DB migrations on install/upgrade. Defaults to true when unset.
coordinator.image.repository / .tag / .pullPolicyNoImage. The tag defaults to the chart’s appVersion.
coordinator.service.type / .portNoService.
coordinator.service.healthCheckPathNoALB target-group health-check path (Ingress annotation + Gateway API TargetGroupConfiguration). Default /api/v1/health.
coordinator.resources.requests / .limitsNoCPU/memory.
coordinator.hpa.enabled / .minReplicas / .maxReplicas / .targetCPUUtilizationPercentageNoAutoscaling.
coordinator.migration.enabledNoDeprecated — use coordinator.database.migrations. Only honored when coordinator.database.migrations is unset.
coordinator.redisMaxConnectionsNoMax Redis connections from the coordinator pool.
coordinator.webhookApiKeysNoAPI keys accepted on webhook endpoints.
coordinator.enableVerifierConfirmUserEndpointNoExpose the engine-identity confirm_user endpoint for a custom session verifier. Default false.
coordinator.cspEnforceNoEnforce Content-Security-Policy instead of Report-Only. Default false; set true after a quiet window.

Encryption keys

Every encryption key is auto-generated on first install and persisted with helm.sh/resource-policy=keep so it survives an uninstall. Changing a key in place destroys any data it encrypts — only override if you’re sourcing keys from an external vault (cross-cluster / multi-region).

Each field below accepts a pre-existing Kubernetes Secret via its paired *ExistingSecret / *ExistingSecretKey keys. Defaults for the key names are listed; the secret name is empty (and therefore the chart auto-generates the value) unless you set it.

KeyRequired?What it changes
encryption.databasePrivateKeyExistingSecretNoSecret name holding the RSA key (PEM) that wraps column-encrypted coordinator fields.
encryption.databasePrivateKeyExistingSecretKeyNoKey within that Secret. Default CURRENT_PRIVATE.
encryption.databaseRootKeyExistingSecretNoSecret name holding the 32-char symmetric key that encrypts OAuth tokens at rest.
encryption.databaseRootKeyExistingSecretKeyNoKey within that Secret. Default CURRENT_ROOT_KEY.
encryption.symmetricKeysExistingSecretNoSecret name holding the API-key signing KEY_CONFIGS JSON (supports rotation).
encryption.symmetricKeysExistingSecretKeyNoKey within that Secret. Default key-config.
encryption.asymmetricKeysExistingSecretNoSecret name holding the Ed25519 ASYMMETRIC_KEY_CONFIGS JSON for Arcade Identity / Intermediate AS.
encryption.asymmetricKeysExistingSecretKeyNoKey within that Secret. Default asymmetric-key-config.
engineJwsSigningKey.existingSecretNoSecret name holding the P-256 engine→coordinator JWT signing key.
engineJwsSigningKey.existingSecretKeyNoKey within that Secret. Default private-key-pem.

Postgres

KeyRequired?What it changes
postgres.enabledNoDeploys the bundled Postgres StatefulSet. Set false for external.
postgres.hostIf enabled: falsePostgres hostname.
postgres.portNoPostgres port.
postgres.directHostNoHost reaching Postgres directly, bypassing a pooler on host. This server only. Defaults to host.
postgres.directPortNoPort for directHost. Defaults to port.
postgres.targetSessionAttrsNolibpq target_session_attrs. Defaults to read-write.
postgres.waitForDb.enabledNoRun the wait-for-db init container, which waits for the writer and creates missing databases.
postgres.imageNoImage for the bundled Postgres.
postgres.sslmodeNoPostgres sslmode (disable, require, verify-ca, verify-full).
postgres.sslRootCertNoCA path appended to DATABASE_URL as sslrootcert. Required for verify-ca/verify-full.
postgres.caBundle.enabledNoMount a trusted CA bundle and set PGSSLROOTCERT / NODE_EXTRA_CA_CERTS.
postgres.caBundle.secretNameOne of twoSecret holding the PEM bundle. Takes precedence over configMapName.
postgres.caBundle.configMapNameOne of twoConfigMap holding the PEM bundle. Used when secretName is empty; templating fails if neither is set.
postgres.caBundle.keyNoKey within the Secret/ConfigMap holding the PEM bundle.
postgres.caBundle.mountPathNoMount path inside containers. Should match sslRootCert.
postgres.auth.usernameNoPostgres username.
postgres.auth.passwordNoPostgres password (bundled Postgres). Has a default; override for any non-evaluation install.
postgres.auth.existingSecretNoName of a Secret to read the password from instead of postgres.auth.password.
postgres.auth.existingSecretKeyNoKey within that Secret. Default DB_PASSWORD.
postgres.auth.existingSecretURLEncKeyNoKey holding the URL-encoded password, needed by the DSN-assembling services. Default DB_PASSWORD_URLENC.
postgres.auth.databaseNoDefault database name.
postgres.persistence.sizeNoPVC size for the bundled Postgres.
postgres.persistence.storageClassNoStorageClass for the PVC.
postgres.persistence.existingClaimNoUse a pre-existing PVC.
postgres.resources.requests / .limitsNoCPU/memory for the bundled Postgres.

directPort takes precedence over any port embedded in host (host:port or a comma-separated list), so a pooled entry’s port never carries into the direct endpoint; leaving both directHost and directPort unset changes nothing.

A directHost set without a directPort inherits port, which is correct when the direct server and the pooler listen on the same port and wrong when they do not. The wait-for-db init container logs the endpoint it is waiting on and where that port came from — Waiting for the PostgreSQL writer at pg-primary.internal:6432/postgres to be ready (from directHost with port 6432 inherited from the pooled endpoint …) — so a wait that never finishes names its own cause. Give directHost its own directPort (or write it as directHost: pg-primary.internal:5432) when the servers differ.

Per-service Postgres endpoints

By default all four Postgres consumers — engine, coordinator, experience-api and openfga — share the endpoint above, each with its own logical database. Any of them can instead point at its own server, with its own credentials:

YAML
postgres: enabled: false host: shared-db.internal # inherited by anything not overridden below auth: username: arcade existingSecret: shared-db-creds engine: database: name: arcade_engine host: engine-db.internal port: 6432 sslmode: verify-full auth: username: arcade_engine existingSecret: engine-db-creds coordinator: database: host: coordinator-db.internal auth: username: arcade_coordinator existingSecret: coordinator-db-creds # experience-api and the coordinator assemble a DSN, so their Secret needs # the password URL-encoded as well as raw. existingSecretURLEncKey: DB_PASSWORD_URLENC

The same keys are available under engine.database, coordinator.database, experienceApi.database and rbac.openfga.database.

KeyRequired?What it changes
<service>.database.hostNoHostname, host:port, or a comma-separated list. Inherits postgres.host.
<service>.database.portNoPort for bare host entries. Inherits postgres.port.
<service>.database.directHostNoInherits postgres.directHost unless host/port relocate the service; '' clears it.
<service>.database.directPortNoInherits postgres.directPort unless host/port relocate the service; '' clears it.
<service>.database.sslmodeNoInherits postgres.sslmode.
<service>.database.sslRootCertNoInherits postgres.sslRootCert. Only experience-api reads it.
<service>.database.targetSessionAttrsNoInherits postgres.targetSessionAttrs.
<service>.database.auth.usernameNoInherits postgres.auth.username.
<service>.database.auth.existingSecretNoReplaces the global Secret outright — no per-key merge. Inherits postgres.auth.existingSecret.
<service>.database.auth.existingSecretKeyNoKey within that Secret. Default DB_PASSWORD.
<service>.database.auth.existingSecretURLEncKeyNoKey holding the URL-encoded password. Default DB_PASSWORD_URLENC.
<service>.database.probeDatabaseNoDatabase the wait-for-db init container connects to. Defaults per the rule below.

Things to know:

  • A per-service host wins over the bundled Postgres, so services can be migrated one at a time.
  • Setting host or port flips create to false, and wait-for-db then probes the service’s own database rather than postgres. A different role or sslmode on the same server does not. Set <service>.database.create: true to opt back in.
  • A direct endpoint describes one server, so host/port also stop the service inheriting postgres.directHost/postgres.directPort — otherwise it would wait for readiness against, and migrate against, the shared primary. Give a relocated service behind its own pooler its own directHost/directPort. Conversely, <service>.database.directHost: '' keeps a service that has not moved on the pooled host/port even when the global block names a direct endpoint.
  • Give openfga a single host. Its entrypoint keeps only the first entry of a comma-separated DB_HOST; rbac.openfga.database.host rejects a list, but one inherited from postgres.host is silently truncated.
  • openfga migrate calls createdb regardless of database.create, so its role needs CREATEDB — or set rbac.openfga.database.migrations: false, which now defaults to true, and migrate out-of-band. With migrations on, wait-for-db probes postgres rather than the openfga database, since that same step creates it.
  • Endpoint values travel as container env, not via a ConfigMap. The migration Jobs are pre-upgrade hooks: Helm renders their spec from the new revision but resolves referenced ConfigMaps against the cluster, i.e. the previous revision. engine.yaml reads ${env:DB_HOST} and friends for the same reason.
  • directHost/directPort reach the engine’s migration Job as --db-direct-host/--db-direct-port arguments instead of through engine.yaml, so a pooled release can adopt a direct endpoint in a single helm upgrade — the hook does not depend on the ConfigMap of the revision it upgrades from.
  • Do not adopt this chart version and move a service’s endpoint in the same upgrade. Upgrading from a version that baked the endpoint into engine.yaml means the pre-upgrade hook still reads those old literals, so the engine’s migration would run against the previous server. Upgrade first, then move the endpoint in a second upgrade. Subsequent moves need no two-step.
  • Per-service credentials require auth.existingSecret; there is no inline password. The release’s app-secrets Secret is mounted wholesale via envFrom by ten workloads, so a password there would reach every service.
  • postgres.caBundle stays global: experience-api honors a single NODE_EXTRA_CA_CERTS, so concatenate multiple CAs into one bundle.

Redis

redis.tls.insecureSkipVerify has no default: with redis.tls.enabled: true the chart refuses to render until it is set. Set false to verify the Redis server certificate, which must be signed by a CA the pods trust. Set true to skip.

KeyRequired?What it changes
redis.enabledNoDeploys the bundled Redis StatefulSet. Set false for external.
redis.hostIf enabled: falseRedis hostname.
redis.portNoRedis port.
redis.architectureNoRedis topology.
redis.image.repository / .tag / .pullPolicyNoBundled Redis image. Default redis:8-alpine. Override to pull from a private registry mirror.
redis.auth.enabledNoEnables Redis AUTH.
redis.auth.passwordIf auth.enabledRedis password.
redis.auth.existingSecretNoName of a Secret to read the Redis password from.
redis.auth.existingSecretKeyNoKey within that Secret. Default REDIS_PASSWORD.
redis.tls.enabledNoEnables TLS to Redis.
redis.tls.existingSecretIf tls.enabledSecret containing Redis TLS material.
redis.tls.certFilename / certKeyFilename / certCAFilenameNoFilenames in the TLS secret.
redis.tls.authClientsNoRequire client certificate authentication.
redis.tls.insecureSkipVerifyIf tls.enabledSkip Redis TLS cert verification. No default; false verifies.
redis.master.persistence.enabledNoEnables persistence on the bundled Redis.
redis.master.persistence.sizeNoPVC size.
redis.master.persistence.storageClassNoStorageClass for the PVC.
redis.master.persistence.existingClaimNoUse a pre-existing PVC.
redis.master.resources.requests / .limitsNoCPU/memory.

Discovery (arcade-discovery subchart)

The optional arcade-discovery subchart adds discovery — Condex, hybrid tool retrieval over RediSearch + Postgres — with its own vendored Redis and Postgres. It is off by default; a default install renders no discovery workloads and leaves the platform Redis and Postgres untouched.

GoEmbed is no longer part of it. arcade-discovery 0.13.0 moved the model servers into arcade-inference below, so a discovery install that needs embeddings enables both and points Condex at the inference release.

KeyRequired?What it changes
discovery.enabledNoRenders the arcade-discovery subchart. Default false.

Configure the subchart itself under the arcade-discovery: key — its full value reference lives in deploy/charts/arcade-discovery/README.md. The chart is fail-closed: opting in requires, at minimum, arcade-discovery.arcade.releaseName (or explicit engine/coordinator URLs), arcade-discovery.condex.catalogSync.secret, and an inference coordinate (arcade-discovery.inference.releaseName, .embeddingModel, .modelRelease). Enabling discovery with no inference endpoint named is refused at render rather than deployed as a Condex that cannot embed.

Inference (arcade-inference subchart)

The optional arcade-inference subchart adds the model servers — GoEmbed (ONNX embeddings, reranking, image embedding and transcription) and, off by default, the LLM proxy. Split out of arcade-discovery in 0.13.0 so they scale, schedule and upgrade on their own cadence: they want GPUs and multi-minute model loads, while Condex wants Redis and Postgres. It is off by default.

KeyRequired?What it changes
inference.enabledNoRenders the arcade-inference subchart. Default false.
arcade-inference.goembed.modelDelivery.releaseIf inference.enabledmlops release id of the model weights — the tag of the OCI models image, or the version segment of the S3 prefix. No default and no public models image, so the chart refuses to render without it.

Configure it under the arcade-inference: key — see deploy/charts/arcade-inference/README.md. It is fail-closed too: a model delivery source and its release must be named, because a GoEmbed with no weights to load is a pod that passes no probe.

mTLS

KeyRequired?What it changes
mtls.enabledNoWires a custom CA into every Arcade service for internal mTLS.
mtls.secretNameIf mtls.enabledName of a pre-existing Secret containing ca.crt, tls.crt, tls.key.

Telemetry

Global defaults live under telemetry.* and apply to every service. Operators can override any field per service by setting <service>.telemetryOverrides.* — the override wins over the global value. The engine, coordinator, experience-api, and workers consume this configuration via dedicated ConfigMaps emitting ARCADE_TELEMETRY_* env vars. All workers share one ConfigMap, so their overrides go under workerDefaults.telemetryOverrides; per-worker differences need workers[].extraEnv.

KeyRequired?What it changes
otelConfig.endpointNoDeprecated — prefer telemetry.otlpEndpoint. Serves as the fallback inside the per-service telemetry helper, and is still set on workers as OTEL_EXPORTER_OTLP_ENDPOINT.
telemetry.logsNoGlobal logs destination — none, stdout, otlp, or stdout+otlp.
telemetry.tracesNoGlobal traces destination — none or otlp.
telemetry.metricsNoGlobal metrics destination — none or otlp.
telemetry.otlpEndpointNoShared OTLP endpoint. Empty falls back to otelConfig.endpoint. Used by any signal whose per-signal override below is empty.
telemetry.otlpEndpoints.logsNoPer-signal endpoint for logs. Empty falls back to telemetry.otlpEndpoint.
telemetry.otlpEndpoints.tracesNoPer-signal endpoint for traces. Empty falls back to telemetry.otlpEndpoint.
telemetry.otlpEndpoints.metricsNoPer-signal endpoint for metrics. Empty falls back to telemetry.otlpEndpoint.
telemetry.logLevelNodebug / info / warn / error.
telemetry.logFormatNojson or text.
telemetry.logMaxBytesNoMax bytes per emitted log line.
<service>.telemetryOverrides.*NoPer-service overrides (any of the telemetry.* keys above). Supported services: engine, coordinator, experienceApi, workerDefaults.
opentelemetry-collector.modeNoCollector deployment mode.
opentelemetry-collector.replicaCountNoCollector replicas.
opentelemetry-collector.image.repository / .tagNoCollector image.
opentelemetry-collector.configNoFull OTLP collector pipeline.
opentelemetry-collector.serviceMonitor.enabledNoServiceMonitor for the collector.

Example — quiet the coordinator while leaving the rest of the stack alone:

YAML
coordinator: telemetryOverrides: logLevel: "warn" traces: "none"

Example — fan signals out to separate collectors (logs to a Loki gateway, traces to a Tempo gateway, metrics still to the in-cluster collector):

YAML
telemetry: otlpEndpoints: logs: "http://loki-gateway:4318" traces: "http://tempo-gateway:4318" # metrics omitted → falls back to telemetry.otlpEndpoint / otelConfig.endpoint

Per-signal endpoints also accept <service>.telemetryOverrides.otlpEndpoints.* when a single service needs to diverge from the global routing.

For any value not listed, see values.yaml.

Last updated on