Console Helm values
Configure the console chart with these Helm values.
This reference lists values declared in the chart's default values.yaml.
Templates can also accept optional settings and inherited global values.
Chart: toolhive-cloud-ui. Chart version: 0.22.0. Generated from the platform
source at e71926418e98c7598815d0abf07039d3c1646f21.
Values
replicaCount
Type: int
Default: 1
Number of replicas for the deployment. Ignored when ha.enabled or autoscaling.enabled is true.
ha
Type: object
Default value
antiAffinityPreset: soft
enabled: false
podDisruptionBudget:
minAvailable: 1
replicaCount: 2
High availability. Bundles replica count, a PodDisruptionBudget, and pod anti-affinity together so they can't drift apart — specifically, so a PDB can never be enabled without enough replicas to back it. A PDB with minAvailable >= the actual replica count blocks every voluntary disruption forever (node drains, cluster upgrades, cluster-autoscaler scale-down all wait on a budget Kubernetes can never satisfy while evicting a pod). The chart refuses to render if ha.enabled is true with fewer than 2 replicas.
ha.enabled
Type: bool
Default: false
Enable HA mode: replicaCount above is ignored in favor of ha.replicaCount, a PodDisruptionBudget is created, and pod anti-affinity spreads replicas across nodes and zones.
ha.replicaCount
Type: int
Default: 2
Replica count used when ha.enabled is true.
ha.podDisruptionBudget.minAvailable
Type: int
Default: 1
Minimum number of pods that must remain available.
ha.antiAffinityPreset
Type: string
Default: "soft"
Pod anti-affinity preset spreading replicas across nodes: "soft" (preferred — schedules even if it can't spread) or "hard" (required — refuses to schedule a replica on a node that already has one). Spreading across zones is always preferred, never required, so a single-zone cluster still schedules every replica.
image.repository
Type: string
Default value
image-proxy.stacklok.com/proxy/stacklok-enterprise/ghcr.io/stacklok/stacklok-enterprise/cloud-ui
Image repository. Enterprise build produced by _release-toolhive-cloud-ui.yml
(Next.js multi-stage build over the source in enterprise/toolhive-cloud-ui/),
then promoted to the platform tag by release.yml. Served to customers via
Replicated's image proxy. Customers running their own mirror override this in
their values file. task version-bump rewrites the trailing :<tag> via a
regex anchored on ghcr.io/stacklok/stacklok-enterprise/<name>: — that anchor
still matches inside this longer proxy URL.
image.tag
Type: string
Default: ""
Image tag (defaults to .Chart.AppVersion when empty, which tracks /VERSION via
task version-bump).
image.pullPolicy
Type: string
Default: "IfNotPresent"
Pull from registry if available, use local image if not
imagePullSecrets
Type: list
Default: []
Extra image pull Secrets to apply to the cloud-ui pod. On Replicated installs,
the SDK injects global.replicated.dockerconfigjson and creates an
enterprise-pull-secret Secret in the release namespace; the
toolhive-cloud-ui.imagePullSecrets helper auto-detects that injection and
merges the SDK secret in front of anything listed here, so customers do NOT need
to add enterprise-pull-secret themselves. Use this list only for additional,
customer-supplied registries.
nameOverride
Type: string
Default: ""
Override the name of the chart
fullnameOverride
Type: string
Default: ""
Override the full name of the resources
serviceAccount.create
Type: bool
Default: false
Specifies whether a service account should be created
serviceAccount.automount
Type: bool
Default: true
Automatically mount a ServiceAccount's API credentials
serviceAccount.annotations
Type: object
Default: {}
Annotations to add to the service account
serviceAccount.name
Type: string
Default: ""
The name of the service account to use (if not set and create is true, a name is generated using the fullname template)
podAnnotations
Type: object
Default: {}
Annotations to add to the pod
podLabels
Type: object
Default: {}
Labels to add to the pod
podSecurityContext
Type: object
Default value
fsGroup: 1001
runAsGroup: 1001
runAsNonRoot: true
runAsUser: 1001
seccompProfile:
type: RuntimeDefault
Security context for the pod
securityContext
Type: object
Default value
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1001
Security context for the container
runtimeWritableDirs
Type: object
Default: {"nextCache":{"sizeLimit":""},"tmp":{"sizeLimit":""}}
emptyDir volumes mounted at /tmp and /app/.next/cache so the container keeps working under the read-only root filesystem above. Next.js's standalone server writes to both at runtime (general tmp usage, and the built-in image optimizer's disk cache for next/image). sizeLimit is a Kubernetes resource-quantity string; empty means unbounded.
service.type
Type: string
Default: "ClusterIP"
Kubernetes service type
service.port
Type: int
Default: 80
Service port
service.targetPort
Type: int
Default: 3000
Container target port
service.nodePort
Type: string
Default: nil
NodePort (only used if type is NodePort, range: 30000-32767)
resources
Type: object
Default:
{"limits":{"cpu":"500m","memory":"512Mi"},"requests":{"cpu":"100m","memory":"128Mi"}}
Resource limits and requests for the container
startupProbe
Type: object
Default value
failureThreshold: 30
httpGet:
path: /
port: http
initialDelaySeconds: 0
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 3
Startup probe configuration (checks if app is ready to start)
livenessProbe
Type: object
Default value
failureThreshold: 3
httpGet:
path: /
port: http
initialDelaySeconds: 0
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
Liveness probe configuration (checks if app is alive)
readinessProbe
Type: object
Default value
failureThreshold: 3
httpGet:
path: /
port: http
initialDelaySeconds: 0
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 3
Readiness probe configuration (checks if app can receive traffic)
autoscaling.enabled
Type: bool
Default: false
Enable Horizontal Pod Autoscaler
autoscaling.minReplicas
Type: int
Default: 1
Minimum number of replicas
autoscaling.maxReplicas
Type: int
Default: 5
Maximum number of replicas
autoscaling.targetCPUUtilizationPercentage
Type: int
Default: 80
Target CPU utilization percentage
volumes
Type: list
Default: []
Additional volumes for the pod
volumeMounts
Type: list
Default: []
Additional volume mounts for the container
nodeSelector
Type: object
Default: {}
Node labels for pod assignment
tolerations
Type: list
Default: []
Tolerations for pod assignment
affinity
Type: object
Default: {}
Affinity rules for pod assignment
networkPolicy
Type: object
Default: {"allowExternalEgress":true,"egress":[],"enabled":false}
NetworkPolicy. Off by default. Turning this on matters most for clusters running a default-deny policy engine (Kyverno's add-network-policy, OPA Gatekeeper): those engines auto-attach a deny-all NetworkPolicy to any pod that has none of its own, so a chart that ships zero NetworkPolicy silently loses whatever traffic that engine decides to block. Shipping our own explicit policy — even a permissive one — means the cluster no longer treats this pod as unmanaged.
networkPolicy.allowExternalEgress
Type: bool
Default: true
Allow all egress traffic. Recommended default: every outbound destination this app calls is a customer-configured URL (apiBaseUrl, global.stacklok.primaryIdp.issuer, enterpriseManagerUrl, gatewayApiUrl, redisUrl / redisUrlExistingSecret) that can point in-cluster or external — this chart has no way to know your actual values at template time, so a fixed allow-list here would be a guess. Set to false to lock egress down to exactly your deployment's destinations via the egress list below.
networkPolicy.egress
Type: list
Default: []
Additional egress rules (Kubernetes NetworkPolicyEgressRule shape), applied when allowExternalEgress is false. Must cover DNS (UDP/TCP 53) plus every destination you've actually configured above — omitting one doesn't fail loudly, the app just can't reach it.
apiBaseUrl
Type: string
Default: ""
Base URL of the Registry Server API. Required.
oidc
Type: object
Default: {"additionalProviders":[]}
OpenID Connect (OIDC) and OAuth configuration. The primary provider's issuer,
client credentials, and scopes come from global.stacklok.primaryIdp, shared
with Enterprise Manager and Connector Gateway. For an IdP served by a private
certificate authority, set global.stacklok.primaryIdp.caBundleRef with exactly
one of secretRef or configMapRef, plus key (default ca.crt). The chart
mounts that certificate bundle and sets NODE_EXTRA_CA_CERTS, extending Node's
default trusted roots. Restart the pods after changing the bundle's contents.
Changing the reference name or key triggers a rollout automatically. The console
permits private IdP addresses.
oidc.additionalProviders
Type: list
Default: []
Additional OIDC providers (opt-in; empty = single-provider mode). Each entry is rendered as OIDC_ADDITIONAL_PROVIDERS (JSON array) in the pod.
betterAuth
Type: object
Default:
{"existingSecret":"","existingSecretKey":"secret","secret":"","url":""}
Better Auth session management
betterAuth.secret
Type: string
Default: ""
Token encryption secret as a plain value, at least 32 characters long. Required
unless existingSecret is set. Prefer a Kubernetes Secret via existingSecret.
Generate a value with openssl rand -base64 32.
betterAuth.existingSecret
Type: string
Default: ""
Name of an existing Secret holding the token encryption secret. Takes precedence over secret above (rendered via secretKeyRef instead of a plaintext env var).
betterAuth.existingSecretKey
Type: string
Default: "secret"
Key within existingSecret holding the token encryption secret.
betterAuth.url
Type: string
Default: ""
Public URL of the console, used for authentication callbacks. Required. Must be externally reachable since the browser uses it during sign-in.
enterpriseManagerUrl
Type: string
Default: ""
Base URL of Enterprise Manager, required for the administration experience. The console uses it for feature flags, configuration, and directory operations. When empty, administration pages fail with "No enterprise-manager API URL configured." There is no fallback URL.
gatewayApiUrl
Type: string
Default: ""
LLM Gateway management API URL — server-to-server endpoint used by the cloud-UI
for budget management, model catalog, etc. (calls /v1/budgets, /v1/models). NOT
shown to end users. When set, takes effect via the GATEWAY_API_URL env var. May
also be served by the config server's gateway.api_url directive; when both are
set, the config-server value wins. Required (here or via the config server) for
the "My Usage" page. NOTE: do not also set any of the vars below via .Values.env
— the typed blocks emit before the env[] passthrough and produce a duplicate env
entry.
gatewayProxyUrl
Type: string
Default: ""
User-facing LLM Gateway proxy URL — the public proxy endpoint baked into the
thv llm setup --gateway-url <url> command and shown in the "My Usage"
connection banner. Typically distinct from gatewayApiUrl above. When set, takes
effect via the GATEWAY_PROXY_URL env var. May also be served by the config
server's gateway.proxy_url directive; when both are set, the config-server
value wins.
connectorGatewayUrl
Type: string
Default: ""
Base URL of the per-user Connector Gateway control-plane API (the
/v1/users/me/gateway/... endpoints the "Connectors" pages call). When set,
takes effect via the CONNECTOR_GATEWAY_API_URL env var; the nav entry +
/tools/connectors*//neo/setup* routes are hidden while it is unset. Setting
this alone is no longer sufficient to turn the feature on: those surfaces also
require the connector-gateway install toggle
(global.stacklok.connectorGateway.enabled at Helm render time, mirrored into the
mounted AppConfig) to resolve true.
Address the CONTROL-PLANE Service, not the data-plane one: connector-gateway
serves this API on its own port behind <fullname>-control-plane
(controlPlane.port, default 8090) — e.g.
http://<release>-connector-gateway-control-plane.<namespace>:8090.
The data-plane Service (<fullname>, port 8443) serves /gw/mcp and will not
answer these routes.
Unlike its sibling URL values above, this one is tpl-EVALUATED before it
reaches the env var (deployment.yaml). That is what lets the umbrella chart hand
this subchart a template string deriving the address from
global.stacklok.connectorGateway.enabled — the component's own install toggle
— rather than requiring an operator to set the same fact twice and get it
silently wrong in either direction. A literal URL has no template actions and
passes through unchanged, so nothing about setting this by hand changes.
Standalone default stays empty: with no umbrella above it, no safe cross-chart default exists (Service name/namespace and control-plane port are deployment-specific), and an empty value keeps the feature hidden rather than pointing the UI at a Service that may not exist.
thvCliOidcIssuerUrl
Type: string
Default: ""
OIDC issuer URL used by the console's Stacklok CLI setup instructions. Set this and thvCliOidcClientId to enable the setup wizard.
thvCliOidcClientId
Type: string
Default: ""
Public OAuth client ID used by the Stacklok CLI with PKCE. Set this and thvCliOidcIssuerUrl to enable the console's setup wizard.
thvCliOidcAudience
Type: string
Default: ""
Optional OAuth audience included in the CLI setup command. Set it when the LLM gateway requires a specific JWT audience; empty omits the option.
thvCliOidcCallbackPort
Type: string
Default: ""
Local OAuth callback port included in the CLI setup command. Set it to match the redirect URI registered with your IdP; empty uses the CLI default of 8666.
redisUrl
Type: string
Default: ""
Optional Redis connection URL for server-side caching (currently used to cache SKILL.md previews pulled from OCI artifacts). External Redis only — the chart does not deploy a Redis instance. The SKILL.md preview is Redis-gated: when unset (or when Redis is unreachable) the cloud-ui hides the preview entirely rather than re-pulling on every request. Example: "redis://:password@redis.example.com:6379/0"
The URL embeds the Redis password. Prefer redisUrlExistingSecret below, which keeps the whole connection string (and its embedded credential) out of the rendered pod spec / Helm release object; redisUrl is kept for backward compatibility with existing installs that already set it directly.
redisUrlExistingSecret
Type: string
Default: ""
Name of an existing Secret holding the full Redis connection URL. Takes precedence over redisUrl above (rendered via secretKeyRef instead of a plaintext env var).
redisUrlExistingSecretKey
Type: string
Default: "redis-url"
Key within redisUrlExistingSecret holding the connection URL.
branding
Type: object
Default:
{"config":{"enabled":false,"json":{}},"faviconUrl":"","logoUrl":"","name":""}
Branding. Prefer the file-based config block below — it carries the app name,
logo, favicon, and design tokens together as one payload. The legacy
name/logoUrl/faviconUrl fields are also supported (they wire directly to
env vars and skip the ConfigMap mount), useful for quick one-off overrides; when
both are set, values from config.json win.
branding.config
Type: object
Default: {"enabled":false,"json":{}}
File-based branding configuration mounted at /etc/branding/config.json and
read by the console on each request. Set config.json to a branding object with
app_name, logo_url, favicon_url, and design_tokens.
branding.name
Type: string
Default: ""
Simple-override path (no ConfigMap required). Wires to BRAND_NAME,
BRAND_LOGO_URL, FAVICON_URL env vars. Overridden by config.json when both are
present.
env
Type: list
Default: []
Additional env vars (escape hatch for experimental/uncommitted config). Prefer structured keys above when available.
envFrom
Type: list
Default: []
Environment variables from ConfigMaps or Secrets