Skip to content

Configuration

The settings you choose at install time: the fields of the Olympus resource for an operator install, and the Helm chart values for a chart install. Both reach the same chart, so a setting does the same thing on either path.

The resource is a curated set of decisions, not a copy of the chart’s values: where the platform is reachable, which database, who signs the tokens, where the secrets are, and which optional parts run. Everything else keeps the chart’s default. oc explain olympus.spec --recursive (or kubectl explain) lists every field with its documentation. The kind is Olympus in olympus.olympusx.ai/v1; its short name is olymp.

Four blocks are required: ingress, auth, secrets and database. The API server refuses a resource without them.

Field Default What it does
consoleHost Required The console’s hostname. Sign-in is served on it under /auth
gatewayHost Required The OpenAI-compatible API’s hostname
className nginx The IngressClass. The cluster’s default IngressClass is not consulted. Ignored on OpenShift, which gets Routes
tlsSecret Empty An existing TLS Secret covering both hosts. Empty keeps the names olympus-console-tls and olympus-gateway-tls. Create those Secrets yourself, or let cert-manager issue into them. Ignored on OpenShift, where the Route terminates TLS
Field Default What it does
issuer Required The OIDC issuer, exactly as tokens carry it, with no trailing slash. With the built-in identity service, https://<console-host>/auth/realms/olympus
clientId olympus-studio The client the console signs in as

Every entry is the name of a Secret in the same namespace, never a value.

Field Default What it does
masterKey Required A Secret with the entry SECRETS_MASTER_KEY: base64 of 32 random bytes. The operator refuses to install when the Secret or the entry is missing
registry Empty The image pull Secret for the platform’s images. Needed on every install that pulls from the subscription registry
Field Default What it does
mode Required managed: PostgreSQL run by the PostgreSQL operator in this namespace. external: your own server
instances 3 Managed instances. 1 is allowed for evaluation and is not highly available
storageSize 20Gi Each instance’s data volume
storageClass Cluster default Must support ReadWriteOnce
walStorageSize 10Gi Each instance’s separate write-ahead-log volume, so the log cannot fill the data disk
walStorageClass Cluster default
backupDestination Empty An s3://bucket/path for continuous archiving. Without it there are no backups, and deleting the resource deletes the database with no copy anywhere
backupEndpoint AWS S3 The S3 endpoint. Required for every other store (on-premises object storage, OCI Object Storage); without it archiving fails while the resource reports Ready
backupCredentialsSecret olympus-backup-s3 A Secret with ACCESS_KEY_ID and ACCESS_SECRET_KEY. You create it; nothing deletes it
backupSchedule 0 30 2 * * * (02:30 daily) When a full base backup runs. Six fields: the first is seconds. The API server refuses five
archiveName The database cluster’s name The folder this install archives into. Once set, leave it set
urlSecret Empty external only, and required there: a Secret with DATABASE_URL
appRoleSecret Empty A Secret with a connection string for the restricted application role. Required by components.tenantIsolation
appRoleSecretKey DATABASE_URL The entry inside appRoleSecret
restoreFrom Empty Brings a new install up from a previous install’s archive: sourceServerName (required: the database cluster that wrote the archive, <name>-db for a resource named <name>), destination, pointInTime. Setting it on a running install changes nothing. Refused with external. Backup and restore

A schedule without a destination does nothing: set backupDestination, backupEndpoint, backupCredentialsSecret and backupSchedule together.

Every optional part here is off unless you turn it on.

Field Default What it does
keycloak false Deploys the built-in identity service, which then must be the auth.issuer. Leave off only when the issuer is your own provider
keycloakBootstrapUser admin@olympusx.ai The first platform administrator: an email address, which is also the username. Used once, at first start
keycloakSmtp Unset The relay invitations go through: host (no scheme, no port), port (587), from, fromDisplayName (Olympusx AI), encryption (starttls, ssl or none), and auth with username, passwordSecret and passwordSecretKey (password). Applied at the first install only
keycloakRealm olympus The realm the identity service creates and issues tokens for
keycloakRelativePath /auth The path the identity service is served under. Must be a path segment
keycloakHostname Empty A hostname of its own for the identity service, scheme included, ending in the same path, such as https://sso.example.com/auth. Empty serves it on the console’s host
keycloakJdbcUrl Empty Where the identity service keeps its state. Required with the identity service on and database.mode: external
guardrails false Runs the guardrails service in the cluster. Requires guardrailsImage
guardrailsImage Empty The scanner’s digest (sha256:...) as the release pins it, never a full image reference
externalGuardrailsUrl Empty A scanner you already run, with an http:// or https:// scheme. Excludes guardrails: true. It also turns on review capture for the gateway
langfuse false Runs the tracing store, which the console reads traces from. Adds a 50Gi volume
langfuseHostname Empty A browser address for the tracing store’s own interface. Empty leaves it reachable by port-forward only
monitoring false ServiceMonitors and alert rules. Needs the Prometheus Operator’s CRDs
tenantIsolation false The control plane connects as the restricted application role. Requires database.appRoleSecret

