Deploy Multica, the open-source managed agents platform, on Kubernetes.
Current upstream multica-web images resolve their API and documentation URLs from runtime environment variables. The chart sets REMOTE_API_URL to the release backend Service by default and exposes frontend.config.* for explicit URLs. It also keeps a compatibility Service named backend enabled by default for legacy images; because that Service name is intentionally unprefixed, run only one Multica release per namespace unless you disable the alias.
If you build a custom frontend image and do not need the legacy alias, disable it:
frontend:
backendServiceAlias:
enabled: false
JWT_SECREThelm repo add icoretech https://icoretech.github.io/helm
helm repo update
helm upgrade --install multica icoretech/multica \
-n multica --create-namespace \
--set backend.config.jwtSecret="replace-with-a-strong-secret-at-least-32-characters"
OCI:
helm upgrade --install multica oci://ghcr.io/icoretech/charts/multica \
-n multica --create-namespace \
--set backend.config.jwtSecret="replace-with-a-strong-secret-at-least-32-characters"
For production, prefer external PostgreSQL and S3-compatible uploads:
postgres:
enabled: false
database:
external:
enabled: true
# Required by the wait-for-Postgres init container when DATABASE_URL comes from a Secret.
host: postgres.example.com
urlFrom:
secretKeyRef:
name: multica-db
key: DATABASE_URL
backend:
config:
frontendOrigin: https://multica.example.com
publicUrl: https://multica.example.com
jwtSecretRef:
name: multica-auth
key: JWT_SECRET
email:
resendApiKeyRef:
name: multica-email
key: RESEND_API_KEY
resendFromEmail: noreply@example.com
smtp:
host: smtp.example.com
port: 587
# Use implicit for SMTPS/465, or leave empty for STARTTLS when advertised.
tls: starttls
# Set a real FQDN when strict public relays reject the container hostname.
ehloName: mail.example.com
usernameRef:
name: multica-smtp
key: SMTP_USERNAME
passwordRef:
name: multica-smtp
key: SMTP_PASSWORD
storage:
local:
persistence:
enabled: false
s3:
bucket: multica-uploads
region: eu-west-1
redis:
enabled: true
persistence:
size: 8Gi
When using the chart-managed Ingress or HTTPRoute, backend-owned paths such as /health, /api, /auth, /uploads, and /ws are routed directly to the backend Service by default. This is required by multica setup self-host, which probes <server-url>/health. If you manage Traefik IngressRoute, nginx snippets, or another external router outside the chart, mirror the same path split.
When using S3-compatible storage without storage.s3.cloudfrontDomain, Multica stores reader-facing URLs using the configured bucket endpoint. Configure the bucket with public s3:GetObject access for uploaded objects, set storage.s3.cloudfrontDomain with CloudFront signing support, or use storage.attachments.downloadMode=proxy when browsers and CLI clients cannot reach a private S3-compatible endpoint directly.
The backend startup probe gives cold installs time to wait for PostgreSQL and run migrations before liveness starts. Readiness uses /readyz, which checks PostgreSQL connectivity and the latest server migration. Liveness stays on /health, which only confirms the process is alive.
Backend pod annotations include a checksum of referenced Kubernetes Secret data so out-of-band rotations of jwtSecretRef, database or read-replica URL, email, OAuth, Redis, GitHub, Lark, and S3 secrets roll the Deployment on the next helm upgrade. helm template and dry-run renders cannot read live Secrets, so they emit a stable placeholder checksum.
Leave database.pool.maxConns and database.pool.minConns empty unless you explicitly want DATABASE_MAX_CONNS / DATABASE_MIN_CONNS env vars to override Multica’s own defaults and any pool_max_conns / pool_min_conns query parameters already embedded in DATABASE_URL. backend.config.databaseSearchWorkMemMB (default 64) sets the transaction-local PostgreSQL work_mem ceiling for search queries; set 0 to keep the database/session default, or 1-64 to lower it on memory-constrained databases.
Set database.replica.url (or database.replica.urlFrom.secretKeyRef) to enable the optional PostgreSQL read replica. Every replica connection is forced read-only and recycled after 5 minutes, replica failures fall back to the primary, and database.replica.maxConns / database.replica.minConns size its pool independently of the primary (Multica defaults are 10 / 0).
Set backend.config.maintenancePort to expose Multica’s container-loopback maintenance API. The listener binds 127.0.0.1 only and has no application authentication; run the packaged /app/maintenance client through kubectl exec to drive resumable backfills such as the issue-status category migration. Never publish this port through a Service, Ingress, HTTPRoute, or host port.
The chart disables PostHog product analytics by default via backend.config.analyticsDisabled. Multica also sends one first-party anonymous self-host telemetry snapshot per UTC day; set backend.config.doNotTrack to "1" or "true" to opt out of telemetry collection and delivery.
Set backend.config.metricsAddr to enable Multica’s Prometheus metrics listener. If your cluster has the Prometheus Operator CRD installed, monitoring.prometheusRule.enabled=true adds alert rules for business sampler query failures and high query latency; it is disabled by default so minimal clusters without the CRD still render and install.
Signup restrictions only apply to first-time signup. Existing users can always sign in again. To restrict first-time signup to explicit addresses or domains, keep backend.config.allowSignup=true and set backend.config.allowedEmails or backend.config.allowedEmailDomains. Setting backend.config.allowSignup=false blocks every new signup even when an email allowlist is present.
Set backend.config.disableWorkspaceCreation=true after bootstrapping the shared workspace when self-hosted users should only join by invitation. This maps to upstream DISABLE_WORKSPACE_CREATION and makes workspace creation fail for every caller.
Set backend.config.authTokenTtl only when you need to override Multica’s default auth token lifetime. Behind a reverse proxy, configure backend.rateLimits.auth.trustedProxies for the public auth limiter and backend.config.trustedProxies for the autopilot webhook limiter so upstream rate limits see real client IPs instead of only the proxy address.
Email delivery can use Resend or an SMTP relay. SMTP is enabled when backend.email.smtp.host is set, and upstream Multica checks SMTP_HOST before Resend, so SMTP takes priority when both are configured. Port 465 is supported for implicit TLS; set backend.email.smtp.tls=implicit for non-standard SMTPS ports. For strict relays such as Google Workspace, set backend.email.smtp.ehloName to the FQDN the relay accepts. For production SMTP auth, prefer backend.email.smtp.passwordRef instead of inline backend.email.smtp.password.
GitHub App integration needs the app slug and webhook secret. Optionally set backend.github.appId with backend.github.appPrivateKeyRef so Multica can enrich the connected account name immediately after install. Store secrets in an existing Kubernetes Secret:
backend:
github:
appSlug: multica-example
webhookSecretRef:
name: multica-github
key: GITHUB_WEBHOOK_SECRET
appId: "123456"
appPrivateKeyRef:
name: multica-github
key: GITHUB_APP_PRIVATE_KEY
Lark/Feishu Bot integration is disabled until backend.lark.secretKey or backend.lark.secretKeyRef is set. Use a base64-encoded 32-byte key, for example openssl rand -base64 32. International Lark tenants should set both backend.lark.httpBaseUrl and backend.lark.callbackBaseUrl to https://open.larksuite.com; backend.config.publicUrl must point at the public API origin used by Lark binding prompts. Set backend.lark.wsProxyUrl only when Lark WebSocket long-connection handshakes must go through a fixed HTTP CONNECT proxy instead of the standard pod HTTP_PROXY / HTTPS_PROXY / NO_PROXY environment.
backend:
config:
publicUrl: https://multica.example.com
lark:
secretKeyRef:
name: multica-lark
key: MULTICA_LARK_SECRET_KEY
httpBaseUrl: https://open.larksuite.com
callbackBaseUrl: https://open.larksuite.com
Slack integration is disabled until backend.slack.secretKey or backend.slack.secretKeyRef is set. Use a separate base64-encoded 32-byte key from the Lark key; Multica uses it to decrypt Slack bot/app tokens stored in channel installation rows.
backend:
slack:
secretKeyRef:
name: multica-slack
key: MULTICA_SLACK_SECRET_KEY
Feature flags are optional. Leave backend.featureFlags.rules and backend.featureFlags.existingConfigMap.name empty to use upstream defaults plus any FF_* overrides from backend.extraEnv. To ship file-backed rules, either provide inline rules and let the chart render a ConfigMap, or mount an existing ConfigMap; the chart exports MULTICA_FEATURE_FLAGS_FILE only when it also mounts the file.
backend:
featureFlags:
rules:
runtime_brief_slim:
default: true
Multica runs rollup_task_usage_hourly() in-process on every backend replica through its DB-backed scheduler (sys_cron_executions), so a fresh install needs no external rollup scheduler. usageRollups.cronJob.enabled therefore defaults to false; it remains only as a compatibility path for backend images older than v0.3.5 or when the in-process scheduler is unavailable. The SQL function holds advisory lock 4246, so the CronJob and the in-process scheduler can coexist without double-writing if you enable both:
usageRollups:
cronJob:
enabled: true
Redis-backed features — realtime fanout, channel WebSocket leases, rate limits, and token caches — share the single realtime.redisUrl (REDIS_URL) connection. For native Redis Cluster or ElastiCache Serverless endpoints, set realtime.redisClusterMode=true with a database-0 URL; cluster mode rejects the legacy and dual relay modes, so pair it with realtime.relay.mode=stream when you tune the relay.
For upgrades, migrations.preUpgradeJob.enabled runs the backend image as a Helm pre-upgrade hook before the Deployment rolls. It first runs ./migrate up; if Multica refuses to drop legacy daily rollups because task_usage_hourly has not been seeded yet, the hook runs ./backfill_task_usage_hourly and retries ./migrate up. This matches the upstream v0.3.5 self-host upgrade order while keeping the regular backend entrypoint unchanged.
Chart 0.5.0 tracks Multica v0.5.0. Upstream consolidated every Redis feature onto REDIS_URL, removed the dedicated REALTIME_RELAY_REDIS_URL and CHANNEL_WS_LEASE_REDIS_URL variables, and dropped the legacy daily/dashboard rollup read-path flags. The chart fails loudly instead of silently ignoring the removed keys:
realtime.relay.redisUrl / realtime.relay.redisUrlRef with realtime.redisUrl / realtime.redisUrlRef.channelLeases.redisUrl / channelLeases.redisUrlRef with realtime.redisUrl / realtime.redisUrlRef.backend.usageRollups.dailyEnabled and backend.usageRollups.dashboardEnabled; the legacy tables were dropped upstream.usageRollups.cronJob override you no longer need; the default flipped to false because the backend schedules the rollup itself.This chart deploys the Multica server layer only: backend, frontend, database wiring, and upload storage. Agent execution still happens through Multica daemons running on separate machines where Codex, Claude Code, OpenCode, or another supported coding tool is installed.
Daemon-only environment variables don’t belong in this server-layer chart. Keep values such as MULTICA_CLAUDE_ARGS, MULTICA_CODEX_ARGS, and MULTICA_TASK_SLOT on daemon hosts or daemon workloads, not in backend or frontend pod configuration.
| Key | Type | Default | Description |
|---|---|---|---|
| backend.affinity | object | {} |
Backend affinity. |
| backend.autoscaling.enabled | bool | false |
Enable backend HPA. |
| backend.autoscaling.maxReplicas | int | 5 |
Maximum backend replicas. |
| backend.autoscaling.minReplicas | int | 1 |
Minimum backend replicas. |
| backend.autoscaling.targetCPUUtilizationPercentage | int | 80 |
Target CPU utilization percentage. |
| backend.autoscaling.targetMemoryUtilizationPercentage | string | nil |
Target memory utilization percentage. |
| backend.composio.apiKey | string | "" |
Composio API key. Prefer apiKeyRef in production. |
| backend.composio.apiKeyRef.key | string | "" |
Secret key for COMPOSIO_API_KEY. |
| backend.composio.apiKeyRef.name | string | "" |
Existing secret containing COMPOSIO_API_KEY. |
| backend.composio.callbackBaseUrl | string | "" |
Public callback base URL for Composio OAuth flows. |
| backend.composio.stateSecret | string | "" |
Composio state-signing secret. Prefer stateSecretRef in production. |
| backend.composio.stateSecretRef.key | string | "" |
Secret key for COMPOSIO_STATE_SECRET. |
| backend.composio.stateSecretRef.name | string | "" |
Existing secret containing COMPOSIO_STATE_SECRET. |
| backend.config.allowSignup | bool | true |
Signup master switch. Keep true when using allowedEmails or allowedEmailDomains; set false only to block all first-time signup. |
| backend.config.allowedEmailDomains | string | "" |
First-time signup domain allowlist, comma-separated. Existing users can still sign in even if their domain is removed from the allowlist. |
| backend.config.allowedEmails | string | "" |
Explicit first-time signup email allowlist, comma-separated. Existing users can still sign in even if removed from the allowlist. |
| backend.config.allowedOrigins | string | "" |
Additional WebSocket origins, comma-separated. |
| backend.config.analyticsDisabled | bool | true |
Disable backend/frontend analytics. Defaults to true for self-host privacy. |
| backend.config.analyticsEnvironment | string | "" |
Optional PostHog environment property override. Empty lets Multica derive it from APP_ENV. |
| backend.config.appEnv | string | "production" |
Runtime environment. Keep production on public deployments. |
| backend.config.appUrl | string | "" |
User-reachable web URL used by CLI sign-in and account links. Empty defaults to frontendOrigin. |
| backend.config.authTokenTtl | string | "" |
Optional AUTH_TOKEN_TTL override. Empty uses Multica’s default auth token lifetime. |
| backend.config.cloud.url | string | "" |
Public Multica Cloud URL used for cloud-linked flows. Empty disables the cloud link. |
| backend.config.cookieDomain | string | "" |
Optional cookie Domain attribute. Leave empty for single-host deployments. |
| backend.config.corsAllowedOrigins | string | "" |
Additional CORS origins, comma-separated. |
| backend.config.daemonServerUrl | string | "" |
URL used by the backend to reach the daemon control API. Empty keeps the server default. |
| backend.config.databaseConnectTimeout | string | "5s" |
Optional database connection timeout, e.g. 5s. Empty uses Multica’s default. |
| backend.config.databaseSearchWorkMemMB | int | 64 |
PostgreSQL work_mem ceiling in MB for search transactions. Set 1-64 to lower it for memory-constrained databases, or 0 to keep the database/session default. Values above 64 fall back to 64 with a warning at startup. |
| backend.config.databaseStartupTimeout | string | "3m" |
Optional database startup timeout, e.g. 3m. Empty uses Multica’s default. |
| backend.config.devVerificationCode | string | "" |
Fixed local test verification code. Keep empty in production. |
| backend.config.disableWorkspaceCreation | bool | false |
Disable workspace creation globally. Bootstrap the shared workspace with this false, then set true so users can only join by invitation. |
| backend.config.doNotTrack | string | "" |
Disable first-party anonymous self-host telemetry. The backend sends one deployment-level snapshot per UTC day to https://telemetry.multica.ai; set to "1" or "true" to opt out, or leave empty for Multica’s default-on behavior. Separate from backend.config.analyticsDisabled (PostHog product analytics). |
| backend.config.frontendOrigin | string | "http://localhost:3000" |
Public frontend origin. Required for production links, cookies, CORS, and WebSocket origin checks. |
| backend.config.jwtSecret | string | "change-me-in-production" |
JWT signing secret. Replace in production or use jwtSecretRef. |
| backend.config.jwtSecretRef.key | string | "" |
Secret key for JWT_SECRET. |
| backend.config.jwtSecretRef.name | string | "" |
Existing secret containing JWT_SECRET. |
| backend.config.maintenancePort | string | "" |
Optional container-loopback maintenance API port, e.g. 6061. Empty disables it. The listener always binds 127.0.0.1 and exposes /maintenance/* with no application authentication for the packaged /app/maintenance CLI (run via kubectl exec). Never publish it through a Service, Ingress, HTTPRoute, or host port. |
| backend.config.metricsAddr | string | "" |
Prometheus metrics listener, e.g. 127.0.0.1:9090. Empty disables it. |
| backend.config.port | int | 8080 |
Backend bind port. |
| backend.config.posthogApiKey | string | "" |
PostHog API key when analytics are enabled. |
| backend.config.posthogHost | string | "https://us.i.posthog.com" |
|
| backend.config.publicUrl | string | "" |
Public API URL without a trailing slash. Empty defaults to frontendOrigin, which matches the chart-managed same-origin routes. |
| backend.config.realtimeMetricsToken | string | "" |
Token required to expose /health/realtime through a proxy. |
| backend.config.realtimeMetricsTokenRef.key | string | "" |
Secret key for REALTIME_METRICS_TOKEN. |
| backend.config.realtimeMetricsTokenRef.name | string | "" |
Existing secret containing REALTIME_METRICS_TOKEN. |
| backend.config.runtimeReconnectGrace | string | "" |
Optional runtime reconnect grace period, e.g. 3h. Empty uses Multica’s default. |
| backend.config.shutdownHoldDuration | string | "" |
Optional graceful shutdown hold duration. Keep terminationGracePeriodSeconds larger than this value. |
| backend.config.trustedProxies | string | "" |
Comma-separated CIDRs whose X-Forwarded-For/X-Real-IP headers are trusted by Multica’s autopilot webhook limiter. |
| backend.config.vcsIntegrationEnabled | bool | false |
Enable self-hosted VCS integration. Requires vcs.secretKey or vcs.secretKeyRef. |
| backend.deployment.progressDeadlineSeconds | int | 600 |
Time in seconds for the Deployment controller to wait before marking a rollout failed. |
| backend.deployment.strategy.type | string | "Recreate" |
Deployment strategy. Recreate avoids RWO upload PVC multi-attach deadlocks. |
| backend.deployment.terminationGracePeriodSeconds | int | 30 |
Seconds Kubernetes allows the backend to shut down before sending SIGKILL. Set higher than shutdownHoldDuration when draining runtimes. |
| backend.dingtalk.secretKey | string | "" |
Base64-encoded 32-byte key enabling DingTalk integration. Prefer secretKeyRef in production. |
| backend.dingtalk.secretKeyRef.key | string | "" |
Secret key for MULTICA_DINGTALK_SECRET_KEY. |
| backend.dingtalk.secretKeyRef.name | string | "" |
Existing secret containing MULTICA_DINGTALK_SECRET_KEY. |
| backend.email.resendApiKey | string | "" |
Resend API key. When empty, Multica prints verification codes to stdout. |
| backend.email.resendApiKeyRef.key | string | "" |
Secret key for RESEND_API_KEY. |
| backend.email.resendApiKeyRef.name | string | "" |
Existing secret containing RESEND_API_KEY. |
| backend.email.resendFromEmail | string | "noreply@multica.ai" |
Sender address for verification emails. |
| backend.email.smtp.ehloName | string | "" |
EHLO/HELO hostname announced to strict SMTP relays. Empty lets Multica use the backend container hostname. |
| backend.email.smtp.fromEmail | string | "" |
Optional sender address used by the SMTP transport. |
| backend.email.smtp.host | string | "" |
SMTP relay host. When empty, Multica uses Resend or stdout fallback. |
| backend.email.smtp.password | string | "" |
Optional SMTP auth password. |
| backend.email.smtp.passwordRef.key | string | "" |
Secret key for SMTP_PASSWORD. |
| backend.email.smtp.passwordRef.name | string | "" |
Existing secret containing SMTP_PASSWORD. |
| backend.email.smtp.port | int | 25 |
SMTP relay port. Port 465 auto-enables implicit TLS unless smtp.tls overrides the mode. |
| backend.email.smtp.tls | string | "" |
SMTP TLS mode. Empty/starttls uses STARTTLS when advertised; implicit/smtps/ssl starts TLS immediately. |
| backend.email.smtp.tlsInsecure | bool | false |
Skip TLS certificate verification for SMTP STARTTLS. |
| backend.email.smtp.username | string | "" |
Optional SMTP auth username. |
| backend.email.smtp.usernameRef.key | string | "" |
Secret key for SMTP_USERNAME. |
| backend.email.smtp.usernameRef.name | string | "" |
Existing secret containing SMTP_USERNAME. |
| backend.envFrom | list | [] |
Extra backend envFrom refs. |
| backend.extraEnv | list | [] |
Extra backend env vars. Managed env names are rejected to avoid silent overrides. |
| backend.featureFlags.existingConfigMap.key | string | "feature-flags.yaml" |
ConfigMap key containing feature flag YAML. |
| backend.featureFlags.existingConfigMap.name | string | "" |
Existing ConfigMap containing the feature flag YAML file. |
| backend.featureFlags.mountPath | string | "/etc/multica/feature-flags.yaml" |
Absolute file path mounted into the backend container and exported as MULTICA_FEATURE_FLAGS_FILE. |
| backend.featureFlags.rules | object | {} |
Inline Multica feature flag rules rendered to a ConfigMap and loaded from MULTICA_FEATURE_FLAGS_FILE. Leave empty to use upstream defaults plus any FF_* env overrides. |
| backend.github.appId | string | "" |
Optional GitHub App ID used to enrich connected account names after install. |
| backend.github.appPrivateKey | string | "" |
Optional GitHub App private key PEM. Prefer appPrivateKeyRef for production deployments. |
| backend.github.appPrivateKeyRef.key | string | "" |
Secret key for GITHUB_APP_PRIVATE_KEY. |
| backend.github.appPrivateKeyRef.name | string | "" |
Existing secret containing GITHUB_APP_PRIVATE_KEY. |
| backend.github.appSlug | string | "" |
GitHub App slug. |
| backend.github.webhookSecret | string | "" |
GitHub App webhook secret. Prefer webhookSecretRef for production deployments. |
| backend.github.webhookSecretRef.key | string | "" |
Secret key for GITHUB_WEBHOOK_SECRET. |
| backend.github.webhookSecretRef.name | string | "" |
Existing secret containing GITHUB_WEBHOOK_SECRET. |
| backend.google.clientId | string | "" |
Google OAuth client ID. |
| backend.google.clientIdRef.key | string | "" |
Secret key for GOOGLE_CLIENT_ID. |
| backend.google.clientIdRef.name | string | "" |
Existing secret containing GOOGLE_CLIENT_ID. |
| backend.google.clientSecret | string | "" |
Google OAuth client secret. |
| backend.google.clientSecretRef.key | string | "" |
Secret key for GOOGLE_CLIENT_SECRET. |
| backend.google.clientSecretRef.name | string | "" |
Existing secret containing GOOGLE_CLIENT_SECRET. |
| backend.google.redirectUri | string | "http://localhost:3000/auth/callback" |
Google OAuth redirect URI. |
| backend.image.pullPolicy | string | "IfNotPresent" |
Backend image pull policy. |
| backend.image.repository | string | "ghcr.io/multica-ai/multica-backend" |
Backend image repository. |
| backend.image.tag | string | "" |
Backend image tag override. Defaults to chart appVersion. |
| backend.lark.callbackBaseUrl | string | "" |
Optional Lark long-connection callback bootstrap base URL. Set to https://open.larksuite.com for international Lark tenants. |
| backend.lark.httpBaseUrl | string | "" |
Optional Lark Open Platform API base URL. Set to https://open.larksuite.com for international Lark tenants. |
| backend.lark.registrationDomain | string | "" |
Optional initial device-flow registration host override. |
| backend.lark.registrationLarkDomain | string | "" |
Optional Lark international device-flow registration host override. |
| backend.lark.secretKey | string | "" |
Base64-encoded 32-byte key enabling Lark/Feishu Bot integration and encrypting Bot app secrets at rest. Prefer secretKeyRef in production. |
| backend.lark.secretKeyRef.key | string | "" |
Secret key for MULTICA_LARK_SECRET_KEY. |
| backend.lark.secretKeyRef.name | string | "" |
Existing secret containing MULTICA_LARK_SECRET_KEY. |
| backend.lark.wsProxyUrl | string | "" |
Optional fixed HTTP CONNECT proxy URL for Lark/Feishu WebSocket long-connection handshakes. |
| backend.llm.apiKey | string | "" |
Server-side LLM API key. Prefer apiKeyRef in production. |
| backend.llm.apiKeyRef.key | string | "" |
Secret key for MULTICA_LLM_API_KEY. |
| backend.llm.apiKeyRef.name | string | "" |
Existing secret containing MULTICA_LLM_API_KEY. |
| backend.llm.baseUrl | string | "" |
OpenAI-compatible LLM base URL. |
| backend.llm.defaultModel | string | "" |
Default server-side LLM model. |
| backend.llm.maxRetries | string | nil |
Maximum server-side LLM retries. |
| backend.nodeSelector | object | {} |
Backend node selector. |
| backend.plugins.apiUrl | string | "" |
Plugin API URL. |
| backend.plugins.dir | string | "" |
Plugin installation directory inside the backend container. |
| backend.plugins.secretKey | string | "" |
Base64-encoded 32-byte key used to sign plugin sessions. Prefer secretKeyRef in production. |
| backend.plugins.secretKeyRef.key | string | "" |
Secret key for MULTICA_PLUGIN_SECRET_KEY. |
| backend.plugins.secretKeyRef.name | string | "" |
Existing secret containing MULTICA_PLUGIN_SECRET_KEY. |
| backend.plugins.surfaceOrigin | string | "" |
Public plugin surface origin. |
| backend.podAnnotations | object | {} |
Pod annotations for backend pods. |
| backend.podLabels | object | {} |
Pod labels for backend pods. |
| backend.podSecurityContext | object | {} |
Pod security context for backend pods. |
| backend.rateLimits.auth.maxPerMinute | string | nil |
Optional RATE_LIMIT_AUTH override for /auth/send-code and /auth/google requests per IP per minute. Empty uses Multica’s default. |
| backend.rateLimits.auth.trustedProxies | string | "" |
Comma-separated CIDRs whose X-Forwarded-For header is trusted by the auth rate limiter. |
| backend.rateLimits.auth.verifyMaxPerMinute | string | nil |
Optional RATE_LIMIT_AUTH_VERIFY override for /auth/verify-code requests per IP per minute. Empty uses Multica’s default. |
| backend.rateLimits.invitation.actor10m | string | nil |
Optional RATE_LIMIT_INVITATION_ACTOR_10M override. |
| backend.rateLimits.invitation.recipient24h | string | nil |
Optional RATE_LIMIT_INVITATION_RECIPIENT_24H override. |
| backend.rateLimits.invitation.workspace24h | string | nil |
Optional RATE_LIMIT_INVITATION_WORKSPACE_24H override. |
| backend.replicaCount | int | 1 |
Number of backend replicas. |
| backend.resources | object | {} |
Backend resources. |
| backend.securityContext | object | {} |
Container security context for the backend container. |
| backend.service.annotations | object | {} |
Backend Service annotations. |
| backend.service.nodePort | string | nil |
Optional nodePort when service.type is NodePort/LoadBalancer. |
| backend.service.port | int | 8080 |
Backend Service port. |
| backend.service.targetPort | int | 8080 |
Backend container port. |
| backend.service.type | string | "ClusterIP" |
Backend Service type. |
| backend.slack.secretKey | string | "" |
Base64-encoded 32-byte key enabling Slack integration and encrypting Slack app/bot tokens at rest. Prefer secretKeyRef in production. |
| backend.slack.secretKeyRef.key | string | "" |
Secret key for MULTICA_SLACK_SECRET_KEY. |
| backend.slack.secretKeyRef.name | string | "" |
Existing secret containing MULTICA_SLACK_SECRET_KEY. |
| backend.telegram.secretKey | string | "" |
Base64-encoded 32-byte key enabling Telegram integration. Prefer secretKeyRef in production. |
| backend.telegram.secretKeyRef.key | string | "" |
Secret key for MULTICA_TELEGRAM_SECRET_KEY. |
| backend.telegram.secretKeyRef.name | string | "" |
Existing secret containing MULTICA_TELEGRAM_SECRET_KEY. |
| backend.tolerations | list | [] |
Backend tolerations. |
| backend.vcs.secretKey | string | "" |
Base64-encoded 32-byte key used to encrypt self-hosted VCS integration secrets. Prefer secretKeyRef in production. |
| backend.vcs.secretKeyRef.key | string | "" |
Secret key for MULTICA_VCS_SECRET_KEY. |
| backend.vcs.secretKeyRef.name | string | "" |
Existing secret containing MULTICA_VCS_SECRET_KEY. |
| backend.volumeMounts | list | [] |
Additional backend volume mounts. |
| backend.volumes | list | [] |
Additional backend volumes. |
| backend.wecom.mediaAllowCidrs | string | "" |
Optional CIDRs allowed to fetch WeCom media. |
| backend.wecom.secretKey | string | "" |
Base64-encoded 32-byte key enabling WeCom integration. Prefer secretKeyRef in production. |
| backend.wecom.secretKeyRef.key | string | "" |
Secret key for MULTICA_WECOM_SECRET_KEY. |
| backend.wecom.secretKeyRef.name | string | "" |
Existing secret containing MULTICA_WECOM_SECRET_KEY. |
| backend.wecom.trace | bool | false |
Enable verbose WeCom tracing. Keep false outside debugging. |
| channelLeases.backend | string | "" |
Lease backend, e.g. postgres or redis. Redis mode uses realtime.redisUrl (REDIS_URL); the former dedicated CHANNEL_WS_LEASE_REDIS_URL no longer exists upstream. |
| channelLeases.errorRetryInterval | string | "" |
Retry interval after lease backend errors. |
| channelLeases.expirySafetyMargin | string | "" |
Safety margin before lease expiry. |
| channelLeases.namespace | string | "" |
Redis key namespace for channel leases. |
| channelLeases.pollInterval | string | "" |
Lease polling interval. |
| channelLeases.renewInterval | string | "" |
Lease renewal interval. |
| channelLeases.ttl | string | "" |
Lease TTL. |
| database.external.enabled | bool | false |
Enable external PostgreSQL mode. When enabled, set postgres.enabled=false. |
| database.external.host | string | "" |
External PostgreSQL host. Required for waitForReady when using urlFrom; optional with url because the chart can derive the host from the URL. |
| database.external.name | string | "multica" |
External PostgreSQL database name. |
| database.external.password | string | "" |
External PostgreSQL password. |
| database.external.port | int | 5432 |
External PostgreSQL port. |
| database.external.sslMode | string | "disable" |
SSL mode appended to generated DATABASE_URL. |
| database.external.url | string | "" |
Full PostgreSQL connection URL. |
| database.external.urlFrom.secretKeyRef | object | {"key":"","name":""} |
Existing secret containing DATABASE_URL. |
| database.external.username | string | "" |
External PostgreSQL username. |
| database.internal.port | int | 5432 |
Internal PostgreSQL service port. |
| database.internal.serviceName | string | "" |
Override internal PostgreSQL service name. Defaults to <release>-postgres. |
| database.pool.maxConns | string | nil |
Optional DATABASE_MAX_CONNS env override. Leave empty to honor DATABASE_URL pool_max_conns or Multica defaults. |
| database.pool.minConns | string | nil |
Optional DATABASE_MIN_CONNS env override. Leave empty to honor DATABASE_URL pool_min_conns or Multica defaults. |
| database.replica.maxConns | string | nil |
Optional DATABASE_REPLICA_MAX_CONNS override. Empty uses Multica’s default (10). |
| database.replica.minConns | string | nil |
Optional DATABASE_REPLICA_MIN_CONNS override. Empty uses Multica’s default (0). |
| database.replica.url | string | "" |
Optional PostgreSQL read-replica connection URL. Multica requires every replica connection to be read-only and recycles it after 5m so a promoted node is revalidated; replica failures fall back to the primary. Empty disables replica reads. Do not also set urlFrom. |
| database.replica.urlFrom.secretKeyRef | object | {"key":"","name":""} |
Existing secret containing DATABASE_REPLICA_URL. |
| database.waitForReady.enabled | bool | true |
Wait for PostgreSQL TCP readiness before starting the backend. |
| database.waitForReady.image | string | "busybox:1.38" |
Init container image used for DB readiness checks. |
| database.waitForReady.imagePullPolicy | string | "IfNotPresent" |
Init container image pull policy. |
| database.waitForReady.periodSeconds | int | 2 |
Poll interval in seconds. |
| database.waitForReady.timeoutSeconds | int | 180 |
Max seconds to wait for DB readiness. |
| frontend.affinity | object | {} |
Frontend affinity. |
| frontend.autoscaling.enabled | bool | false |
Enable frontend HPA. |
| frontend.autoscaling.maxReplicas | int | 5 |
Maximum frontend replicas. |
| frontend.autoscaling.minReplicas | int | 1 |
Minimum frontend replicas. |
| frontend.autoscaling.targetCPUUtilizationPercentage | int | 80 |
Target CPU utilization percentage. |
| frontend.autoscaling.targetMemoryUtilizationPercentage | string | nil |
Target memory utilization percentage. |
| frontend.backendServiceAlias.annotations | object | {} |
Compatibility Service annotations. |
| frontend.backendServiceAlias.enabled | bool | true |
Create a Service named backend for legacy multica-web images that still use baked-in Next.js rewrites. Current images can use frontend.config.remoteApiUrl instead. |
| frontend.backendServiceAlias.name | string | "backend" |
Compatibility Service name. |
| frontend.config.docsUrl | string | "" |
Documentation site URL consumed by current multica-web images. |
| frontend.config.publicApiUrl | string | "" |
Public API URL used by generated links. |
| frontend.config.publicWsUrl | string | "" |
Public WebSocket URL used by generated links. |
| frontend.config.remoteApiUrl | string | "" |
Runtime API URL consumed by current multica-web images. |
| frontend.envFrom | list | [] |
Extra frontend envFrom refs. |
| frontend.extraEnv | list | [] |
Extra frontend env vars. Managed frontend config names are rejected to avoid silent overrides. |
| frontend.image.pullPolicy | string | "IfNotPresent" |
Frontend image pull policy. |
| frontend.image.repository | string | "ghcr.io/multica-ai/multica-web" |
Frontend image repository. |
| frontend.image.tag | string | "" |
Frontend image tag override. Defaults to chart appVersion. |
| frontend.nodeSelector | object | {} |
Frontend node selector. |
| frontend.podAnnotations | object | {} |
Pod annotations for frontend pods. |
| frontend.podLabels | object | {} |
Pod labels for frontend pods. |
| frontend.podSecurityContext | object | {} |
Pod security context for frontend pods. |
| frontend.replicaCount | int | 1 |
Number of frontend replicas. |
| frontend.resources | object | {} |
Frontend resources. |
| frontend.securityContext | object | {} |
Container security context for the frontend container. |
| frontend.service.annotations | object | {} |
Frontend Service annotations. |
| frontend.service.externalTrafficPolicy | string | nil |
External traffic policy. |
| frontend.service.loadBalancerIP | string | nil |
Optional LoadBalancer IP. |
| frontend.service.loadBalancerSourceRanges | list | [] |
Optional CIDRs allowed via LoadBalancer. |
| frontend.service.nodePort | string | nil |
Optional nodePort when service.type is NodePort/LoadBalancer. |
| frontend.service.port | int | 80 |
Frontend Service port. |
| frontend.service.targetPort | int | 3000 |
Frontend container port. |
| frontend.service.type | string | "ClusterIP" |
Frontend Service type. |
| frontend.tolerations | list | [] |
Frontend tolerations. |
| fullnameOverride | string | "" |
Override fully-qualified release name. |
| httpRoute.annotations | object | {} |
HTTPRoute annotations. |
| httpRoute.backendMatches.enabled | bool | true |
Route backend-owned paths directly to the backend Service. Required for CLI multica setup self-host, which probes /health. |
| httpRoute.backendMatches.matches | list | [{"path":{"type":"Exact","value":"/health"}},{"path":{"type":"PathPrefix","value":"/health/"}},{"path":{"type":"Exact","value":"/ws"}},{"path":{"type":"Exact","value":"/api"}},{"path":{"type":"PathPrefix","value":"/api/"}},{"path":{"type":"Exact","value":"/auth"}},{"path":{"type":"PathPrefix","value":"/auth/"}},{"path":{"type":"Exact","value":"/uploads"}},{"path":{"type":"PathPrefix","value":"/uploads/"}}] |
Backend HTTPRoute matches emitted before frontend matches. |
| httpRoute.enabled | bool | false |
Enable Gateway API HTTPRoute for Multica. |
| httpRoute.hostnames | list | [] |
Optional HTTPRoute hostnames. |
| httpRoute.matches | list | [{"path":{"type":"PathPrefix","value":"/"}}] |
Match rules for HTTPRoute. |
| httpRoute.parentRefs | list | [] |
ParentRefs for HTTPRoute. Required when enabled. |
| imagePullSecrets | list | [] |
Shared image pull secrets. |
| ingress.annotations | object | {} |
Ingress annotations. |
| ingress.backendPaths.enabled | bool | true |
Route backend-owned paths directly to the backend Service. Required for CLI multica setup self-host, which probes /health. |
| ingress.backendPaths.paths | list | [{"path":"/health","pathType":"Prefix"},{"path":"/ws","pathType":"Exact"},{"path":"/api","pathType":"Prefix"},{"path":"/auth","pathType":"Prefix"},{"path":"/uploads","pathType":"Prefix"}] |
Backend paths to expose through Ingress before frontend catch-all paths. |
| ingress.className | string | "" |
IngressClass name. |
| ingress.enabled | bool | false |
Enable Ingress for Multica. |
| ingress.hosts | list | [] |
Ingress hosts and paths. |
| ingress.tls | list | [] |
Ingress TLS entries. |
| livenessProbe.backend.failureThreshold | int | 6 |
|
| livenessProbe.backend.httpGet.path | string | "/health" |
|
| livenessProbe.backend.httpGet.port | string | "http" |
|
| livenessProbe.backend.initialDelaySeconds | int | 10 |
|
| livenessProbe.backend.periodSeconds | int | 10 |
|
| livenessProbe.backend.successThreshold | int | 1 |
|
| livenessProbe.backend.timeoutSeconds | int | 3 |
|
| livenessProbe.frontend.failureThreshold | int | 6 |
|
| livenessProbe.frontend.httpGet.path | string | "/" |
|
| livenessProbe.frontend.httpGet.port | string | "http" |
|
| livenessProbe.frontend.initialDelaySeconds | int | 10 |
|
| livenessProbe.frontend.periodSeconds | int | 10 |
|
| livenessProbe.frontend.successThreshold | int | 1 |
|
| livenessProbe.frontend.timeoutSeconds | int | 3 |
|
| migrations.preUpgradeJob.backfillTaskUsageHourlyOnFailure | bool | true |
Retry migrate up after running backfill_task_usage_hourly when the first migration pass fails. |
| migrations.preUpgradeJob.backoffLimit | int | 1 |
Job backoff limit. |
| migrations.preUpgradeJob.enabled | bool | true |
Run a Helm pre-upgrade Job with the backend image before rolling the Deployment. |
| migrations.preUpgradeJob.hookDeletePolicy | string | "before-hook-creation,hook-succeeded" |
Hook delete policy for the migration Job. |
| migrations.preUpgradeJob.hookWeight | int | -5 |
Helm hook weight for the migration Job. |
| migrations.preUpgradeJob.podAnnotations | object | {} |
Pod annotations for the migration Job. |
| migrations.preUpgradeJob.resources | object | {} |
Migration Job resources. |
| migrations.preUpgradeJob.ttlSecondsAfterFinished | int | 300 |
Seconds to keep the finished Job. Set null to omit. |
| monitoring.prometheusRule.additionalLabels | object | {} |
Extra labels to add to the PrometheusRule. |
| monitoring.prometheusRule.enabled | bool | false |
Create Prometheus Operator alert rules for Multica business sampler metrics. |
| monitoring.prometheusRule.samplerQueryErrorsFor | string | "5m" |
Alert duration for business sampler query errors. |
| monitoring.prometheusRule.samplerQueryLatencyFor | string | "10m" |
Alert duration for high business sampler query latency. |
| monitoring.prometheusRule.severity | string | "warning" |
Prometheus alert severity label. |
| nameOverride | string | "" |
Override chart name. |
| postgres.auth.database | string | "multica" |
|
| postgres.auth.password | string | "multica" |
|
| postgres.auth.username | string | "multica" |
|
| postgres.enabled | bool | true |
|
| postgres.image.imagePullPolicy | string | "IfNotPresent" |
|
| postgres.image.repository | string | "pgvector/pgvector" |
|
| postgres.image.tag | string | "pg17" |
|
| postgres.persistence.enabled | bool | true |
|
| postgres.persistence.size | string | "8Gi" |
|
| readinessProbe.backend.failureThreshold | int | 6 |
|
| readinessProbe.backend.httpGet.path | string | "/readyz" |
|
| readinessProbe.backend.httpGet.port | string | "http" |
|
| readinessProbe.backend.initialDelaySeconds | int | 10 |
|
| readinessProbe.backend.periodSeconds | int | 10 |
|
| readinessProbe.backend.successThreshold | int | 1 |
|
| readinessProbe.backend.timeoutSeconds | int | 3 |
|
| readinessProbe.frontend.failureThreshold | int | 6 |
|
| readinessProbe.frontend.httpGet.path | string | "/" |
|
| readinessProbe.frontend.httpGet.port | string | "http" |
|
| readinessProbe.frontend.initialDelaySeconds | int | 5 |
|
| readinessProbe.frontend.periodSeconds | int | 10 |
|
| readinessProbe.frontend.successThreshold | int | 1 |
|
| readinessProbe.frontend.timeoutSeconds | int | 3 |
|
| realtime.redisClusterMode | bool | false |
Set REDIS_CLUSTER_MODE=true for native Redis Cluster or ElastiCache Serverless endpoints. Cluster mode requires database 0 and rejects the legacy/dual relay modes. |
| realtime.redisDisableClientName | bool | false |
Set REDIS_DISABLE_CLIENT_NAME when Redis deployments reject CLIENT SETNAME. |
| realtime.redisUrl | string | "" |
Redis connection URL for multi-backend realtime fanout, channel WebSocket leases, rate limits, auth-token caches, daemon task-claim cache, and runtime-local skill queues. Leave empty for single-backend in-memory mode or when using bundled Redis. Since Multica v0.5.0 every Redis-backed feature shares this one URL; the former dedicated relay/lease URLs no longer exist upstream. |
| realtime.redisUrlRef.key | string | "" |
Secret key for REDIS_URL. |
| realtime.redisUrlRef.name | string | "" |
Existing secret containing REDIS_URL. |
| realtime.relay.maintenanceInterval | string | "" |
Relay maintenance interval. |
| realtime.relay.mode | string | "" |
Relay mode, e.g. stream. Cluster deployments support sharded mode only; other modes are rejected when realtime.redisClusterMode=true. |
| realtime.relay.replayGrace | string | "" |
Replay grace duration. |
| realtime.relay.shards | string | nil |
Number of relay shards. |
| realtime.relay.streamMaxLen | string | nil |
Maximum stream length. |
| realtime.relay.streamTtl | string | "" |
Relay stream TTL duration. |
| realtime.relay.streamTtlEnabled | bool | false |
Enable relay stream TTL maintenance. |
| realtime.relay.trimHorizon | string | "" |
Trim horizon duration. |
| realtime.relay.ttlRefreshInterval | string | "" |
Relay TTL refresh interval. |
| realtime.relay.xreadBlock | string | "" |
XREAD block duration. |
| realtime.relay.xreadCount | string | nil |
XREAD batch size. |
| redis.architecture | string | "standalone" |
|
| redis.auth.enabled | bool | true |
|
| redis.enabled | bool | false |
Enable bundled Redis for multi-backend realtime fanout, auth-token caches, daemon task-claim cache, and runtime-local skill queues. |
| redis.persistence.enabled | bool | true |
|
| redis.persistence.size | string | "8Gi" |
|
| serviceAccount.annotations | object | {} |
Service account annotations. |
| serviceAccount.create | bool | true |
Create a service account for Multica pods. |
| serviceAccount.name | string | "" |
Service account name. |
| startupProbe.backend.failureThreshold | int | 30 |
|
| startupProbe.backend.httpGet.path | string | "/health" |
|
| startupProbe.backend.httpGet.port | string | "http" |
|
| startupProbe.backend.periodSeconds | int | 10 |
|
| startupProbe.backend.successThreshold | int | 1 |
|
| startupProbe.backend.timeoutSeconds | int | 3 |
|
| storage.attachments.downloadMode | string | "auto" |
Attachment download behavior: auto, cloudfront, presign, or proxy. |
| storage.attachments.downloadUrlTtl | string | "30m" |
TTL for CloudFront signed URLs and S3 presigned attachment download URLs. |
| storage.local.baseUrl | string | "" |
Public base URL for local uploads. Empty returns relative /uploads/... paths. |
| storage.local.persistence.accessModes | list | ["ReadWriteOnce"] |
PVC access modes. |
| storage.local.persistence.annotations | object | {} |
PVC annotations. |
| storage.local.persistence.enabled | bool | true |
Persist local uploads with a PVC. Use S3 for multi-replica production deployments. |
| storage.local.persistence.existingClaim | string | "" |
Existing PVC name. |
| storage.local.persistence.size | string | "10Gi" |
PVC size. |
| storage.local.persistence.storageClass | string | "" |
PVC storage class. |
| storage.local.uploadDir | string | "/app/data/uploads" |
Local upload directory inside the backend container. |
| storage.s3.accessKeyId | string | "" |
AWS access key ID. |
| storage.s3.accessKeyIdRef.key | string | "" |
Secret key for AWS_ACCESS_KEY_ID. |
| storage.s3.accessKeyIdRef.name | string | "" |
Existing secret containing AWS_ACCESS_KEY_ID. |
| storage.s3.bucket | string | "" |
S3 bucket. When set, Multica uses S3-compatible storage instead of local disk for uploads. |
| storage.s3.cloudfrontDomain | string | "" |
CloudFront domain for signed/download URLs. |
| storage.s3.cloudfrontKeyPairId | string | "" |
CloudFront key pair ID. |
| storage.s3.cloudfrontPrivateKey | string | "" |
CloudFront private key. |
| storage.s3.cloudfrontPrivateKeyRef.key | string | "" |
Secret key for CLOUDFRONT_PRIVATE_KEY. |
| storage.s3.cloudfrontPrivateKeyRef.name | string | "" |
Existing secret containing CLOUDFRONT_PRIVATE_KEY. |
| storage.s3.cloudfrontPrivateKeySecret | string | "" |
AWS Secrets Manager secret name for CLOUDFRONT_PRIVATE_KEY. |
| storage.s3.endpointUrl | string | "" |
S3-compatible endpoint URL, e.g. MinIO/R2/Wasabi. |
| storage.s3.region | string | "us-west-2" |
S3 region. |
| storage.s3.secretAccessKey | string | "" |
AWS secret access key. |
| storage.s3.secretAccessKeyRef.key | string | "" |
Secret key for AWS_SECRET_ACCESS_KEY. |
| storage.s3.secretAccessKeyRef.name | string | "" |
Existing secret containing AWS_SECRET_ACCESS_KEY. |
| storage.s3.usePathStyle | string | "" |
Whether to use S3 path-style addressing (true or false). Empty uses the SDK default. |
| tests.enabled | bool | true |
Enable Helm test pod. |
| tests.image.pullPolicy | string | "IfNotPresent" |
Test image pull policy. |
| tests.image.repository | string | "busybox" |
Test image repository. |
| tests.image.tag | string | "1.38" |
Test image tag. |
| usageRollups.cronJob.backoffLimit | int | 1 |
Job backoff limit. |
| usageRollups.cronJob.concurrencyPolicy | string | "Forbid" |
CronJob concurrency policy. Forbid pairs with the database advisory lock to avoid overlapping rollups. |
| usageRollups.cronJob.enabled | bool | false |
Legacy compatibility path. Since Multica v0.3.5 the backend runs rollup_task_usage_hourly() in-process on every replica through its DB-backed scheduler (sys_cron_executions), so an external CronJob is redundant and disabled by default. Enable only for backend images older than v0.3.5 or when the in-process scheduler is unavailable. The SQL function holds advisory lock 4246, so both paths can coexist without double-writing. |
| usageRollups.cronJob.failedJobsHistoryLimit | int | 3 |
Failed Job history limit. |
| usageRollups.cronJob.image.pullPolicy | string | "IfNotPresent" |
PostgreSQL client image pull policy. |
| usageRollups.cronJob.image.repository | string | "postgres" |
PostgreSQL client image repository used to call the rollup SQL function. |
| usageRollups.cronJob.image.tag | string | "18-alpine" |
PostgreSQL client image tag. |
| usageRollups.cronJob.podAnnotations | object | {} |
Pod annotations for the rollup CronJob. |
| usageRollups.cronJob.resources | object | {} |
Rollup CronJob resources. |
| usageRollups.cronJob.schedule | string | "*/5 * * * *" |
Cron schedule for the in-process scheduler’s 5-minute plan cadence. |
| usageRollups.cronJob.startingDeadlineSeconds | int | 300 |
Seconds after a missed schedule when the job may still start. Set null to omit. |
| usageRollups.cronJob.successfulJobsHistoryLimit | int | 3 |
Successful Job history limit. |