Skip to content

Introduction

Updated 2 min read

The Nebari MLflow Pack deploys MLflow on a Nebari cluster: experiment tracking and a model registry behind Keycloak SSO, with a PostgreSQL backend store and TLS provisioned for you.

It wraps the community MLflow chart and adds three things that chart cannot know about: a NebariApp for routing and auth, a MLFLOW_SERVER_ALLOWED_HOSTS secret derived from that hostname, and defaults chosen so the combination actually works.

browser ──► Envoy Gateway ──► MLflow ──► PostgreSQL
│ svc :80 (bundled)
OIDC filter pod :5000
│
Keycloak
JupyterHub notebooks ──────► MLflow (in-cluster, no auth hop)
MLFLOW_TRACKING_URI svc :80

Two ways in, deliberately. Humans arrive through the gateway and authenticate against Keycloak; notebooks talk to the ClusterIP service directly, bypassing the OIDC filter because the MLflow Python client has no way through it. See Connecting JupyterHub.

  • MLflow 3.7.0, served by uvicorn so the 3.x security-middleware flags are available.
  • PostgreSQL 17.5 as the backend store, with an 8Gi PVC and schema migration on startup. On by default — the alternative is SQLite that loses every experiment on pod restart.
  • A NebariApp producing an HTTPRoute, a cert-manager certificate, a Keycloak client, and an Envoy SecurityPolicy enforcing OIDC at the gateway.
  • An allowed-hosts Secret computed from the NebariApp hostname plus the in-cluster service DNS name, injected via envFrom.

Two defaults surprise people, and both are covered in full below.

  • Artifacts are ephemeral out of the box. The backend store is durable; the artifact store defaults to a path inside the pod’s filesystem, so logged models and files vanish on restart. See Artifact storage.
  • The PostgreSQL secret must exist first, and its name must be exactly <release-name>-postgresql. See Getting started.