Install Dexter

Dexter runs as its own Helm release in its own namespace, configured by one values file. It does not have to share a cluster with Kloudfuse: it reads your telemetry through the Kloudfuse MCP server.

Prerequisites

  • A Kubernetes cluster with a default StorageClass, and kubectl access to it.

  • Helm 3.8 or later.

  • The token.json that Kloudfuse provided for your Kloudfuse install.

  • An Anthropic API key, or a Claude Max OAuth token.

  • A Kloudfuse cluster with the remote MCP server enabled, and a service account token for it.

  • To serve Dexter on your own domain (step 6): cert-manager installed in the cluster, and a DNS name you can point at a load balancer.

1. Log in to the Helm registry

cat token.json | helm registry login -u _json_key --password-stdin us-east1-docker.pkg.dev

2. Create the namespace and image pull secret

The chart uses this secret by default, the same one a Kloudfuse install creates.

kubectl create namespace dexter

kubectl create secret docker-registry kfuse-image-pull-credentials \
  --namespace dexter --docker-server us.gcr.io --docker-username _json_key \
  --docker-password="$(cat token.json)"

3. Create the values file

Save this as dexter-values.yaml. As it stands, it installs Dexter privately; steps 5 and 6 uncomment its two sections.

# Values for the Dexter Helm chart: the whole install in one file.
#
#   helm install dexter oci://us-east1-docker.pkg.dev/mvp-demo-301906/kfuse-helm/dexter \
#     --version <VERSION> --namespace dexter -f dexter-values.yaml
#
# To change something later, edit this file and run the same command with `helm upgrade`.
#
# As it stands, this installs Dexter privately. Reach it with
#   kubectl -n dexter port-forward svc/dexter 3000:3000
# The image pull secret defaults to kfuse-image-pull-credentials, the one a Kloudfuse install creates.

# --- Sign-in ---------------------------------------------------------------------------------------
# Required before Dexter is reachable from a network: the chart refuses a public host without it.
# The dexter-auth Secret holds SESSION_SECRET, plus DEXTER_LOCAL_USERS for local accounts.
#
# env:
#   DEXTER_AUTH_REQUIRED: "1"
#   DEXTER_ADMIN_EMAILS: "admin@example.com"
# envFromSecrets:
#   - dexter-auth

# --- Public access ---------------------------------------------------------------------------------
# Serves Dexter at https://<host> through its own load balancer, with a Let's Encrypt certificate.
# Needs cert-manager in the cluster, and a DNS record that points the host at the load balancer.
#
# ingress:
#   enabled: true
#   host: dexter.example.com
#
# The cloud assigns the load balancer's address and it changes if the Service is recreated. To keep
# one address across reinstalls, reserve a REGIONAL static IP in the cluster's region — a GCE
# Ingress's GLOBAL address cannot be used by a LoadBalancer Service.
#
# ingress-nginx:
#   controller:
#     service:
#       loadBalancerIP: 34.1.2.3
#
# Already running an ingress controller? Serve the Ingress from it instead of creating a second
# load balancer:
#
# ingress-nginx:
#   enabled: false
# ingress:
#   enabled: true
#   host: dexter.example.com
#   className: <the existing IngressClass>
yaml

4. Install Dexter

helm install dexter oci://us-east1-docker.pkg.dev/mvp-demo-301906/kfuse-helm/dexter \
  --namespace dexter \
  --version <VERSION> \ (1)
  -f dexter-values.yaml

kubectl -n dexter rollout status deployment/dexter
1 Replace <VERSION> with the Dexter chart version from your Kloudfuse contact.

This installs one Deployment, a Service, and a persistent volume for Dexter’s data, with no load balancer. Every later change is an edit to dexter-values.yaml, applied with the same command using helm upgrade in place of helm install.

5. Turn on sign-in

