57 KiB
Bifrost Helm Charts
Meesho fork: This versioned sibling tracks upstream chart
2.1.26(Bifrost1.5.12) and intentionally retains Meesho's Contour HTTPProxy, ExternalSecret, PodDisruptionBudget, and KEDA templates. Do not replace this directory wholesale during an upstream refresh; rebase upstream changes and preserve the Meesho templates and values.
Meesho upgrade requirements
- Upgrade the Bifrost image with this chart. Upstream
2.1.26targets imagev1.5.12; do not deploy it with the currentv1.4.ximage pins without a separate compatibility review. - Set
bifrost.client.enforceAuthOnInferenceexplicitly in each environment. Upstream defaults it totrue, while the existing Meesho deployment relied on authentication configured in the Bifrost UI/database. - The removed
bifrost.client.enableLitellmFallbacksvalue is accepted only for values-file compatibility and is ignored by Bifrost1.5.x. - Keep
autoscaling.enabled: falsewhen the retainedkeda.enabledsetting is true.
Meesho bundled PostgreSQL
PostgreSQL can be managed by the same Helm release, but it intentionally runs as a separate single-replica Deployment rather than as a sidecar in the Bifrost pod. This keeps database storage and lifecycle independent from Bifrost rollouts and autoscaling.
storage:
mode: postgres
postgresql:
enabled: true
external:
enabled: false
image:
# Pin the approved Meesho Artifact Registry mirror in environment values.
repository: <meesho-postgres-image-repository>
tag: "16-alpine"
auth:
username: bifrost
database: bifrost
existingSecret: bifrost-postgres
passwordKey: password
primary:
persistence:
enabled: true
size: 20Gi
# storageClass: <target-cluster-storage-class>
# Write these for the target cluster; do not copy scheduling across clusters.
nodeSelector: {}
tolerations: []
affinity: {}
externalSecret:
enabled: true
secretName: bifrost-postgres
path: <environment-specific-vault-path>
secretStoreRef: vault-backend
Do not put postgresql.auth.password in Git. The referenced secret must exist
or be produced by the retained ExternalSecret template before the PostgreSQL
and Bifrost pods can start.
Switching an existing release from postgresql.external.enabled: true to the
bundled database does not migrate data. Back up and restore the existing
database into the new PVC-backed PostgreSQL instance before directing Bifrost
to it.
Official Helm charts for deploying Bifrost - a high-performance AI gateway with unified interface for multiple providers.
Latest Version: 2.1.26
Changelog
2.1.26
- Added
bifrost.client.mcpServerAuthMode(headers|both|oauth) andbifrost.client.oauth2ServerConfig(issuerUrl,authCodeTtl,accessTokenTtl,disableVkIdentity) to control how/mcpauthenticates inbound MCP clients. Renders intoclient.mcp_server_auth_modeandclient.oauth2_server_config.authCodeTtlis capped at 900 seconds. - Added ClickHouse as a
storage.logsStore.typeoption. Settype: clickhouseand astorage.logsStore.clickhouseblock (hostrequired; optionalport,database,username,password,protocol,secure,dialTimeout,cluster). Renders intologs_storewithtype: clickhouse. - Added the
bedrock_mantleprovider withbedrock_mantle_key_config(regionrequired; optionalaccess_key,secret_key,session_token,role_arn,external_id,session_name). Added the key-config schema and mutual-exclusion validation invalues.schema.json. - Added
toolExecutionTimeouttobifrost.mcp.clientConfigs[]as a per-server override of the globaltoolManagerConfig.toolExecutionTimeout. Accepts a Go duration string (e.g."30s") or a bare integer treated as seconds. Renders intomcp.client_configs[].tool_execution_timeout. - Added
expires_attobifrost.governance.virtualKeys[]. Optional RFC3339 timestamp; requests using the virtual key are rejected once it passes. Omit for a key that never expires.
2.1.25
- Added
bifrost.circuitBreakerConfig. Renders intocircuit_breaker_configin the generated config JSON. - Extended
bifrost.loadBalancerwith four new behavioural flags:directionSelectionEnabled,routeSelectionEnabled,rerouteFailedDirections, andpruneFailedFallbacks. All are optional booleans; omitting a flag preserves the server default rather than forcing a value. Renders into the corresponding config.json fields insideload_balancer_config. - Added
evaluation_modeto guardrail rules. Acceptsbundled(default, evaluate all turns together) orper_turn(evaluate each turn independently). Set underbifrost.guardrails.rules[].evaluation_mode. - Added
group_traces_by_sessionto the OTEL and Datadog plugin configs. Whentrue, requests sharing the samex-bf-session-idheader are grouped into a single trace. An inbound W3Ctraceparentalways takes priority. Defaults tofalse. - Added
storage.configStore.vaultStoretovalues.yamlwith full commented-out examples for all three backends:aws-secrets-manager,gcp-secret-manager, andhashicorp-vault. SetaccessMode: read_and_writeto automatically store plaintext config fields as vault secrets;read_only(default) only resolves existingvault.<path>references. dns_namesin cluster discovery config now acceptsenv.VAR_NAMEreferences in addition to literal hostnames, consistent with how other secret-bearing fields work across the chart.
2.1.24
allow_private_network(providernetworkConfig) is now rendered by_helpers.tpl; it was in the schema but never wired in, so it had no effect.bifrost.envLabel(max 10 chars) →env_label; shows an environment label in the management UI sidebar.- Datadog plugin: separate
agent_host/agent_portanddogstatsd_host/dogstatsd_portas an alternative to the combined*_addr(defaults8126/8125). passwordCommandfor the PostgreSQL store (config + logs): runs a command that prints the password on stdout.- Async log
writertuning block (maxBatchSize,batchInterval,maxBatchBytes,writeQueueCapacity,deferredUsageConcurrency) for SQLite and PostgreSQL. - Deployment update strategy via top-level
strategy(Deployment only); empty{}keeps the Kubernetes default. bifrost.client.allowDirectKeysandbifrost.client.mcpExternalClientUrl; previously unmapped in_helpers.tpland silently dropped, now render.blacklisted_modelsalongsideallowed_modelsin provider config.bifrost.skillsRegistry(enabled+skills[]) rendered verbatim intoskills_registry.
2.1.23
- Introduced
bifrost.governance.complexityAnalyzerConfigfor complexity router boundaries/keywords; renders intogovernance.complexity_analyzer_config. pluginSpanFilter(mode/plugins) is now supported in OTEL config (single- and multi-profile), with a shared$defsdefinition reused across OTEL, Datadog, and BigQuery connectors.- Brought
plugin_span_filtersupport to the Datadog plugin config. - New
bigqueryplugin defintion:project_id,dataset_id,table_id,location,service_account_key,create_table_if_not_exists,flush_interval_seconds,buffer_size,custom_labels,disable_content_logging,request_headers,plugin_span_filter. - Extended Datadog plugin with
ml_app,dogstatsd_addr,enable_metrics,enable_llm_obs,agentless,api_key(required when agentless), andsite. Credentials supportenv.VAR_NAME. key_idsis now accepted in nested provider config inside virtual providers. Use["*"]for all keys; empty/omitted denies all (v2 default).- New
kafkaplugin definition: requiresbrokers+topic; optional SASL, TLS,compression,batch_size,flush_interval_ms,auto_create_topic,disable_content_logging,plugin_span_filter. - New
pubsubplugin definition: requiresproject_id+topic_id; optionalservice_account_key(or ADC),auto_create_topic,disable_content_logging,plugin_span_filter. - Introduced
bifrost.framework.pricing.mcpLibraryUrlandmcpLibrarySyncIntervalfor configuring a custom MCP server catalog. ingressnow accepts a named map where each key produces a separateIngressnamed<release>-<key>. Legacyingress.enabledshape is unchanged.- Configurable HTTP server read buffer size via
bifrost.server.readBufferSize(controls header-reading buffer; default 65536 bytes). Maps toserver.read_buffer_sizein config.json.
2.1.22
- Added
bifrost.governance.rolesarray tovalues.yaml,values.schema.json, and_helpers.tpl. Each role requires anameand accepts optionaldescription,dac(own-data|team-data|all-data, defaultall-data),access_profile, andpermissions[](resource+operation). bifrost.plugins.otel.confignow accepts either the existing single-profile shape or a newprofileswrapper (otelProfilesConfig) with an array of profiles. Each profile is independently enabled/disabled. A sharedplugin_span_filtercan be set at the top level in either shape.- Added
disable_content_loggingto OTEL config (both single-profile and per-profile). Whentrue, message content (input/output messages, embeddings, tool definitions, tool call arguments/results) is dropped from exported spans — only metadata (model, tokens, latency) is sent to the collector. - Added
otelPluginSpanFilter(mode:include/exclude,pluginsarray) to the OTEL config schema, available in both single-profile and multi-profile shapes. - Added
calendar_alignedtobifrost.governance.modelConfigs[]. - Added
model_config_idandcustomer_idas budget owner fields ingovernance.budgets[], alongside the existingvirtual_key_id,provider_config_id, andteam_id. - Extended
attributeTeamMappingsandattributeBusinessUnitMappingsin SCIM auth config with optionalattributeType(user|group) andattributeValuefields to enable SCIM-driven team/business-unit provisioning. - Added OAuth MCP client config example to
values.yamlshowingauthType: oauthwithoauthConfigId. - Added
bifrost.sourceOfTruth(split|config.json, optional). When set to"config.json", sections explicitly present in the file become authoritative on startup — database-only rows for those sections are pruned. Omitting the field preserves the default"split"merge behavior. - Added
allow_private_networktonetworkConfiginvalues.schema.json. Whentrue, allows connections to RFC 1918 private IPs (10.x, 172.16.x, 192.168.x) — useful for providers on a k8s pod network, LAN, or private VPC.
2.1.21
- Add
per_user_oauth/per_user_headerstoauthTypeenum in mcpClientConfig - Added
scopeandscope_idfields tobifrost.governance.modelConfigs[]items invalues.yamlandvalues.schema.json.scopeaccepts"global"(default, applies to all traffic) or"virtual_key"(applies to a specific virtual key);scope_idis required whenscopeis"virtual_key"and must reference a virtual keyid. The_helpers.tplalready passesmodelConfigsthrough as-is so no template change was needed.
2.1.20
- Added
tlsConfigtobifrost.mcp.clientConfigs[]for HTTP and SSE MCP connection types:insecureSkipVerify— disable TLS certificate verification (development/testing only; takes priority overcaCertPem).caCertPem— PEM-encoded CA certificate for MCP servers that use a self-signed or private CA. Accepts a literal PEM string or anenv.VAR_NAMEreference (e.g."env.MY_MCP_CA_CERT").- Chart maps
tlsConfig.insecureSkipVerify→tls_config.insecure_skip_verifyandtlsConfig.caCertPem→tls_config.ca_cert_pemin the generated config JSON.
- Added
authServerTypeto the Okta SCIM config invalues.schema.jsonandconfig.schema.json. Accepts"org"(Org Authorization Server) or"custom"(Custom Authorization Server); auto-detected from the issuer URL when omitted. Previously the field was documented but rejected byadditionalProperties: falsein both schemas. - Added
attributeRoleMappings,attributeTeamMappings, andattributeBusinessUnitMappingsto the Okta provider branch inconfig.schema.json, aligning the transport runtime schema with the Helm chart schema which already included them.
2.1.19
- Added
bifrost.modelCatalog.modelParametersUrltovalues.yaml,values.schema.json, and_helpers.tpl, allowing operators to override the URL Bifrost uses to fetch model parameter definitions. - Added
existingSecretsupport for hosted PostgreSQL (postgresql.enabled: true). Setpostgresql.auth.existingSecretandpostgresql.auth.passwordKeyto reference a Kubernetes secret (e.g. from Vault Secrets Operator) instead of a plaintext password in values. Both the postgres pod and the bifrost pod will read the password from the secret; the chart-managed secret is not created whenexistingSecretis set. - Added
postgresql.primary.podSecurityContextandpostgresql.primary.containerSecurityContextto allow configuring pod- and container-level security contexts on the hosted PostgreSQL deployment. Defaults topodSecurityContext: { fsGroup: 999 }(preserving prior behaviour) andcontainerSecurityContext: {}(no container security context). Required for clusters enforcing strict Kyverno/OPA policies (e.g.runAsNonRoot,allowPrivilegeEscalation: false,capabilities.drop: [ALL],seccompProfile). - Added
bifrost.featureFlagsmap tovalues.yamland_helpers.tpl. Renders intofeature_flags.flagsin the generated config JSON. Each entry accepts a literal boolean or"env.NAME"string. - Fixed Deployment not exposing the cluster gRPC container port; fixed
service.yamlmissing the gRPC service port. Both now match StatefulSet/headless service behaviour. - Fixed Weaviate PVC rendering when
vectorStore.weaviate.persistence.enabled=false; PVC is now gated on persistence being enabled. - Fixed Redis probes passing password via
-aflag in process args; switched toREDISCLI_AUTHenv var. - Fixed nondeterministic env var order for
providerSecretsandweaviate.envmap iterations; keys are now sorted withsortAlpha. - Corrected guardrail
timeoutexamples invalues.yaml: provider default is30s, rule default is60s.
2.1.18
- Added
bifrost.framework.pricing.modelParametersUrltovalues.yaml,values.schema.json, and_helpers.tpl, allowing operators to override the URL Bifrost uses to fetch model parameter definitions.
2.1.17
- Added
max_turns_to_sendto guardrail rules. The integer caps how many historical conversation turns are sent to the guardrail provider on apply; the latest message is always included on top, and0(default) sends all turns. Wired intovalues.schema.json,config.schema.json, andtemplates/_helpers.tplso it renders intoguardrails_config.guardrail_rules[].max_turns_to_send. - Extended SCIM/SSO support so attribute mappings work for every supported provider, not just Keycloak:
- Added
attributeRoleMappings,attributeTeamMappings, andattributeBusinessUnitMappingstobifrost.scim.configfor the Okta and Entra (Azure AD) provider branches. Previously these fields were rejected byadditionalProperties: falseeven though the enterprise runtime renders them intoconfig.json. - Tightened the existing Keycloak mapping items from the placeholder
{type: object}to a strict shape (attribute,value, plusrole/team/business_unit,additionalProperties: false) so typos surface athelm templatetime. The same strict item shape is applied to Okta, Entra, Zitadel, and Google. - Added two more SCIM providers to the schema enum and provided full config blocks for them:
zitadel(domain,clientId, optionalclientSecret/projectId/audience, plus service-account fields for Management API access) andgoogle(Google Workspace OIDC withdomain,clientId,credentialMode, service-account sources, andadminEmailfor domain-wide delegation). - Added matching
helm template-time validation in_helpers.tplfor Zitadel (requiresdomain,clientId) and Google Workspace (requiresdomain,clientId). - Documented every new field as commented examples under
bifrost.scim.configinvalues.yaml.
- Added
2.1.16
- Widened
bifrost.mcp.toolManagerConfig.toolExecutionTimeoutinvalues.schema.jsonfromintegerto["integer", "string"]so a Go duration string like"30s"or"2m"is accepted alongside the legacy bare integer. Updated the description to clarify "integer = seconds, string = Go duration" and recommend the string form, and changed the default from30to"30s". - Updated the
values.yamlexample to usetoolExecutionTimeout: "30s"instead oftoolExecutionTimeout: 30, matching the new recommended form. - Paired with the upstream runtime fix (PR #3432) that reinterprets bare integers on this field as seconds rather than nanoseconds, and includes
mcp.tool_manager_configin the client config hash so file-level changes survive the hash-based reconciliation pipeline on restart.
2.1.15
- Added
storage.logsStore.matviewRefreshIntervaltovalues.yamlandvalues.schema.json, letting operators control how often PostgreSQL materialized views are refreshed in the logs store (e.g."30s","5m","1h"; minimum5s). - Wired
matviewRefreshIntervalthrough_helpers.tplso it renders into the generated PostgreSQLlogs_store.matview_refresh_intervalfield when set, and is omitted when not. - Bumped
appVersionfrom1.5.0-prerelease7to1.5.0(first chart release pinned to the stable1.5.0app image).
2.1.14
- Removed the obsolete
bifrost.client.allowDirectKeysassertion fromvalidate-helm-config-fields.sh. The field was deleted from the chart schema and codebase in a prior release, so the test was rendering an invalid values file and helm was rejecting it viaadditionalProperties: false. - Hardened
render_config()invalidate-helm-config-fields.shso a failinghelm templateactually surfaces its stderr instead of being swallowed by the script'sset -e(the previous post-hoc$?check was unreachable).
2.1.13
- Surfaced
bifrost.client.enforceAuthOnInferenceinvalues.yamlas a commented default with usage notes. The field was already wired in_helpers.tplto render toclient.enforce_auth_on_inferenceand declared invalues.schema.json; this change makes the knob discoverable without altering default rendered config. - Marked
bifrost.client.enforceGovernanceHeaderas deprecated invalues.yaml(useenforceAuthOnInferenceinstead). Schema description was already deprecated in 2.1.11.
2.1.12
- Added Helm support for
storage.logsStore.objectStorageExcludeFieldsand render path tologs_store.object_storage_exclude_fieldsin generated config.
2.1.11
- Added
descriptionanddefaultfields to numerous properties that previously had neither, includinginitialPoolSize,disableDbPingsInHealth,logRetentionDays,asyncJobResultTTL,mcpAgentDepth,mcpToolExecutionTimeout,hideDeletedVirtualKeysInFilters,mcpDisableAutoToolInject, and MCPtoolManagerConfigfields - Added
additionalProperties: falseto multiple objects (bifrost.config,bifrost.pricing,proxyConfig,concurrencyConfig,providerConfig,credentialsSecret, and auth provider configs) to reject unknown keys at validation time - Added three new
bifrost.clientfields:allowPerRequestContentStorageOverride— controls whether per-request headers can override content logging behaviorallowPerRequestRawOverride— controls whether per-request headers can override raw provider request/response passthroughmcpExternalBaseUrl— public base URL for OAuth callbacks and discovery metadata behind a reverse proxy, supporting both string and env-var object forms
- Added two new
bifrost.cluster.discoveryfields:bindPort— port to bind for cluster communicationdialTimeout— timeout for discovery dial operations as a Go duration string
- Changed
allowedOriginsitems fromoneOftoanyOfand removed the redundantnot: { const: "*" }constraint on the URI branch - Tightened the env-var pattern to require a valid identifier start character (
[A-Za-z_]) for proxyConfig.url - Expanded
toolSyncIntervalto accept either a Go duration string (with a stricter regex) or a legacy integer (nanoseconds) for backward compatibility. - Marked
enforceGovernanceHeaderas deprecated in its description - Added
mdnsServicedescription for local network discovery
2.1.10
- Added
bifrost.cluster.grpcblock for the cluster gRPC counter-sync transport (enterprise):- New values:
bifrost.cluster.grpc.port(default10102) andbifrost.cluster.grpc.dialTimeoutSeconds(default5). - Rendered into
cluster_config.grpc(port,dial_timeout_seconds) bytemplates/_helpers.tpl. - StatefulSet exposes the port as a named
grpccontainer port;service-headlessexposes it as a named service port so peers can dial each other. - Both port additions are guarded by
if .Values.bifrost.cluster.grpcso values overrides that omit the block render cleanly.
- New values:
2.1.9
- Added Kubernetes pod-discovery RBAC templates for cluster discovery:
- Added
templates/rbac.yamlto render a namespacedRole/RoleBindingfor podget/list/watch. - Added
rbac.podDiscovery.enabledtovalues.yamlandvalues.schema.jsonfor controlled enablement (defaults totrue). - RBAC resources render only when
rbac.podDiscovery.enabled,bifrost.cluster.enabled, andbifrost.cluster.discovery.enabledare true, with discoverytype: kubernetes.
- Added
2.1.8
- Added provider key backward compatibility in Helm rendering:
- If
bifrost.providers.<provider>.keys[].idis omitted andnameis present, Helm now auto-populatesid = name. - This preserves legacy values files that only defined key names while still supporting
governance.virtualKeys[].provider_configs[].key_ids.
- If
2.1.7
- Added semantic cache Helm layers and examples:
- Added Redis deployment template for semantic cache.
- Extended Helm values/schema coverage for semantic cache and client-config examples.
- Added enterprise/governance Helm support:
- Added governance
business_unitssupport in Helm schema/template rendering. - Added deferred virtual-key/provider-config budget ordering handling in Helm rendering.
- Added governance
- Added MCP tool-groups support in Helm:
- Added
mcp.tool_groupsconfig support with governance bindings. - Added camelCase alias compatibility for related Helm config fields.
- Added
2.1.6
- Includes unreleased
2.1.5changes - Built-in plugin versioning for DB-backed deployments:
- Added
versionfield support for built-in plugins. - Added default
version: 1for built-in plugins invalues.yaml(telemetry,logging,governance,maxim,semanticCache,otel,datadog). - Updated
_helpers.tplto include pluginversionin rendered config when set (cast as integer).
- Added
- Updated StatefulSet PVC template labels to be immutable-safe:
spec.volumeClaimTemplates.metadata.labelsnow uses stable selector labels (without chart/app version labels).
- Governance schema and validation updates:
- Added
governance.budgets[].virtual_key_idsupport. - Removed stale
budget_idreferences from virtual keys and provider configs in templates/tests. validate-helm-config-fields.shassertions were updated accordingly.
- Added
- Query/schema compatibility updates:
- Tightened
queryvalidation invalues.schema.jsonandconfig.schema.jsonto valid RuleGroupType shape (nullor{ combinator, rules }).
- Tightened
- Config/input alias support updates:
- Added support for
env.*references in proxy/TLS fields (ca_cert_pem,url,username,password). - Added
provider_key_namealias for routing targets and pricing overrides (resolved tokey_idat config load time).
- Added support for
- MCP config improvements:
- Added Go duration string support for
mcp.toolSyncInterval(legacy numeric nanoseconds still supported). - Added hash-based MCP client config reconciliation for DB-backed config store updates.
- Added Go duration string support for
- Upgrade impact:
- Existing SQLite StatefulSets created from older chart templates may require a one-time StatefulSet recreation during upgrade because
spec.volumeClaimTemplatesis immutable in Kubernetes.
- Existing SQLite StatefulSets created from older chart templates may require a one-time StatefulSet recreation during upgrade because
- Migration notes (only if upgrade fails with StatefulSet immutable-field error):
- Identify StatefulSet name and namespace for your Helm release.
- Delete only the StatefulSet while preserving dependents:
kubectl delete statefulset <statefulset-name> -n <namespace> --cascade=orphan
- Run Helm upgrade:
helm upgrade <release-name> bifrost/bifrost -n <namespace> -f <values-file> --set image.tag=<tag>
- If needed, re-apply/recreate the StatefulSet from the upgraded chart manifests.
- Verify PVCs are preserved and pods become healthy:
kubectl get pvc -n <namespace>kubectl get pods -n <namespace>
2.1.5 (not released separately)
- Merged into
2.1.6release notes above.
2.1.4
- Added stricter cluster discovery validation in Helm templates:
- Require
bifrost.cluster.discovery.serviceNamewhenbifrost.cluster.discovery.typeisconsul,etcd, orudp. - For
udpdiscovery, require both:bifrost.cluster.discovery.udpBroadcastPortbifrost.cluster.discovery.allowedAddressSpace
- Require
- Added/updated template fail-fast errors so invalid discovery config is rejected at render time instead of failing later at runtime.
2.1.3
- For
bifrost.cluster.discovery.typeset toconsul,etcd, orudp, setbifrost.cluster.discovery.serviceNameexplicitly during upgrade.
v2.1.2
- Removed
encryption_keyrequirement — field is now optional; Bifrost will operate without encryption when omitted
v2.1.1
- Made
bifrost.governance.virtualKeys[].valueoptional — template no longer fails when the field is omitted, allowing the backend to auto-generate the virtual key value - When
valueis absent, the renderedconfig.jsonomits the field entirely (consistent with other optional VK fields)
v2.1.0-prerelease2 (prerelease)
- Synced helm
values.schema.jsonwith transportconfig.schema.json— fixed virtual key and budget drift:- Removed
required: [mcp_client_id]constraint onvirtualKeys[].mcp_configs[]items — canonical schema accepts eithermcp_client_id(DB form) ormcp_client_name(config-file form, resolved to ID at startup) - Added
mcp_client_nameas an allowed property onvirtualKeys[].mcp_configs[]items - Added
calendar_aligned(boolean) onvirtualKeys[]— field now lives on the virtual key, applies uniformly to all budgets under it - Removed stale
budget_idfromvirtualKeys[]—TableVirtualKeyhas noBudgetID; budgets link via foreign key from the budget table - Removed stale
calendar_alignedfrombudgets[]— moved to virtual key level
- Removed
v2.0.17
- Added object storage support (S3/GCS) for offloading log payloads from the database
- Added
storage.logsStore.objectStorageconfiguration with S3 and GCS backend support - Added object storage credential injection from Kubernetes secrets (
existingSecret) - Added
object_storageschema toconfig.schema.jsonunderlogs_store - Updated deployment and stateful templates with object storage secret env vars
v2.0.16
- Fixed disabled custom plugins being completely removed from rendered config.json instead of being kept with
enabled: false
v2.0.15
- Synced helm schema with transport
config.schema.json— added missing properties:client.mcpDisableAutoToolInject— disable automatic MCP tool injectiongovernance.budgets[].calendar_aligned— snap budget resets to calendar boundariesgovernance.pricingOverrides— scoped pricing overrides for the model catalogmcp.clientConfigs[].allowedExtraHeaders— header allowlist per MCP clientmcp.clientConfigs[].allowOnAllVirtualKeys— make MCP server accessible to all virtual keysmcp.toolManagerConfig.disableAutoToolInject— disable auto tool injection at manager levelnetworkConfig.beta_header_overrides— override Anthropic beta header support per providerwebsocket— full WebSocket gateway tuning (connections, pool, transcript buffer)
- Fixed SSE
connectionStringnot being rendered in_helpers.tplfor MCP clients - Added template rendering for all new properties in
_helpers.tpl
v2.0.14
- Added
placementandorderfields to custom plugin schema and template rendering - Added plugin property completeness check to
validate-helm-schema.sh - Added custom plugin placement/order rendering tests to
validate-helm-templates.sh - Added
PluginConfigstruct validation tovalidate-go-config-fields.sh
v2.0.13
- Added missing client config properties:
asyncJobResultTTL,requiredHeaders,loggingHeaders,allowedHeaders,mcpAgentDepth,mcpToolExecutionTimeout,mcpCodeModeBindingLevel,mcpToolSyncInterval,hideDeletedVirtualKeysInFilters - Added MCP new fields: top-level
toolSyncInterval, per-clientclientId,isCodeModeClient,toolSyncInterval,isPingAvailable,toolPricing, andcodeModeBindingLevelin tool manager config - Added governance
modelConfigsandproviderstop-level properties - Added cluster
regionproperty - Added guardrail provider
timeoutfield (was missing from schema and template rendering) - Fixed
isPingAvailablerendering bug in_helpers.tpl(was using wrong key name) - Added
is_ping_availableandtool_pricingtoconfig.schema.jsonMCP client config - Added new CI script
validate-go-config-fields.shfor Go struct-to-schema drift detection - Expanded all 3 existing CI validation scripts with Gap 1-8 property coverage
v2.0.12
- Fixed health probe paths to use
/healthinstead of/metrics
v2.0.11
- Bumped appVersion to 1.4.11
v2.0.10
- Added missing plugin config properties from Go implementations:
- governance:
required_headers,is_enterprise - logging:
disable_content_logging,logging_headers - otel:
headers,tls_ca_cert,insecure - telemetry:
custom_labels
- governance:
v2.0.9
- Bumped appVersion to 1.4.8
v2.0.8
- Added comprehensive config field coverage for all
config.schema.jsonfields - Added Pinecone vector store support (external only) with secret injection
- Added governance routing rules template support
- Added OTEL metrics fields (metrics_enabled, metrics_endpoint, metrics_push_interval)
- Added advanced Redis connection pool fields (pool_size, timeouts, idle conns, etc.)
- Added Weaviate timeout and className fields
- Expanded values.yaml with commented examples for all provider types (Azure, Vertex, Bedrock), network config, concurrency, proxy config, and governance entities
- Added helm config field validation CI test (246 assertions covering all config.schema.json fields)
v2.0.7
- Previous release
v2.0.6
- Fixes MCP client config template to convert camelCase Helm values to snake_case config format
v2.0.5
- Fixes config field validation parity
v2.0.2
- Added Qdrant vector store support with deployment, service, and PVC templates
- Added headless service template for StatefulSet DNS resolution
- Fixed gitignore pattern that was excluding template files from version control
v2.0.1
- Added missing StatefulSet template for SQLite with persistence mode
- Added headless service for StatefulSet DNS resolution
- v2.0.0 documented StatefulSet support but the template was not included - this release fixes that
v2.0.0 (Breaking Change)
StatefulSet for SQLite with Persistence
This release fixes the multi-attach volume error when running multiple replicas with SQLite storage mode.
What Changed
- When using
storage.mode: sqlitewithstorage.persistence.enabled: true, Bifrost now deploys as a StatefulSet instead of a Deployment - Each pod gets its own dedicated PersistentVolumeClaim (e.g.,
data-bifrost-0,data-bifrost-1,data-bifrost-2) - A headless service is created for StatefulSet DNS resolution
- HorizontalPodAutoscaler now correctly references StatefulSet or Deployment based on storage configuration
Who Is Affected
- Users running SQLite mode with persistence enabled and multiple replicas
- Users upgrading existing SQLite deployments need to migrate (see below)
Who Is NOT Affected
- Users running PostgreSQL mode (
storage.mode: postgres) - no changes, still uses Deployment - Users running SQLite without persistence (
storage.persistence.enabled: false) - Users running SQLite with an existing PVC claim (
storage.persistence.existingClaim)
Migration Guide for Existing SQLite Deployments
Since Kubernetes doesn't allow in-place conversion from Deployment to StatefulSet, you need to:
- Back up your data (if needed)
- Uninstall the existing release:
helm uninstall bifrost - Delete the old PVC:
kubectl delete pvc bifrost-data - Install with the new chart version:
helm install bifrost bifrost/bifrost --set image.tag=<latest-image>
Note: For production high-availability setups, we recommend using PostgreSQL mode which scales horizontally without these concerns.
v1.7.0
- Previous stable release with Deployment-based architecture for all storage modes
Quick Start
# Add the Bifrost Helm repository
helm repo add bifrost https://maximhq.github.io/bifrost/helm-charts
# Update your local Helm chart repository cache
helm repo update
# Install Bifrost with default configuration (SQLite storage)
helm install bifrost bifrost/bifrost --set image.tag=v1.4.3
Prerequisites
- Kubernetes 1.23+
- Helm 3.2.0+
- PV provisioner support in the underlying infrastructure (for persistent storage)
Installation
From Helm Repository (Recommended)
# Add repository
helm repo add bifrost https://maximhq.github.io/bifrost/helm-charts
helm repo update
# Install with default values
helm install bifrost bifrost/bifrost --set image.tag=v1.4.3
# Or install with custom values
helm install bifrost bifrost/bifrost -f my-values.yaml
From Source
# Clone the repository
git clone https://github.com/maximhq/bifrost.git
cd bifrost/helm-charts
# Install from local chart
helm install bifrost ./bifrost --set image.tag=v1.5.2
Interactive Installation
Use the included installation script for guided setup:
cd bifrost/helm-charts/bifrost
./scripts/install.sh
Configuration
Image Configuration
| Parameter | Description | Default |
|---|---|---|
image.repository |
Container image repository | docker.io/maximhq/bifrost |
image.tag |
Container image tag (required) | "" |
image.pullPolicy |
Image pull policy | IfNotPresent |
Important: You must specify the
image.tag. See available tags at Docker Hub.
Enterprise Private Registry
For enterprise customers with private container registries, simply override the image.repository with your full registry URL:
# Google Artifact Registry
image:
repository: us-west1-docker.pkg.dev/bifrost-enterprise/your-org/bifrost
tag: v1.5.0
# AWS ECR
image:
repository: 123456789.dkr.ecr.us-east-1.amazonaws.com/bifrost
tag: v1.5.0
# Azure Container Registry
image:
repository: yourregistry.azurecr.io/bifrost
tag: v1.5.0
# Self-hosted registry
image:
repository: registry.yourcompany.com/ai/bifrost
tag: v1.5.0
If your private registry requires authentication, configure imagePullSecrets:
image:
repository: us-west1-docker.pkg.dev/bifrost-enterprise/your-org/bifrost
tag: v1.5.0
imagePullSecrets:
- name: my-registry-secret
Create the secret beforehand:
kubectl create secret docker-registry my-registry-secret \
--docker-server=us-west1-docker.pkg.dev \
--docker-username=_json_key \
--docker-password="$(cat key.json)" \
--docker-email=your-email@example.com
Storage Configuration
Bifrost supports two storage backends (SQLite and PostgreSQL) that can be configured independently for config and logs stores.
| Parameter | Description | Default |
|---|---|---|
storage.mode |
Default storage backend (fallback when per-store type not set) | sqlite |
storage.persistence.enabled |
Enable persistent storage for SQLite | true |
storage.persistence.size |
Storage size | 10Gi |
storage.configStore.enabled |
Enable configuration store | true |
storage.configStore.type |
Config store backend: sqlite, postgres, or "" |
"" (uses storage.mode) |
storage.logsStore.enabled |
Enable logs store | true |
storage.logsStore.type |
Logs store backend: sqlite, postgres, or "" |
"" (uses storage.mode) |
storage.logsStore.objectStorageExcludeFields |
Payload DB fields to keep in DB instead of offloading to object storage | [] |
Mixed Backend Example
You can use different backends for config and logs stores:
storage:
mode: sqlite # Default fallback
configStore:
enabled: true
type: sqlite # Config in SQLite (fast, local)
logsStore:
enabled: true
type: postgres # Logs in PostgreSQL (scalable, queryable)
postgresql:
enabled: true
# ... PostgreSQL configuration for logs store
PostgreSQL Configuration
| Parameter | Description | Default |
|---|---|---|
postgresql.enabled |
Deploy PostgreSQL as part of this chart | false |
postgresql.auth.username |
Database username | bifrost |
postgresql.auth.password |
Database password (ignored when existingSecret is set) |
bifrost_password |
postgresql.auth.database |
Database name | bifrost |
postgresql.auth.existingSecret |
Name of an existing Kubernetes secret containing the password. When set, the chart does not create its own secret — both the postgres pod and the bifrost pod read from this secret. Useful with secret managers such as Vault Secrets Operator. | "" |
postgresql.auth.passwordKey |
Key inside existingSecret that holds the password |
password |
postgresql.external.enabled |
Use external PostgreSQL (e.g. RDS) instead of deploying a pod | false |
postgresql.external.host |
External PostgreSQL host | "" |
postgresql.external.existingSecret |
Name of an existing Kubernetes secret containing the password for the external instance | "" |
postgresql.external.passwordKey |
Key inside the external existingSecret that holds the password |
password |
Using an Existing Secret for Hosted PostgreSQL
If you manage secrets externally (e.g. with Vault Secrets Operator, External Secrets Operator, or Sealed Secrets), point existingSecret at the synced Kubernetes secret instead of providing a plaintext password:
storage:
mode: postgres
postgresql:
enabled: true
auth:
username: bifrost
database: bifrost
existingSecret: vault-postgres-secret # VSO-synced secret name
passwordKey: password # key inside the secret
The chart will skip creating its own secret. Both the postgres pod (POSTGRES_PASSWORD) and the bifrost pod (BIFROST_POSTGRES_PASSWORD) will mount the password directly from your secret.
For external PostgreSQL (e.g. RDS), use postgresql.external.existingSecret instead:
postgresql:
external:
enabled: true
host: my-db.us-east-1.rds.amazonaws.com
user: bifrost
database: bifrost
existingSecret: vault-rds-secret
passwordKey: password
sslMode: require
Vector Store Configuration (Semantic Caching)
Bifrost supports multiple vector stores for semantic caching:
| Parameter | Description | Default |
|---|---|---|
vectorStore.enabled |
Enable vector store | false |
vectorStore.type |
Vector store type: none, weaviate, redis, qdrant |
none |
Weaviate
vectorStore:
enabled: true
type: weaviate
weaviate:
enabled: true # Deploy Weaviate
# Or use external:
# external:
# enabled: true
# host: "weaviate.example.com"
Redis
vectorStore:
enabled: true
type: redis
redis:
enabled: true # Deploy Redis
# Or use external:
# external:
# enabled: true
# host: "redis.example.com"
Qdrant
vectorStore:
enabled: true
type: qdrant
qdrant:
enabled: true # Deploy Qdrant
# Or use external:
# external:
# enabled: true
# host: "qdrant.example.com"
Bifrost Application Configuration
| Parameter | Description | Default |
|---|---|---|
bifrost.port |
Application port | 8080 |
bifrost.host |
Bind address | 0.0.0.0 |
bifrost.logLevel |
Log level | info |
bifrost.logStyle |
Log format: json or text |
json |
bifrost.encryptionKey |
Encryption key for sensitive data | "" |
Provider Configuration
Configure AI provider API keys:
Note:
keys[].weightis optional in Helm values. If omitted, the chart renders it as1.
bifrost:
providers:
openai:
keys:
- value: "sk-..."
weight: 1
anthropic:
keys:
- value: "sk-ant-..."
weight: 1
Plugins Configuration
| Plugin | Parameter | Description |
|---|---|---|
| Telemetry | bifrost.plugins.telemetry.enabled |
Enable metrics collection |
| Logging | bifrost.plugins.logging.enabled |
Enable request logging |
| Governance | bifrost.plugins.governance.enabled |
Enable budget management |
| Semantic Cache | bifrost.plugins.semanticCache.enabled |
Enable semantic caching |
| OTEL | bifrost.plugins.otel.enabled |
Enable OpenTelemetry integration |
| Maxim | bifrost.plugins.maxim.enabled |
Enable Maxim observability |
| Datadog | bifrost.plugins.datadog.enabled |
Enable Datadog APM integration |
| Custom | bifrost.plugins.custom |
Array of custom/dynamic plugins |
Custom Plugins
You can add custom/dynamic plugins using the bifrost.plugins.custom array:
bifrost:
plugins:
custom:
- name: "my-custom-plugin"
enabled: true
path: "/plugins/my-plugin.so"
version: 1
placement: "pre_builtin" # or "post_builtin" (default)
order: 0 # execution order within placement group
config:
key: value
Client Configuration
| Parameter | Description | Default |
|---|---|---|
bifrost.client.disableDbPingsInHealth |
Disable DB pings in health check | false |
bifrost.client.dumpErrorsInConsoleLogs |
Dump full error details to server console | false |
bifrost.client.headerFilterConfig.allowlist |
Headers allowed to forward to LLM providers | [] |
bifrost.client.headerFilterConfig.denylist |
Headers blocked from forwarding | [] |
MCP Configuration
| Parameter | Description | Default |
|---|---|---|
bifrost.mcp.enabled |
Enable MCP (Model Context Protocol) | false |
bifrost.mcp.clientConfigs |
Array of MCP client configurations | [] |
bifrost.mcp.toolManagerConfig.toolExecutionTimeout |
Tool execution timeout. Integer = seconds, string = Go duration (e.g. "30s", "2m"). Prefer the string form. |
"30s" |
bifrost.mcp.toolManagerConfig.maxAgentDepth |
Maximum agent depth | 10 |
bifrost.mcp.toolManagerConfig.codeModeBindingLevel |
Code mode binding level (server or tool) |
server |
bifrost.mcp.toolManagerConfig.disableAutoToolInject |
Disable automatic MCP tool injection | false |
bifrost.mcp.toolSyncInterval |
Global MCP tool sync interval. Prefer a Go duration string (for example, 10m); legacy numeric nanoseconds are still supported for backward compatibility, but string format is recommended. |
10m |
bifrost.mcp.clientConfigs[].tlsConfig.insecureSkipVerify |
[Upcoming] Disable TLS certificate verification for HTTP/SSE MCP connections. Takes priority over caCertPem. For development/testing only — not recommended for production. |
false |
bifrost.mcp.clientConfigs[].tlsConfig.caCertPem |
[Upcoming] PEM-encoded CA certificate to trust for HTTP/SSE MCP server connections. Accepts a literal PEM string or an env.VAR_NAME reference. Use when the MCP server uses a self-signed or private CA. |
"" |
MCP Migration Guide (client.mcp* -> mcp.*)
Prefer MCP settings under bifrost.mcp going forward. Older bifrost.client.mcp*
keys are retained for backward compatibility, but new configs should migrate to the
mcp.toolManagerConfig and mcp.toolSyncInterval fields.
| Old key | New key |
|---|---|
bifrost.client.mcpAgentDepth |
bifrost.mcp.toolManagerConfig.maxAgentDepth |
bifrost.client.mcpToolExecutionTimeout |
bifrost.mcp.toolManagerConfig.toolExecutionTimeout |
bifrost.client.mcpCodeModeBindingLevel |
bifrost.mcp.toolManagerConfig.codeModeBindingLevel |
bifrost.client.mcpDisableAutoToolInject |
bifrost.mcp.toolManagerConfig.disableAutoToolInject |
bifrost.client.mcpToolSyncInterval |
bifrost.mcp.toolSyncInterval |
Ingress Configuration
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: bifrost.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: bifrost-tls
hosts:
- bifrost.example.com
Auto-scaling Configuration
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
targetMemoryUtilizationPercentage: 80
Referencing Secrets in MCP Headers
bifrost.mcp.clientConfigs[].headers is a free-form map<string, string>
whose values can contain auth tokens. The chart does not wrap this map with
a bespoke secretRef — a per-header dict would explode the values surface.
Instead, use the standard pattern:
- Write
env.MY_HEADER_VARas the header value invalues.yaml:bifrost: mcp: clientConfigs: - name: "my-mcp" connectionType: "http" headers: Authorization: "env.MY_MCP_AUTH" - Inject the env var into the pod via the chart's top-level
envFrom:orenv:pass-through — e.g., invalues.yaml:envFrom: - secretRef: name: my-mcp-auth-secret # OR: env: - name: MY_MCP_AUTH valueFrom: secretKeyRef: name: my-mcp-auth-secret key: authorization
For bifrost.mcp.clientConfigs[].connectionString itself, prefer the
chart-native secretRef (name + connectionStringKey) instead — the
chart will inject BIFROST_MCP_<NAME>_CONNECTION_STRING and rewrite the
config automatically.
Example Configurations
The chart includes pre-configured examples in values-examples/:
| Configuration | Description |
|---|---|
sqlite-only.yaml |
Simple setup with SQLite (local development) |
postgres-only.yaml |
PostgreSQL for config and logs |
mixed-backend.yaml |
SQLite for config + PostgreSQL for logs (mixed backend) |
postgres-weaviate.yaml |
PostgreSQL + Weaviate for semantic caching |
postgres-redis.yaml |
PostgreSQL + Redis for semantic caching |
postgres-qdrant.yaml |
PostgreSQL + Qdrant for semantic caching |
sqlite-weaviate.yaml |
SQLite + Weaviate |
sqlite-redis.yaml |
SQLite + Redis |
sqlite-qdrant.yaml |
SQLite + Qdrant |
external-postgres.yaml |
Using external PostgreSQL |
production-ha.yaml |
Production high-availability setup |
Using Example Configurations
# From Helm repository
helm install bifrost bifrost/bifrost \
-f https://raw.githubusercontent.com/maximhq/bifrost/main/helm-charts/bifrost/values-examples/postgres-only.yaml \
--set image.tag=v1.5.2
# From local source
helm install bifrost ./bifrost -f ./bifrost/values-examples/postgres-only.yaml
Production Deployment
For production deployments, we recommend:
- Use PostgreSQL for reliable data persistence
- Enable semantic caching with Weaviate, Redis, or Qdrant
- Configure auto-scaling for handling variable load
- Set up Ingress with TLS termination
- Use external secrets for sensitive data
Example Production Setup
# production-values.yaml
replicaCount: 3
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
storage:
mode: postgres
postgresql:
enabled: true
auth:
password: "SECURE_PASSWORD_HERE"
primary:
persistence:
size: 50Gi
vectorStore:
enabled: true
type: weaviate
weaviate:
enabled: true
persistence:
size: 50Gi
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: bifrost.yourdomain.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: bifrost-tls
hosts:
- bifrost.yourdomain.com
bifrost:
client:
initialPoolSize: 1000
allowedOrigins:
- "https://yourdomain.com"
plugins:
semanticCache:
enabled: true
telemetry:
enabled: true
logging:
enabled: true
Upgrading
# Update repository
helm repo update
# Upgrade release
helm upgrade bifrost bifrost/bifrost --set image.tag=v1.5.2
# Or with custom values
helm upgrade bifrost bifrost/bifrost -f my-values.yaml
Uninstalling
# Uninstall release
helm uninstall bifrost
# If you want to delete persistent volumes
kubectl delete pvc -l app.kubernetes.io/name=bifrost
Accessing Bifrost
After installation, access Bifrost using one of these methods:
Port Forwarding (Development)
kubectl port-forward svc/bifrost 8080:8080
# Then visit http://localhost:8080
LoadBalancer
service:
type: LoadBalancer
Ingress
Configure the ingress section as shown above.
Monitoring
Bifrost exposes Prometheus metrics at /metrics:
# Get metrics
curl http://localhost:8080/metrics
For OpenTelemetry integration:
bifrost:
plugins:
otel:
enabled: true
config:
service_name: "bifrost"
collector_url: "http://otel-collector:4317"
trace_type: "genai_extension"
protocol: "grpc"
Troubleshooting
Check Pod Status
kubectl get pods -l app.kubernetes.io/name=bifrost
kubectl describe pod <pod-name>
View Logs
kubectl logs -l app.kubernetes.io/name=bifrost -f
Check Configuration
# View generated configmap
kubectl get configmap bifrost -o yaml
# View generated secrets
kubectl get secret bifrost -o yaml
Common Issues
Pod stuck in Pending state:
- Check if PersistentVolume is available:
kubectl get pv - Check storage class:
kubectl get storageclass
Pod CrashLoopBackOff:
- Check logs:
kubectl logs <pod-name> - Verify environment variables and secrets
Cannot connect to PostgreSQL:
- Ensure PostgreSQL pod is running
- Check connection string in configmap/secrets
- Verify network policies allow connectivity
Resources
License
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.
Built with ❤️ by Maxim