Skip to content

Install

KubeManta installs via Helm from a private OCI registry. Your license key authenticates image pulls — there is no separate pull token to manage.

One page, one command

Everything you need is here. The builder below assembles the exact helm command for your cloud, load balancer and certificate — no other page has a different version of it.

Docs for the version you run

This site keeps the documentation for each KubeManta release line. Pages under /latest/ describe the newest release; if you run an earlier one, pick it from the version selector in the header so the commands and flags match your chart.

No internet access where KubeManta runs? Once it is installed, the Documentation page inside KubeManta is served by your own installation: the product manual and quick answers for exactly the version you installed, readable on an air-gapped network. You need this page before KubeManta is running, so keep a saved copy of it for the install itself.


Prerequisites

  • kubectl configured and pointed at your target cluster
  • Kubernetes 1.30 or newer (the pre-install check refuses an older cluster)
  • helm 3.14 or newer (OCI registry support needs 3.8; the --reset-then-reuse-values upgrades on this page need 3.14)
  • A KubeManta license key — get one free at kubemanta.com

Enter your email and the key arrives by return, along with the exact helm commands for your key. Free licenses unlock the read-only core plus alerting (unlimited rules to Slack, Telegram or email) and the MCP server; Pro adds AI, Helm write operations, and the alerting extras — auto-investigation, firing history, and the PagerDuty/webhook integrations.


Required flags

Every install needs these. Everything else has safe defaults.

Flag Required Description
license.key Yes Your KubeManta license key — auto-creates the registry pull secret
global.hostname Yes (for Ingress) Public hostname, e.g. km.example.com
global.ingressClassName Recommended gce · alb · nginx, or any installed class. Unset, the Ingress goes to the cluster's default IngressClass.
global.tls Yes (for Ingress) true for HTTPS · false for HTTP-only
security.cookieSecure No Default auto: on when global.hostname and global.tls=true are set. Set true explicitly when TLS terminates at your own edge with ingress.enabled=false.
global.acmCertificateArn EKS + TLS only ACM certificate ARN
rbac.allowWrites No Default false (read-only). Set true to enable pod restart/delete, deployment scale.
expertMode.enabled No Default false. Set true for Helm write ops and Resource Builder apply (a separate cluster-admin pod). The browser terminal does not need it.
metrics.kubeletScrape.enabled No Default true. Charts pod network bandwidth without Prometheus, scraped from each kubelet's cadvisor and authorized against nodes/metrics — the metrics endpoints only. CPU/memory work either way. Details below.
agent.anthropicApiKey No Server-side key for alert auto-investigation and scheduled reports. Never exposed to terminal sessions — the terminal is bring-your-own-LLM.

global.hostname is what creates the Ingress. global.ingressClassName (or ingress.className) is optional: left unset, the Ingress goes to the cluster's default IngressClass, and the pre-install check fails if there is none.

