Skip to content

Install on Kubernetes

This page installs Olympusx AI with the Helm chart on Kubernetes 1.27 or later: on-premises, EKS, AKS, GKE or any conformant cluster. For Oracle OKE, follow Install on Oracle OKE, which adds the OKE-specific settings to these steps. For OpenShift, follow Install on OpenShift.

  • A cluster that meets Requirements, with kubectl and Helm 3.12 or later on your workstation.
  • The decisions and values from Before you start.
  • For the managed database: the PostgreSQL operator installed, and an S3-compatible bucket with an access key pair.
  • An ingress controller, and TLS certificates for both hostnames, or cert-manager issuing them.

The shortest install that works: the bundled database, cache and identity service, reached by port-forward. Use it to evaluate, then install properly for anything that has to survive. For production, set a backup destination or use your own database.

helm registry login <registry-host> --username <registry-username>
kubectl create namespace olympus
kubectl -n olympus create secret docker-registry <pull-secret> \
--docker-server=<registry-host> \
--docker-username=<registry-username> \
--docker-password=<registry-token>
helm install olympus oci://<registry>/charts/olympus --version <version> \
-n olympus --set 'image.pullSecrets[0].name=<pull-secret>' \
--wait --timeout 10m

Reach the console and sign-in from two terminals:

kubectl -n olympus port-forward svc/olympus-studio 8080:8080
kubectl -n olympus port-forward svc/olympus-keycloak 8180:8080

Open http://localhost:8080 and continue with First sign-in. The first administrator is admin@olympusx.ai unless you named another.

helm registry login <registry-host> --username <registry-username>

Helm prompts for the token. Skip this step if you install from your own mirror.

Step 2: Create the namespace and the pull secret

Section titled “Step 2: Create the namespace and the pull secret”
kubectl create namespace olympus
kubectl -n olympus create secret docker-registry <pull-secret> \
--docker-server=<registry-host> \
--docker-username=<registry-username> \
--docker-password=<registry-token>

The release images are private. Without this Secret every platform pod stops at ImagePullBackOff, the most common way a first install fails.

Pass credentials as Secrets, never with --set: values given on the command line land in the release’s stored manifest and in your shell history.

The master key:

kubectl -n olympus create secret generic olympus-secrets \
--from-literal=SECRETS_MASTER_KEY="$(openssl rand -base64 32)"

Do not name it olympus-config: the chart gives that name to the Secret it creates when you supply none. With External Secrets, Vault or sealed secrets, create it your usual way with the same key name.

Store a copy of the key now:

kubectl -n olympus get secret olympus-secrets \
-o jsonpath='{.data.SECRETS_MASTER_KEY}' | base64 -d

The backup credentials for the managed database:

kubectl -n olympus create secret generic olympus-backup-s3 \
--from-literal=ACCESS_KEY_ID='<access-key-id>' \
--from-literal=ACCESS_SECRET_KEY='<secret-access-key>'

The mail relay’s password, if the relay takes a login:

kubectl -n olympus create secret generic olympus-smtp \
--from-literal=password='<relay-password>'

Save this as olympus-values.yaml and replace the placeholders:

image:
pullSecrets:
- name: <pull-secret>
secrets:
existingSecret: olympus-secrets
# The managed database: three instances, continuous backup.
postgresql:
enabled: false
postgresqlCNPG:
enabled: true
storage:
size: 20Gi
storageClass: <storage-class>
walStorage:
size: 10Gi
storageClass: <storage-class>
backup:
destinationPath: s3://<bucket>/olympus-db
endpointURL: https://<s3-endpoint>
credentialsSecret: olympus-backup-s3
# The built-in identity service: first administrator and mail relay.
keycloak:
bootstrapUser: <admin-email>
smtp:
enabled: true
host: <smtp-host>
port: 587
from: <sender-address>
starttls: true
auth:
enabled: true
username: <smtp-username>
existingSecret: olympus-smtp
ingress:
enabled: true
className: <ingress-class>
consoleHost: <console-host>
gatewayHost: <gateway-host>
tls:
enabled: true
consoleSecret: olympus-console-tls
gatewaySecret: olympus-gateway-tls
guardrails:
enabled: true
clusterRegistration:
enabled: true
modelServing:
runAsUser: 1000

What each block does:

Block Effect
image.pullSecrets The platform’s pods pull with your credential
secrets.existingSecret The master key comes from your Secret, never generated
postgresql, postgresqlCNPG The bundled single instance is off and the managed database is on. endpointURL is required for any store other than AWS S3; without it the archive fails while the platform reports healthy
identity service block The first administrator, and the relay invitations are sent through. Both apply at the first install only
ingress Publishes both hosts. The sign-in address is derived from consoleHost
guardrails.enabled Turns on PII detection and content safety, with the image the release pins
clusterRegistration.enabled Registers this cluster with the platform at start-up, so you can place models without pasting a token
modelServing.runAsUser The user ID model servers run as. Clusters other than OpenShift assign none, and the inference runtime’s image runs as root without it

The certificates: create TLS Secrets named olympus-console-tls and olympus-gateway-tls in the namespace, or let cert-manager issue them by adding an annotation:

ingress:
annotations:
cert-manager.io/cluster-issuer: <cluster-issuer>

Without either, the ingress controller serves its own fallback certificate and browsers report a name mismatch.

For another shape (your own database, your own identity provider, a relay without login, monitoring), see Configuration.

helm install olympus oci://<registry>/charts/olympus --version <version> \
-n olympus -f olympus-values.yaml --wait --timeout 20m

--version is the chart version, which is also the platform version it deploys.

The schema is applied by an init container before the control plane serves anything; with several replicas, one applies it and the others wait. The guardrails image is large, so a first install on cold nodes takes longer than ten minutes.

Watch it come up:

kubectl -n olympus get pods -w

Every pod reaches Running and Ready. If one stays Pending, ImagePullBackOff or CreateContainerConfigError, see Troubleshooting.

Create DNS records for <console-host> and <gateway-host> pointing at your ingress controller’s address:

kubectl -n olympus get ingress

Continue with First sign-in, then Verify the installation.

To review the chart before you install it, or to keep a copy beside your values:

helm pull oci://<registry>/charts/olympus --version <version> --untar -d ./chart
helm install olympus ./chart/olympus -n olympus -f olympus-values.yaml --wait --timeout 20m

helm show values ./chart/olympus prints every value with its documentation.

The operator runs on Kubernetes 1.33 or later with Operator Lifecycle Manager. Choose it here only when no self-hosted model will run on a cluster that assigns no user ID: the user ID model servers need is a chart value with no field on the Olympus resource (Installation overview).

  1. Install OLM if the cluster has none:

    operator-sdk olm install
  2. Follow Install on OpenShift from step 1, with kubectl in place of oc and these namespaces:

    On OpenShift On Kubernetes
    openshift-marketplace (the catalog, and the Subscription’s sourceNamespace) olm
    openshift-operators (the Subscription and the operator) operators
    olympus (the platform) olympus

    The pull secret is needed in all three, and must be linked to the operator’s ServiceAccount in operators.

  3. In the Olympus resource, set ingress.className to your ingress controller’s class, and either ingress.tlsSecret or cert-manager issuing into olympus-console-tls and olympus-gateway-tls. Without a NetworkPolicy peer setting, the metrics ports admit the monitoring namespace and the database admits the PostgreSQL operator’s default namespace (Configuration).