Skip to main content

Configure the Enterprise Cloud UI

The Enterprise Cloud UI runs as a Next.js application in your Kubernetes cluster. It ships in the Stacklok Enterprise platform chart, the umbrella chart that installs the platform.

Deploy the platform first

Install the Cloud UI with the platform chart, which deploys it alongside the other components. To run it in its own cluster, enable only this component as described in Distributed deployments.

You enable the component with its cloudUi.enabled flag and set its configuration under the toolhive-cloud-ui key in your platform values.yaml.

Prerequisites

Before configuring, ensure you have:

  • A Registry Server deployed and reachable; its API URL is the apiBaseUrl value you set below
  • An OIDC-compatible identity provider (Okta, Entra ID, or generic OIDC) configured with a client application for the Cloud UI
  • An OpenRouter API key, if you want to enable the AI assistant
  • Enterprise Cloud UI distribution access (container image and Helm chart, provided by Stacklok during onboarding)

Configuration values

Enable the Cloud UI and set its configuration:

values.yaml
# Enable the Cloud UI.
cloudUi:
enabled: true

# Cloud UI configuration.
toolhive-cloud-ui:
# Required: Registry Server API URL
apiBaseUrl: 'https://registry.example.com'

# Required: OIDC configuration
oidc:
issuerUrl: 'https://idp.example.com'
clientId: '<CLIENT_ID>'
clientSecret: '<CLIENT_SECRET>'
# scopes: 'openid,email,profile,offline_access'

# Required: Better Auth session management
# Generate secret with: openssl rand -base64 32
betterAuth:
secret: '<BETTER_AUTH_SECRET>'
url: 'https://cloud-ui.example.com'

# Optional: Enterprise Manager for server-side enterprise config
# enterpriseManagerUrl: 'https://enterprise-manager.example.com'

# Optional: external Redis for caching skill previews.
# redisUrl: 'redis://:<PASSWORD>@redis.example.com:6379/0'

# Optional: White-label branding (see "White-label branding" below)
# branding:
# config:
# enabled: true
# json:
# logo_url: 'https://cdn.example.com/acme/logo.svg'
# favicon_url: 'https://cdn.example.com/acme/favicon.ico'
# design_tokens:
# colors:
# light: { primary: '#7a1a1a' }
# dark: { primary: '#b04545' }
# # Simple-override branding (bypasses ConfigMap mount).
# # Overridden by `branding.config.json` when both are set.
# name: 'Acme'
# logoUrl: 'https://cdn.example.com/acme/logo.svg'
# faviconUrl: 'https://cdn.example.com/acme/favicon.ico'

# Additional env vars not yet exposed as structured keys above.
# env:
# - name: OPENROUTER_API_KEY
# value: '<OPENROUTER_API_KEY>'

Environment variables

The Helm keys in the tables below are relative to the Cloud UI's values. In the platform chart, nest them under the toolhive-cloud-ui key (for example, toolhive-cloud-ui.apiBaseUrl). Each maps to the environment variable the Cloud UI container reads.

note

API_BASE_URL and ENTERPRISE_MANAGER_URL can use in-cluster Service DNS because the Cloud UI backend calls them server-side. BETTER_AUTH_URL and OIDC_ISSUER_URL must be externally reachable URLs because the browser uses them during the sign-in flow.

Required

Helm keyEnv varDescription
apiBaseUrlAPI_BASE_URLBase URL of the Registry Server API (see Registry API URL resolution)
oidc.issuerUrlOIDC_ISSUER_URLOIDC issuer/discovery URL for your identity provider
oidc.clientIdOIDC_CLIENT_IDOAuth2 client ID
oidc.clientSecretOIDC_CLIENT_SECRETOAuth2 client secret
betterAuth.secretBETTER_AUTH_SECRETToken encryption secret (min 32 chars, generate with openssl rand -base64 32)
betterAuth.urlBETTER_AUTH_URLPublic URL of the Cloud UI (used for auth callbacks)

Optional (structured)

Helm keyEnv varDescription
oidc.scopesOIDC_SCOPESComma-separated OIDC scopes. Overrides the defaults: openid,email,profile,offline_access. If set, include at least openid and offline_access to avoid breaking authentication and session refresh.
enterpriseManagerUrlENTERPRISE_MANAGER_URLEnterprise Manager URL the Cloud UI server reads enterprise config from (feature-flag gating, plus registry and gateway URLs that override the env-var fallbacks). Server-side only, so this can be in-cluster Service DNS. When unset, the Cloud UI falls back to the env vars for those URLs.
redisUrlREDIS_URLExternal Redis connection URL. The Cloud UI caches unpacked skill previews so it doesn't re-fetch each skill's OCI artifact on every view. The chart does not deploy Redis; when unset or unreachable, previews are hidden rather than re-pulled.
branding.config.enabledBRANDING_CONFIG_PATHEnable file-based white-label branding. See White-label branding.
branding.config.json(none)JSON payload with logo_url, favicon_url, and design_tokens.colors. See White-label branding.
branding.nameBRAND_NAMESimple-override app name. Bypasses the ConfigMap mount. Overridden by branding.config.json when both are set.
branding.logoUrlBRAND_LOGO_URLSimple-override logo URL. Bypasses the ConfigMap mount.
branding.faviconUrlFAVICON_URLSimple-override favicon URL. Bypasses the ConfigMap mount.