Until now, anyone who can reach Dexter is an admin. Create an admin account and require sign-in before you expose Dexter.

  1. Choose a password for the admin account and hash it with the Bun runtime inside the Dexter pod. The command prompts for the password and passes it on standard input, which keeps it out of your shell history and process list:

    printf 'Admin password: '; read -rs ADMIN_PASSWORD; echo
    ADMIN_HASH=$(printf '%s' "$ADMIN_PASSWORD" | kubectl -n dexter exec -i deployment/dexter -- \
      bun -e 'console.log(await Bun.password.hash(await Bun.stdin.text()))')
    unset ADMIN_PASSWORD
  2. Create a secret that holds a session key and the admin account. Replace <ADMIN_EMAIL> with the admin’s email address:

    ADMIN_USER=$(printf '[{"id":"admin","email":"%s","name":"Admin","passwordHash":"%s"}]' '<ADMIN_EMAIL>' "$ADMIN_HASH")
    
    kubectl -n dexter create secret generic dexter-auth \
      --from-literal=SESSION_SECRET="$(openssl rand -hex 32)" \
      --from-literal=DEXTER_LOCAL_USERS="$ADMIN_USER"
  3. In dexter-values.yaml, uncomment the Sign-in section and set the admin email:

    env:
      DEXTER_AUTH_REQUIRED: "1"
      DEXTER_ADMIN_EMAILS: "<ADMIN_EMAIL>"
    envFromSecrets:
      - dexter-auth
    yaml
  4. Apply the change:

    helm upgrade dexter oci://us-east1-docker.pkg.dev/mvp-demo-301906/kfuse-helm/dexter \
      --namespace dexter \
      --version <VERSION> \
      -f dexter-values.yaml
  5. Wait for Dexter to restart, open it through a port-forward, and sign in at http://localhost:3000 with <ADMIN_EMAIL> and the password you chose:

    kubectl -n dexter rollout status deployment/dexter
    kubectl -n dexter port-forward svc/dexter 3000:3000
To sign in through your identity provider (Okta, Google, or Azure AD) instead of a local account, open Dexter through the port-forward before you turn on sign-in, add the provider under Admin > Identity providers, and create the secret with SESSION_SECRET only.

6. Serve Dexter on your domain

Skip this step to keep Dexter private and reach it through a port-forward.

  1. In dexter-values.yaml, uncomment the Public access section and set host to the DNS name for Dexter:

    ingress:
      enabled: true
      host: <HOST>
    yaml
  2. Apply the change with the same helm upgrade command as in step 5. Dexter gets its own load balancer, HTTPS with a Let’s Encrypt certificate, and signs users in on https://<HOST>;.

  3. Find the load balancer’s EXTERNAL-IP:

    kubectl -n dexter get svc -l app.kubernetes.io/instance=dexter,app.kubernetes.io/component=controller
  4. Create a DNS A record that points <HOST> at that address. cert-manager issues the certificate a minute or two after the name resolves. Check it with the following command. After READY shows True, allow a few seconds before HTTPS serves the certificate; until then, Dexter’s ingress controller presents a self-signed placeholder:

    kubectl -n dexter get certificate
The chart adds the load balancer only after sign-in is required (step 5), and stops with a message if cert-manager is not installed. If the cluster already runs an ingress controller, use it instead: add ingress-nginx.enabled: false to the values file and set ingress.className to that controller’s IngressClass.
The cloud assigns the load balancer’s address, and it changes if the load balancer is ever recreated. To keep one address for good, reserve a regional static IP in the cluster’s region before this step and set it in dexter-values.yaml as ingress-nginx.controller.service.loadBalancerIP (the values file shows where). The load balancer takes that address, so the DNS record never has to change. A global address, the kind a GCE Ingress uses, cannot be assigned to it.

7. Connect Anthropic and Kloudfuse

  1. Open Dexter at https://<HOST>;, or at http://localhost:3000 through the port-forward if you skipped step 6, and sign in.

  2. Under Settings > Connections, connect:

    • Anthropic: your Anthropic API key or Claude Max OAuth token.

    • Kloudfuse: the MCP address of your Kloudfuse cluster, https://<KLOUDFUSE_HOST>/mcp, and its service account token.

Dexter stores both on its persistent volume, so they survive restarts and upgrades.

Verify

curl https://<HOST>/readyz

The command returns {"status":"ok"}. If you skipped step 6, run it against http://localhost:3000/readyz while the port-forward is open. Then create an incident to confirm that Dexter can read your telemetry.