Secure by default: a vanilla install cannot change your workloads — it holds no write verb on anything you run, and writes only inside its own namespace. Add --set rbac.allowWrites=true for write features (this also applies to kubectl in the browser terminal, whose own ServiceAccount follows this flag everywhere except KubeManta's own namespace); add --set expertMode.enabled=true for Helm write ops.


Authenticate to the registry

KubeManta's images and chart are served from registry.kubemanta.com, gated by your license key. Log in once with Helm (the username is always license) — this lets Helm pull the chart, and the in-cluster pull secret handles image pulls:

echo '<LICENSE-KEY>' | helm registry login registry.kubemanta.com \
  --username license --password-stdin

Use --password-stdin, not --password

Passing the key as --password <LICENSE-KEY> writes it into your shell history and into the process list, where anyone else on the box can read it. Piping it on stdin does not. This is the same command the license email sends you.


Every pod KubeManta runs meets the Kubernetes restricted Pod Security profile, but nothing enforces that until the namespace says so, and the chart does not own the namespace. Create and label it before installing:

kubectl create namespace kubemanta-system
kubectl label namespace kubemanta-system \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/warn=restricted \
  pod-security.kubernetes.io/audit=restricted

warn and audit alone report a violation without refusing the pod, if you want to watch first. Under enforce=restricted the optional Network Analyzer node probe, which needs host networking, is refused and says so; probes from a pod source are unaffected. --create-namespace in the install commands is then a no-op, and helm install prints this reminder when the namespace has no Pod Security label.


helm install vs helm upgrade

The commands below use helm upgrade --install, which both creates the release and updates an existing one — convenient when you are re-running a documented scenario or driving it from automation.

For a first install by hand, helm install is the clearer command, and it is what your license email contains. Afterwards, use helm upgrade to change a setting or move to a new version — helm install fails once the release exists:

# change a setting later; --reset-then-reuse-values keeps everything you set
helm upgrade kubemanta oci://registry.kubemanta.com/kubemanta/charts/stable/kubemanta \
  --namespace kubemanta-system --reset-then-reuse-values \
  --set global.hostname=km.example.com

Use --reset-then-reuse-values, not --reuse-values

--reuse-values replays the previous release's computed values, which freezes every chart default at whatever it was when that release was created — so later improvements never reach your install, silently and with no error. An install carrying a 30-minute session timeout will keep it for as long as it lives after the chart default becomes 8 hours, with no override set anywhere and nothing to indicate it.

--reset-then-reuse-values takes the new chart defaults and re-applies your explicit values on top, which is what "keep my settings, take your improvements" actually means.


Build your install command

Answer five questions. Every flag below is validated against the chart itself, so the command it produces is the same one this page would tell you to write by hand — there is no second version to keep in sync.

1. Where are you installing?

2. Who owns the load balancer?

3. TLS certificate

4. Features

5. Details

No license key? Get a free one — the Free tier costs nothing and has no time limit; the key is what authenticates image pulls. A paid key unlocks Pro or Enterprise. See Free vs Pro.

Your install command

Step 1 — sign in to the registry with your license key (the chart is license-gated; an anonymous pull is refused):

Step 2 — install:

Using a load balancer you already run?

Choose "I already have one" above. The wizard drops the chart's Ingress and reminds you of the two things that are easy to miss: trusting your edge's source CIDRs, and routing the terminal WebSocket to the agent Service. Exposure & Load Balancers has the full topology detail and per-cloud worked examples.


KubeManta is read-only by default, deliberately. Some of the flags above change that, and they are worth understanding rather than pasting:

Flag What it turns on What it grants
rbac.allowWrites=true Pod restart/delete, deployment scale, apply manifests, pod exec — and the same writes for kubectl in the browser terminal, whose own ServiceAccount follows this flag Adds write verbs to the reader ClusterRole cluster-wide. Pod create and pods/exec reach every pod in scope, including the Expert Mode pod, so treat this as cluster-admin-equivalent for anyone who is a KubeManta admin. The terminal's account can change nothing in KubeManta's own namespace, but in your other namespaces a pod it creates can borrow any ServiceAccount there.
expertMode.enabled=true Helm install/upgrade/rollback, Resource Builder apply Deploys a separate expert-exec pod holding a cluster-admin token. It accepts connections only from the agent, and every use is audited. Where it may connect to is limited only when you also set expertMode.networkPolicy.egress.enabled=true (Helm values).
security.scanning.enabled (on by default) Vulnerability Scanner: read your trivy-operator reports; an admin can trigger a scan Read-only access to trivy-operator CRDs — never a write to your cluster. Set =false to turn scanning off. The built-in self-scan is a separate Pro feature that additionally needs expertMode.enabled.
metrics.kubeletScrape.enabled (on by default) Network bandwidth charts without Prometheus The kubelet authorizes the scrape against nodes/metrics — metrics endpoints only. Set =false to turn it off; CPU and memory are unaffected. Only viaProxy=true grants the broader nodes/proxy.

Drop any you do not want — each is independent, and the product degrades cleanly rather than breaking.

One thing stays off even in a "full" install, on purpose:

  • security.airgap.enabled=true — a deny-egress NetworkPolicy for sealed networks. Follow the Air-gapped install guide, which mirrors the images into your registry and turns this on for you; licensing then works offline from a licence file.

Two features are not Helm flags at all — configure them after install:

  • AI — add a provider key in Admin → AI. Nothing is sent anywhere until you do.
  • SSO (Enterprise) — Admin → Auth.

Network access (egress allowlist)

KubeManta runs entirely inside your cluster. If your nodes sit behind an egress firewall, an EgressNetworkPolicy, or a proxy that blocks outbound traffic by default, allow the domains below. Connections are outbound from KubeManta's pods (the agent, and the scan Jobs it starts) and are HTTPS (TCP 443) unless a row says otherwise (email alerts use your SMTP relay's port). Only two are ever required by KubeManta itself; everything else is feature-gated — if you don't use the feature, you don't need the domain. Your nodes also pull a few public images, listed under Network Egress → Images your nodes pull.