Optional (additional env vars)

Use the env array in values.yaml for env vars not exposed as structured keys:

Env varDescription
OPENROUTER_API_KEYOpenRouter API key for the AI assistant
TRUSTED_ORIGINSComma-separated list of trusted origins for CORS and auth callbacks
DATABASE_URLPostgreSQL connection string for session storage (required for large OIDC tokens, for example, with Entra ID)

White-label branding

Replace the Cloud UI's default logo, favicon, and theme colors with your organization's branding so the application matches your internal visual identity.

The Helm chart delivers branding as a JSON file mounted into the Cloud UI container. It writes the contents of branding.config.json into a ConfigMap, mounts it at /etc/branding/config.json, and sets BRANDING_CONFIG_PATH to point at it. Enable the branding.config block in your values.yaml:

values.yaml
branding:
config:
enabled: true
json:
logo_url: 'https://cdn.example.com/acme/logo.svg'
favicon_url: 'https://cdn.example.com/acme/favicon.ico'
design_tokens:
colors:
light:
primary: '#7a1a1a'
nav-background: '#1a1a2e'
dark:
primary: '#b04545'
nav-background: '#0d0d1a'

Changes to branding.config.json propagate to running pods automatically. The kubelet refreshes the mounted file shortly after the ConfigMap update, without a pod rollout. See Mounted ConfigMaps are updated automatically in the Kubernetes documentation for the underlying behavior.

Fields

All fields are optional. Omitted fields fall back to the Cloud UI's defaults.

FieldDescription
logo_urlURL of the logo image (SVG, PNG, or WebP). Shown on the login screen and in the top navigation bar.
favicon_urlURL of the favicon (ICO, PNG, or SVG).
design_tokens.colorsLight and dark theme color tokens (see below).
app_nameUsed as the logo's alt text. Does not rename the application elsewhere in the UI. Falls back to the BRAND_NAME environment variable, then to ToolHive.

Simple overrides

For quick name and logo changes without a ConfigMap, set branding.name, branding.logoUrl, and branding.faviconUrl directly in values.yaml:

values.yaml
branding:
name: 'Acme'
logoUrl: 'https://cdn.example.com/acme/logo.svg'
faviconUrl: 'https://cdn.example.com/acme/favicon.ico'

These wire directly to env vars and skip the ConfigMap mount entirely. If you also set branding.config.json, the config file takes precedence.

Color tokens

Set CSS color values under design_tokens.colors.light and design_tokens.colors.dark to override the Cloud UI's defaults for each theme.

TokenControls
backgroundPage background
foregroundPrimary text color
cardCard background
card-foregroundCard text
popoverPopover and dropdown menu background
popover-foregroundPopover and dropdown menu text
primaryPrimary button background
primary-foregroundText on primary buttons
secondarySecondary button background
secondary-foregroundText on secondary buttons
mutedMuted surfaces (subtle backgrounds)
muted-foregroundLow-emphasis text (labels, captions)
accentHover and highlight background
accent-foregroundText on accent surfaces
destructiveDestructive action background (errors, delete)
destructive-foregroundText on destructive surfaces
borderDefault border color
inputForm input background
ringFocus ring color
avatar-backgroundUser avatar fallback background
nav-backgroundTop navigation bar background
nav-borderTop navigation bar border
nav-button-active-bgActive top-nav button background
nav-button-active-textActive top-nav button text
successSuccess indicator color
warningWarning indicator color
sidebarSidebar background
sidebar-foregroundSidebar text
sidebar-primarySidebar primary highlight background
sidebar-primary-foregroundText on sidebar primary highlights
sidebar-accentSidebar hover background
sidebar-accent-foregroundSidebar hover text
sidebar-borderSidebar border
sidebar-ringSidebar focus ring

Any CSS color value is accepted, for example:

  • Hex: #7a1a1a
  • RGB: rgb(122 26 26)
  • HSL: hsl(0 65% 29%)

Asset hosting

The Cloud UI fetches logo_url and favicon_url server-side and serves them to browsers itself. The URLs only need to be reachable from the Cloud UI's deployment, not publicly. You can host your assets on an internal CDN or behind your firewall.

The logo_url and favicon_url must start with http:// or https://. URLs with any other scheme are rejected and the Cloud UI uses its default logo or favicon instead. Using http:// for an internal CDN is safe: the Cloud UI fetches the images itself and re-serves them through its own origin, so the browser always loads them over the same protocol it uses to access the Cloud UI (typically HTTPS).

Registry API URL resolution

The Cloud UI resolves the Registry Server API URL dynamically:

  1. If an Enterprise Manager is configured and the registry policy has an api_url value, the Cloud UI uses that URL.
  2. Otherwise, the Cloud UI falls back to the API_BASE_URL environment variable.

This means you can omit API_BASE_URL entirely and let the Enterprise Manager control the registry URL, or set API_BASE_URL as a fallback for when the Enterprise Manager is unreachable.

Feature flags

The Enterprise Manager controls Cloud UI feature visibility via the assistant directive. To hide the AI assistant for all users, set it in the Enterprise Manager's section of your platform values.yaml:

values.yaml
enterprise-manager:
enterpriseConfig:
assistant:
value: false
enforcement: 'enforced'

Next steps