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¶
kubectlconfigured and pointed at your target cluster- Kubernetes 1.30 or newer (the pre-install check refuses an older cluster)
helm3.14 or newer (OCI registry support needs 3.8; the--reset-then-reuse-valuesupgrades 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.hostnameis what creates the Ingress.global.ingressClassName(oringress.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=truefor write features (this also applies tokubectlin the browser terminal, whose own ServiceAccount follows this flag everywhere except KubeManta's own namespace); add--set expertMode.enabled=truefor 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.
Enforce Pod Security on the namespace (recommended)¶
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?
2b. How does that load balancer reach the cluster?
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.
What "full-featured" actually enables¶
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).
Bandwidth trends without Prometheus¶
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:
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:
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.repositoryvalues 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— defaultruntime/default; set tounconfinedto emit no AppArmor profile at all, orlocalhost/<name>to pin a custom loaded profile.terminal.readOnlyRootFilesystem— defaulttrue; setfalseif a terminal user's tooling insists on writing outside$HOMEand/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:
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.