Always required

Domain What it's for When
registry.kubemanta.com Pull the license-gated agent, UI, and Helm-chart OCI images. Fronted by Cloudflare, so also allow Cloudflare edge IPs if you filter by IP rather than SNI. Install & upgrade only (image pull).
api.keygen.sh License validation (Keygen) and a heartbeat that keeps this cluster's activation alive. Validates every tier, including Free, and caches the result, so a brief outage is tolerated (offline grace), but a permanent block eventually disables licensed features. By default the heartbeat also reports the cluster's node count — a number only, never used to charge you; license.reportNodeCount=false in your Helm values keeps it in the cluster. Validation every 12 hours, heartbeat every 6 hours. Not contacted by an air-gapped install with an offline licence file.

Restricted egress, or no internet at all

With a local Ollama AI provider (or AI disabled) and the update check left off (the default), the only egress KubeManta needs is registry.kubemanta.com at install time and api.keygen.sh for licensing, plus Docker Hub for the preflight image unless you mirror it. A cluster with no internet access needs none of them: see Air-gapped install.

Optional — AI features

Needed only when AI is enabled and you use that provider. In AI Guardrails (Admin → AI → Guardrails), Data residency decides which providers may be called at all: a provider not ticked under Allowed Providers is refused, and Local Only refuses every provider you do not host yourself (only Ollama or a Custom endpoint remain). Egress Control can additionally enforce a deny-by-default allowlist of the hosts the AI path may reach.

Domain What it's for
api.anthropic.com Anthropic Claude — the default provider for AI Diagnose, the Copilot, and autonomous alert investigation, and the Claude Code CLI inside the browser terminal.
console.anthropic.com, claude.ai Claude Code OAuth login in the terminal (per-user sign-in; only if operators authenticate Claude Code interactively rather than with an API key).
api.openai.com OpenAI provider (if selected).
generativelanguage.googleapis.com Google Gemini provider (if selected).
api.groq.com Groq provider (if selected).
<resource>.openai.azure.com Azure OpenAI provider — your own resource endpoint (if selected).
(your endpoint) Custom OpenAI-compatible provider — whatever base_url you configure. An in-cluster Ollama needs no egress.

Optional — other features

Domain What it's for Enabled by
api.kubemanta.com In-product update check ("a newer version is available"). Outbound-only and sends no cluster data. Off by default. Opt in with updates.checkEnabled=true or the toggle in Admin → License.
mirror.gcr.io, ghcr.io, pkg-containers.githubusercontent.com Trivy vulnerability database, Java database and checks bundle, downloaded by each container self-scan (the scanner image itself, aquasec/trivy, comes from Docker Hub). Not needed when you only read your own trivy-operator's reports, or when you mirror the databases. security.scanning self-scan.
acme-v02.api.letsencrypt.org Let's Encrypt ACME certificate issuance. cert-manager TLS (installCertManager / a Let's Encrypt issuer).
hooks.slack.com, api.telegram.org, events.pagerduty.com, api.datadoghq.com, sns.<region>.amazonaws.com, (your webhook host) Delivering alert notifications to the integration you configure. Alert integrations.
(your SMTP relay) Email alerts — the host and port you set (default 587; SMTP, not HTTPS). Email alert integration.
slack.com and *.slack.com Slack ChatOps (ask and approve from Slack): the Slack Web API, then a long-lived Socket Mode WebSocket to the address Slack hands back. Slack ChatOps.
(your Jira address), api.trello.com Incident tickets. Ticketing integration.
(your identity provider) The OIDC issuer, SAML metadata URL or LDAP server you configure. SSO (Admin → Auth).
(your S3-compatible bucket endpoint) Database backup — the one feature that copies KubeManta's database out of the cluster. persistence.replication.enabled (off by default).
AWS sts.*/ec2.*.amazonaws.com, GCP compute.googleapis.com, Azure management.azure.com Multi-cloud network topology (VPC/subnet inventory) — only the cloud(s) you add credentials for. Cloud credentials (Admin → Cloud).