With the built-in identity service on, the issuer is https://<console-host><keycloakRelativePath>/realms/<keycloakRealm>, or <keycloakHostname>/realms/<keycloakRealm> with a hostname. Any other auth.issuer is refused with RenderFailed, naming both issuers.

Field Default What it does
provider kubernetes kubernetes: the control plane runs each deployment as its own model server, on GPUs or on CPU nodes. kubernetes-operator: it writes a ModelDeployment for the operator to reconcile
namespace olympus-serving The shared namespace for model workloads. Project namespaces are separate
importRegistry Empty The registry imported model weights are pushed to. Empty turns in-cluster model import off, and the console says so

agents, networkPolicy, clusterRegistration, image, version

Section titled “agents, networkPolicy, clusterRegistration, image, version”
Field Default What it does
agents.mcpInternalAllowList Empty In-cluster hosts and networks a tenant’s tool servers may be on: host names, *. wildcards, addresses and CIDRs. Empty allows public https:// addresses only. Loopback, link-local and cloud metadata addresses are never reachable
networkPolicy.metricsScrapers The monitoring namespace; on OpenShift, its monitoring namespaces NetworkPolicy peers allowed to scrape metrics. The list replaces the default
networkPolicy.cnpgOperatorNamespace The PostgreSQL operator’s default namespace; openshift-operators on OpenShift Where the PostgreSQL operator runs. Wrong here, the database still serves but stops failing over
clusterRegistration.enabled true Registers this cluster with the platform at start-up
clusterRegistration.name in-cluster The cluster’s name in the console
image.registry The subscription registry Where the platform’s own images come from. No trailing slash
version The version the operator ships with Pins the platform version. Set it only to hold a version back

Keep agents.mcpInternalAllowList narrow. The cluster’s service and pod networks contain the platform’s own services; listing them gives a tenant administrator the reach the policy exists to remove.

Cluster registration grants a credential. It creates a second ServiceAccount, <name>-agent, a non-expiring token for it, and a ClusterRole and binding, <name>-selfregister, that read nodes, pods and metrics and manage namespaces, quotas, limits, NetworkPolicies, RBAC, ServiceAccounts, Deployments, Services, ConfigMaps, Jobs, Events and Secrets, plus the model and database resources where their CRDs exist. The token is sealed with the master key. It is the same grant any other registered cluster needs (Clusters). To remove the cluster, set enabled: false first, then delete it in the console; deleting it in the console alone recreates it at the next restart with a new identity.

These are chart values with no field on the resource. Where you need one, install with the chart.

  • modelServing.runAsUser: the user ID model servers run as. Not needed on OpenShift, which assigns one.
  • modelServing.downloadProxy: the proxy model servers fetch weights through. Without it, a model in a project namespace loads its weights from your registry.
  • providers.ociWorkloadIdentity: OCI Generative AI with no stored key. Connect Oracle with an API key instead.
  • controlPlane.extraEnv: an egress proxy. Without it, the platform namespace needs direct egress to any cloud model provider.

helm show values oci://<registry>/charts/olympus --version <version> prints every value with its documentation. These are the ones customers set.

Value Default What it does
secrets.existingSecret Empty A Secret with SECRETS_MASTER_KEY, and DATABASE_URL and the cache URL when the bundled stores are off
secrets.masterKey Generated Generated keys live only in this cluster. Prefer existingSecret
secrets.gitops false true makes the chart refuse to generate a key. Set it under any tool that renders with helm template
image.registry The subscription registry Where the platform’s images come from
image.pullSecrets Empty Pull Secrets for the platform’s pods
Value Default What it does
ingress.enabled false Renders an Ingress for each host
ingress.className nginx The IngressClass
ingress.consoleHost, ingress.gatewayHost Empty The two hostnames. consoleHost is required with an Ingress
ingress.tls.consoleSecret, ingress.tls.gatewaySecret olympus-console-tls, olympus-gateway-tls The TLS Secrets
ingress.annotations Empty For cert-manager or your ingress controller
route.consoleHost, route.gatewayHost Empty OpenShift Routes, with the OpenShift values file. route.consoleHost is required
gateway.publicUrl Derived from the gateway host The API address developers are given, when the gateway is reached some other way
Value Default What it does
postgresql.enabled true The bundled single instance. Turn it off for the managed database or your own
postgresqlCNPG.enabled false The managed database. Exactly one of the two may be on
postgresqlCNPG.instances 3
postgresqlCNPG.storage.size, .storageClass 20Gi, cluster default
postgresqlCNPG.walStorage.size, .storageClass 10Gi, cluster default
postgresqlCNPG.backup.destinationPath Empty Required while postgresqlCNPG.backup.enabled is true, which is the default
postgresqlCNPG.backup.endpointURL AWS S3 Required for every other store
postgresqlCNPG.backup.credentialsSecret olympus-backup-s3 A Secret with ACCESS_KEY_ID and ACCESS_SECRET_KEY
postgresqlCNPG.backup.schedule.cron 0 30 2 * * * Six fields; the first is seconds
postgresqlCNPG.backup.retentionPolicy 30d
externalPostgresql.existingSecret Empty A Secret with DATABASE_URL, when both bundled options are off