The complete list, with the Helm value or setting behind each entry, is on Network Egress.

IMDS is blocked by design

The bundled NetworkPolicy blocks the cloud metadata endpoint (169.254.169.254) from the agent pod. Cloud topology uses the credentials you provide, not node IAM — so blocking IMDS does not affect it.


After install

Your version's own reference is now one click away

Once you are signed in, the Documentation tab inside KubeManta is the technical reference: API paths, environment variables, RBAC verbs, failure modes and exact --set flags, served by the build you just installed rather than by a website that may describe a different one. Read it there whenever a page here and your cluster seem to disagree — the in-product copy is the one that matches what is running.

Get your admin password

The admin password is set at install time — there is no first-login setup step (setting a password from a public URL is blocked by design). If you provided security.adminPassword, use that. Otherwise the chart auto-generates a stable one; retrieve it:

kubectl get secret kubemanta-admin -n kubemanta-system \
  -o jsonpath='{.data.password}' | base64 -d ; echo

Log in as the admin user with that password. Change it anytime (the install seed never overwrites an already-set password):

kubectl exec -it -n kubemanta-system deploy/kubemanta-agent -- \
  python3 -m app.recover_admin --username <you> --password-stdin

DNS

# Get the load balancer address
kubectl get ingress kubemanta -n kubemanta-system \
  -o jsonpath='{.status.loadBalancer.ingress[0].ip}{.status.loadBalancer.ingress[0].hostname}'

Create an A record (GKE/AKS, or an in-cluster controller) or CNAME record (EKS) pointing your hostname at the address above.

Verify

# Agent health
kubectl exec -n kubemanta-system deploy/kubemanta-agent -- \
  python3 -c "import urllib.request; print(urllib.request.urlopen('http://localhost:8080/healthz').read())"

# Pod status
kubectl get pods -n kubemanta-system

# Stream logs
kubectl logs -n kubemanta-system deploy/kubemanta-agent -f
kubectl logs -n kubemanta-system deploy/kubemanta-ui -f

Cluster metrics (metrics-server)

KubeManta's node and pod CPU/memory utilization reads the Kubernetes metrics.k8s.io aggregated API, served by metrics-server. There is nothing to configure in KubeManta — the agent reads it in-cluster via its ServiceAccount (the reader role already grants metrics.k8s.io read). But metrics-server must be present in the cluster, and it is not on every distribution.

Check first

kubectl top nodes — if it returns CPU/memory, you're done. If it says "Metrics API not available", install metrics-server below. Until then the utilization panels show a "metrics unavailable" hint (everything else works).

Platform metrics-server What to do
GKE Pre-installed (managed add-on) Nothing
AKS Pre-installed (managed add-on) Nothing
k3s / k0s / microk8s Bundled Nothing (microk8s: microk8s enable metrics-server)
EKS Not installed by default Install (below) — omit the --kubelet-insecure-tls step
kubeadm / bare-metal / vanilla Not included Install (below) — keep the --kubelet-insecure-tls step

Install

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

# BARE-METAL / kubeadm ONLY — kubelet serving certs are self-signed, so
# metrics-server can't verify them. (Skip this on EKS, where the certs are valid.)
kubectl patch deployment metrics-server -n kube-system --type=json \
  -p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'

kubectl -n kube-system rollout status deploy/metrics-server --timeout=120s
kubectl top nodes    # should now list every node with CPU + memory

metrics-server is a lightweight (~50 MiB) read-only scraper. Once it reports, KubeManta's utilization populates within about a minute (metrics are cached briefly). KubeManta also samples metrics-server in the background to build its own short-term CPU/memory trend charts (about 7 days of retention, Metrics → Built-in) — no Prometheus needed. A Prometheus connected via Admin → Observability remains a separate integration for long-retention history, your application metrics, and ad-hoc PromQL (see Metrics).


metrics-server exposes no network metrics. Pod network bandwidth trends in the Metrics tab therefore come from cadvisor, which already runs inside every kubelet — nothing to deploy. KubeManta scrapes it with its own ServiceAccount, and this is on by default:

# Turn it off, if you would rather not have it:
  --set metrics.kubeletScrape.enabled=false

What it grants:

  • The agent dials each kubelet directly, and the kubelet authorizes that against nodes/metrics — the metrics endpoints and nothing else. No exec, no logs, no arbitrary proxying. That narrow grant is why this is on by default.
  • No new components and no egress.

If port 10250 is firewalled from pods, the scrape cannot reach your kubelets. In that case route it through the API server instead:

  --set metrics.kubeletScrape.viaProxy=true

Be deliberate about that one: it is the only setting that grants nodes/proxy, a much broader verb that reaches every kubelet handler, including exec and logs. Prefer the direct scrape wherever it works.

What you get / lose:

  • On (default): RX/TX bandwidth trend charts on the Network page, with counter-reset and gap handling built in.
  • Off: CPU/memory metrics and trends are unaffected — only the bandwidth charts stay empty, with an in-product hint. The scrape is fail-soft: if it cannot reach a kubelet it records the reason and skips, rather than reporting zero.

If you already run a cluster-scraping Prometheus you can set the metrics source to prometheus instead (Admin → Observability can generate the scrape config for it).


Restricted / policy-enforced clusters (OPA Gatekeeper, AKS Azure Policy, Kyverno)

KubeManta ships hardened by default — there is no profile flag to flip. Every container renders with CPU + memory limits, runAsNonRoot, a read-only root filesystem (writable /tmp and cache via emptyDir), all Linux capabilities dropped, the RuntimeDefault seccomp profile, an AppArmor profile (securityContext.appArmorProfile), and projected ServiceAccount tokens (automatic token mounting is off on the pods that talk to the API server, each given an explicit projected token volume). This clears the common Gatekeeper "baseline" / "restricted" bundles out of the box. For Pod Security Admission, label the namespace as described in Enforce Pod Security so the API server enforces the restricted profile the pods already meet.