The built-in identity service’s values sit under one block, shown here with their defaults:

keycloak:
enabled: true # false with your own identity provider
bootstrapUser: admin@olympusx.ai # the first platform administrator
realm: olympus
relativePath: /auth
hostname: "" # empty: served on the console's host
smtp: # applied at the first install only
enabled: false
host: ""
port: 587
from: ""
fromDisplayName: Olympusx AI
starttls: true # or ssl: true, for port 465
auth:
enabled: false
username: ""
existingSecret: "" # a Secret with the relay password
passwordKey: password
security: # applied at the first install only
passwordPolicy: "length(12) and upperCase(1) and lowerCase(1) and digits(1) and specialChars(1) and notUsername"
accessTokenLifespanSeconds: 900
ssoSessionIdleTimeoutSeconds: 1800
ssoSessionMaxLifespanSeconds: 36000
Value Default What it does
auth.issuer Derived from the console host Your own provider’s issuer, with the built-in identity service off
auth.audience, auth.clientId olympus-studio The aud tokens must carry, and the console’s client
Value Default What it does
guardrails.enabled false The guardrails service, at the digest the release pins
guardrails.failOpen false Lets traffic through uninspected while the scanner is unreachable. A platform administrator can change it at runtime
externalGuardrails.url Empty A scanner you already run
reranker.enabled false Requires reranker.image.digest
langfuse.enabled false The tracing store
monitoring.enabled false ServiceMonitors and alert rules
monitoring.serviceMonitor.additionalLabels Empty Labels your Prometheus’s serviceMonitorSelector requires
monitoring.prometheusRule.additionalLabels The ServiceMonitor labels Labels its ruleSelector requires
Value Default What it does
modelServing.provider kubernetes As on the resource
modelServing.runAsUser 0 (none) Set 1000 on every cluster other than OpenShift. Applies to model servers on every registered cluster
modelServing.downloadProxy.enabled, .domains false, huggingface.co and hf.co A proxy that lets model servers on the install cluster reach the listed domains on port 443 and nothing else
modelServing.import.registry Empty Where imported weights are pushed. Empty turns import off
modelServing.import.image Empty The release’s model packaging image, or your mirror of it. Required for import
modelServing.import.hfTokenSecret Empty A Secret holding a Hugging Face token, for gated repositories
providers.ociWorkloadIdentity.enabled, .region false, empty OCI Generative AI with no stored key, on an enhanced OKE cluster (Oracle OKE)
controlPlane.extraEnv Empty Environment for the control plane, such as HTTPS_PROXY and NO_PROXY for an egress proxy
Value Default What it does
clusterRegistration.enabled false Registers this cluster at start-up. On by default on the resource, off in the chart
clusterRegistration.name in-cluster
networkPolicy.enabled true Leave it on
networkPolicy.metricsScrapers The monitoring namespace As on the resource
networkPolicy.cnpgOperator The PostgreSQL operator’s default namespace Peers for the PostgreSQL operator
networkPolicy.gatewayFrom Any source Narrows who may call the gateway: your ingress controller’s namespace and in-cluster clients
controlPlane.agents.mcpInternalAllowList Empty As agents.mcpInternalAllowList on the resource
controlPlane.agents.maxToolResultBytes 32768 The largest tool result an agent’s model reads
controlPlane.agents.toolCallTimeoutSeconds 60 One tool call’s limit
nodeSelector, tolerations, affinity, priorityClassName, topologySpreadConstraints Empty Chart-wide placement, overridable per component
<component>.replicas, <component>.resources Per component Replicas and requests

On the resource: leave the built-in identity service off (its default) and set auth.issuer to your provider’s issuer, and auth.clientId to the client you registered for the console. Nothing else is required: the control plane reads <issuer>/.well-known/openid-configuration at start-up.