Two things a policy-enforced cluster still enforces that a Helm chart cannot satisfy for you — configure them on the cluster side:

  • Allowed container images. Add the KubeManta images to your image-allowlist constraint (or mirror them into your approved registry and override the *.image.repository values accordingly):

    • registry.kubemanta.com/kubemanta/* — the agent and UI (license-gated)
    • python:3.12-alpine — the pre-install validation hook (preflight.image; air-gapped? --set preflight.enabled=false)
    • aquasec/trivy:* — the container self-scan Job (security.scanning.selfScan.image)
    • nicolaka/netshoot:* — the Network Analyzer's active probe (netAnalyzer.probeImage)
  • Service / ingress constraints. If a policy restricts Service ports or requires HTTPS-only Ingress, allow KubeManta's ports and front the UI with your own TLS edge (ingress.enabled=false + your own gateway is supported).

Relax knobs if a policy or user tooling collides

Two escape hatches let you relax the settings most likely to collide with a customer's tooling — everything else stays hardened:

  • security.appArmorProfile — default runtime/default; set to unconfined to emit no AppArmor profile at all, or localhost/<name> to pin a custom loaded profile.
  • terminal.readOnlyRootFilesystem — default true; set false if a terminal user's tooling insists on writing outside $HOME and /tmp (both stay writable regardless). Every other container's root filesystem stays read-only unconditionally.

A load balancer but no ingress controller (TLS inside KubeManta)

If your cluster can create a LoadBalancer Service but runs no ingress controller, KubeManta can terminate HTTPS itself, in a small proxy inside the UI pod, and still record each user's real address. Create a TLS Secret first, then:

kubectl create secret tls kubemanta-tls -n kubemanta-system \
  --cert=fullchain.pem --key=privkey.pem

helm install kubemanta oci://registry.kubemanta.com/kubemanta/charts/stable/kubemanta \
  --version CHART_VERSION \
  --namespace kubemanta-system \
  --set license.key='YOUR_LICENSE_KEY' \
  --set ingress.enabled=false \
  --set tlsSidecar.enabled=true \
  --set global.tlsSecret=kubemanta-tls \
  --set ui.service.type=LoadBalancer \
  --set ui.service.externalTrafficPolicy=Local \
  --set security.trustedProxyCidrs="<your pod CIDR>"

The UI Service then serves HTTPS on port 443 only, and the terminal works through the same address. This mode has not yet been verified against a live cloud load balancer. Full guide, including certificate renewal: Exposure → Mode 8.


Restrict to specific namespaces

By default KubeManta auto-discovers all non-system namespaces. To limit the namespaces KubeManta shows and acts on:

helm upgrade kubemanta oci://registry.kubemanta.com/kubemanta/charts/stable/kubemanta \
  --version CHART_VERSION \
  -n kubemanta-system --reset-then-reuse-values \
  --set "tenantNamespaces[0]=my-app" \
  --set "tenantNamespaces[1]=staging"

tenantNamespaces is enforced by KubeManta's own views, AI and MCP surface, not by Kubernetes RBAC: the ServiceAccount can still read every namespace, and kubectl in the browser terminal is not bound by the list. It grants no write permission either. For a boundary the API server enforces, use rbac.clusterWide=false with rbac.tenantNamespaces — see Helm values → RBAC.

Which version?

Replace CHART_VERSION with the release you are installing. The newest is at the top of the Changelog, or read it from the registry once you are logged in:

helm show chart oci://registry.kubemanta.com/kubemanta/charts/stable/kubemanta | grep '^version:'

Always pin it. An unpinned install resolves to whatever stable points at today, which is not necessarily the release you tested against.


Bring your own TLS certificate

Terminate TLS in the cluster from a certificate you already hold. Create the Secret first — an Ingress can only reference a Secret in its own namespace:

kubectl create secret tls kubemanta-tls \
  --cert=fullchain.pem --key=privkey.pem \
  -n kubemanta-system

--cert must be the full chain, not the leaf alone

Leaf certificate first, then any intermediates. A leaf-only Secret still validates in a browser that happens to have cached the intermediate, and fails everywhere else — which is why this is usually reported as "works on my machine" rather than as a certificate problem. openssl s_client -connect host:443 -showcerts shows what is actually served.

Then point the chart at it. The builder above emits these flags when you choose Existing TLS Secret; to add them to a release that already exists:

helm upgrade kubemanta oci://registry.kubemanta.com/kubemanta/charts/stable/kubemanta \
  -n kubemanta-system --reset-then-reuse-values \
  --set global.tls=true \
  --set global.tlsSecret=kubemanta-tls \
  --set security.cookieSecure=true

If global.tlsSecret is left unset the chart still expects a Secret, defaulting to <release-name>-tls (kubemanta-tls for a release named kubemanta). Naming it per release is deliberate — two releases in one namespace would otherwise collide on a single certificate.

Not for ALB or Google-managed certificates

An AWS ALB reads certificates from ACM, and a Google-managed certificate is provisioned by GCP; neither consumes a Kubernetes Secret. The chart therefore omits spec.tls entirely for tlsProvider=acm and gcp-managed — on GKE a stray spec.tls referencing a missing Secret stalls load-balancer provisioning silently, with no error anywhere. Use this option with an in-cluster controller: Traefik, HAProxy, Contour.