With the chart:

keycloak:
enabled: false
auth:
issuer: https://<idp-host>/<issuer-path>
audience: <audience>
clientId: <client-id>

The issuer must equal the iss your provider stamps, byte for byte, with no trailing slash; the control plane refuses to start with one. The audience must match the tokens’ aud; without the match, people sign in and every API call answers 401. An issuer that resolves to nothing does not fail the install: the platform reports healthy and nobody can sign in, and the control plane’s log says identity provider not reachable yet.

Your provider must issue the claims Olympusx AI reads, and you register the console’s client with redirect addresses on <console-host>. Identity and sign-in has the claims, the roles and the client settings.

On the resource: database.mode: external and database.urlSecret naming a Secret with DATABASE_URL. With the built-in identity service also on, set components.keycloakJdbcUrl: the identity service needs a JDBC URL, which cannot be derived from a connection string.

With the chart:

kubectl -n olympus create secret generic olympus-secrets \
--from-literal=SECRETS_MASTER_KEY="$(openssl rand -base64 32)" \
--from-literal=DATABASE_URL='postgres://olympus:<password>@<db-host>:5432/olympus?sslmode=require'
secrets:
existingSecret: olympus-secrets
postgresql:
enabled: false
# Only with the built-in identity service on your database:
keycloak:
database:
jdbcUrl: jdbc:postgresql://<db-host>:5432/olympus
username: olympus
existingSecret: <identity-db-secret> # a Secret with the key `password`

The built-in identity service needs its own connection to your database, as a JDBC URL, because one cannot be derived from a connection string. It keeps its tables in a schema of their own. Without the JDBC URL, the chart stops and names the value.

Your own cache works the same way: turn the bundled one off with redis.enabled: false and put its URL in secrets.existingSecret under REDIS_URL. It must speak the Redis protocol, version 6.2 or later. The cache holds budget counters: if it is unavailable, budgets and rate limits stop applying until it returns.

Row-level security already separates tenants’ rows in every install. Tenant isolation adds privilege separation: the control plane connects as olympus_app, a role that can read and write rows but cannot alter tables or drop the policies. Migrations keep running as the owner.

Have a DBA create the role once, as a superuser or a role with CREATEROLE, on the platform database. Check first:

SELECT rolcanlogin FROM pg_roles WHERE rolname = 'olympus_app';

If it is missing or cannot log in:

CREATE ROLE olympus_app LOGIN PASSWORD '<password>'
NOSUPERUSER NOCREATEDB NOCREATEROLE NOBYPASSRLS;
GRANT USAGE ON SCHEMA public TO olympus_app;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO olympus_app;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO olympus_app;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO olympus_app;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT USAGE, SELECT ON SEQUENCES TO olympus_app;

Then the Secret:

kubectl -n olympus create secret generic olympus-app-db \
--from-literal=DATABASE_URL='postgres://olympus_app:<password>@<db-host>:5432/olympus?sslmode=require'

And turn it on: components.tenantIsolation: true with database.appRoleSecret: olympus-app-db on the resource, or with the chart:

tenantIsolation:
enabled: true
appSecret: olympus-app-db

The operator refuses tenantIsolation without appRoleSecret rather than reporting isolation while serving as the owner.

With monitoring on, the chart renders two ServiceMonitors and a PrometheusRule with the platform’s alerts. Two things go wrong, differently:

  • The Prometheus Operator’s CRDs are missing. The install stops and says so.

  • Your Prometheus’s selectors do not match. Nothing fails, and nothing is scraped. Read the selectors, and set the matching labels in monitoring.serviceMonitor.additionalLabels and, if it differs, monitoring.prometheusRule.additionalLabels:

    kubectl get prometheus -A -o jsonpath='{..serviceMonitorSelector}{"\n"}{..ruleSelector}{"\n"}'

networkPolicy.metricsScrapers must also admit the namespace your Prometheus runs in. Wrong, every pod stays Ready and the targets show as down. Monitoring and alerts lists the alerts.

The platform’s NetworkPolicies admit two outside parties by namespace: your Prometheus on the metrics ports, and the PostgreSQL operator on each database instance’s management port. On Kubernetes the defaults are the monitoring namespace and the PostgreSQL operator’s own default namespace; on OpenShift, OpenShift’s monitoring namespaces and openshift-operators. Set them when yours run elsewhere:

spec:
networkPolicy:
cnpgOperatorNamespace: <operator-namespace>
metricsScrapers:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: <prometheus-namespace>

If the PostgreSQL operator cannot reach the instances, the database keeps serving queries, stops reporting status and stops failing over.