Skip to content

Terminal

A real browser PTY into your cluster context with the standard CLI tooling pre-installed, no local setup required.

Tier: Free


What it does

The Terminal is a full xterm.js terminal running in the browser, backed by a real PTY with a pre-configured KUBECONFIG for the current cluster (unless the install withholds those credentials — see below). It supports multiple concurrent session tabs, each an isolated bash subprocess, and copy-on-select — highlighting text copies it to your clipboard automatically, without a separate keystroke.

The Terminal is for admins only. It is not shown in a viewer's or developer's sidebar, and the server refuses to open a session for them. API keys cannot open one either.

Node.js is in the image and npm's global prefix points at $HOME/.npm-global, which lives on the PVC-backed home directory, so npm i -g <pkg> installs any CLI you want without root and it survives both new sessions and pod restarts.

A short-drop reconnect keeps a refresh or brief network blip from losing your session — the server holds the PTY for about two minutes after the socket detaches (TERMINAL_SESSION_TTL, default 120s), replaying the output buffer so the shell state and scrollback survive. Past that window the session is reaped and you start a new one. A session you keep open is never ended for being idle, by default: watching k9s or tailing logs involves no typing. To end idle sessions, set terminal.idleTimeoutSecs to a number of seconds.

Opening the Terminal tab does not by itself spawn a shell; starting a session is an explicit action, and each session belongs to one account and one browser tab, so a duplicated tab can't silently attach to someone else's shell.

The UI shows a memory gauge for the terminal container as a whole (used / limit), which surfaces as a warning as it approaches the cap. Every session in the pod draws from that one pool: memory is bounded by the container's memory limit rather than per session, so tools such as kubectl, helm and k9s start normally.

Up to 8 sessions can be open at once across the install (PTY_MAX_SESSIONS), counting sessions that are waiting to reconnect. Each session may start up to 512 processes (PTY_MAX_PROCS).

The session's KUBECONFIG uses the terminal's own ServiceAccount, <release>-terminal — not KubeManta's. KubeManta issues it a short-lived token (valid for one hour, renewed automatically), so the shell has exactly the permissions that account was granted and nothing more. It can read what the product reads, with one difference: Secrets.

  • The shell can never read a Secret in KubeManta's own namespace — the admin password, the encryption key, the Expert Mode credential and the licence are kept there, and a terminal user who read them could act as someone else. Listing that namespace in a setting below does not change this.
  • Elsewhere it reads Secrets only in namespaces you name in terminal.secretsNamespaces (read only: get, list, watch). Kubernetes RBAC cannot grant "every namespace except one", so on a default (cluster-wide) install kubectl get secret in the shell is refused everywhere, while the product's own Secret views keep working. Listing a namespace there does not change what the product reads. Two entries stop the install with an error: KubeManta's own namespace, and a namespace where KubeManta itself is not allowed to read Secrets (the shell's access is issued by KubeManta, so it can never exceed KubeManta's).
  • For one more release the shell also still reads Secrets where rbac.secretsNamespaces (or rbac.tenantNamespaces when rbac.clusterWide=false) names a namespace, so an upgrade does not take that away silently. This is deprecated: the install notes list those namespaces; copy them into terminal.secretsNamespaces.

On a default install there is no write verb on your workloads either, so kubectl delete, apply and similar are refused by the API server; write verbs are granted only when the chart is installed with rbac.allowWrites=true (default false). Even then the shell can change nothing in KubeManta's own namespace: with rbac.clusterWide=false its permissions there are read-only, and on a cluster-wide install an admission policy the chart installs (Kubernetes 1.30+) refuses every change it attempts there, kubectl exec included. On a cluster that cannot run that policy the shell gets no write verbs at all, and the install notes say so.

Nothing the shell can read opens a terminal session. Each session is authorised by a short-lived, single-use token that KubeManta signs with a key it generates in memory when it starts; that key is never stored in a Secret, on disk or in an environment variable, and the terminal container holds only the half that checks a signature. So a terminal user who reads everything the shell can reach still cannot attach to another user's session, read another user's captured commands, or open a shell that is not recorded. There is nothing to configure. Releases before 1.4.0 took this key from terminal.signingKey, which is no longer read; the <release>-terminal Secret those releases created can be deleted.

Those Kubernetes permissions are the only boundary that applies inside the shell. KubeManta's namespace allowlist and its blocklist filter the product's own views, AI and MCP surface; the shell does not go through them, so kubectl -n <namespace> there reaches whatever the terminal's ServiceAccount may read. Two settings change that, and they are different instruments. rbac.clusterWide=false with rbac.tenantNamespaces makes the API server itself refuse everything outside the namespaces you list, for the product and the shell alike. terminal.clusterCredentials.enabled=false applies to the shell alone: no token is issued to the terminal and nothing is mounted where one would be, no KUBECONFIG is written, the in-cluster environment variables are removed from the shell, and a kubeconfig left on the home volume by an earlier session is deleted. The terminal still opens and every other view keeps working — kubectl in it simply has no credentials until you supply your own.

Expert Mode does not change the shell's credentials. It governs the agent's own privileged actions, which run in a separate expert-exec pod holding a cluster-admin token. The shell cannot call that pod — it needs credentials only the agent container holds — and it cannot exec into it, into the agent container or into anything else in KubeManta's namespace, at any setting (see above). With rbac.allowWrites=true, though, the terminal's ServiceAccount may create and exec into pods in your other namespaces, and a cluster where some ServiceAccount in those namespaces is highly privileged lets a pod borrow it: treat allowWrites as cluster-admin-equivalent for anyone who can open this terminal. The product's own exec view always refuses KubeManta's namespace. Expert Mode takes two steps: expertMode.enabled=true at install to deploy that pod, then the runtime toggle in the terminal header bar, which is off by default. While it is on the terminal marks the state clearly, so you always know whether it is active.

What this shell is, and what it is not

The terminal is a hardened container shell, not a virtual machine. It runs as an unprivileged user with no added Linux capabilities, no privilege escalation, and — unless your install turns that off — a read-only root filesystem. Two consequences are worth stating plainly, because both surface as command not found rather than as a permission error:

  • No system package manager. apt, apt-get and yum need root and a writable root filesystem, and the shell has neither. Nothing you install goes into /usr.
  • No container runtime. docker and podman are not in the image, and a shell inside a pod has no socket to talk to. To run a container, apply a workload to the cluster — which is what kubectl in this shell is for.

What you can install is anything that lives in your own home directory, which is on the persistent volume and survives both new sessions and pod restarts:

  • npm i -g <pkg> — npm's global prefix is redirected to $HOME/.npm-global, so this needs no root and persists.
  • pip install --user <pkg> — lands in $HOME/.local/bin.
  • A binary you copy to $HOME/bin.

$HOME/bin and $HOME/.local/bin are both on PATH in every session, so a tool installed by any of those routes runs by name.

Setup

Open additional session tabs with the + button in the session bar. Run kubectl, helm, k9s, or any standard Linux tool against your cluster directly.

Change the text size with the − and + buttons in the terminal header bar; the figure between them shows the current size, and clicking it resets to the default. With the terminal focused, Ctrl+= (larger), Ctrl+- (smaller) and Ctrl+0 (reset) do the same — ⌘ instead of Ctrl on a Mac. The size runs from 10 to 28 px, applies to every session at once, and is remembered for your account in this browser, so it survives reconnects and carries over to terminals you open in other tabs. The shell is told its new width and height each time, so full-screen tools such as vim, less and k9s redraw to fit. Outside the terminal those keys keep their usual meaning (the browser's page zoom). Like every other shortcut, the three can be rebound under Keyboard shortcuts → Customize.

Commands typed into the shell are not governed like the product's other write paths — there is no approval step, no blast-radius window, and no circuit breaker. The terminal is kubectl, and a limit on a person's own shell could cut them off in the middle of an incident. The control is visibility instead: every submitted command is captured, attributed to an account, and retained for audit (180 days by default), and opening and closing a session is audited. An install can turn command capture off with terminal.commandCapture.enabled=false; session open and close are still audited.

Troubleshooting

If a session appears "stuck" after a network blip or a laptop sleep, wait for the ~120s reconnect window (TERMINAL_SESSION_TTL) before assuming the shell is gone — reconnecting inside that window replays the output buffer and restores scrollback. Once the window has passed, the session is reaped server-side and the only option is to start a new one; nothing recovers a shell past that point. If a connection keeps dropping before you can act, check that your proxy or load balancer isn't closing idle WebSockets — the client pings every 25s to keep them open.

If a new session reports Too many terminal sessions are open on this pod, the install-wide session limit is reached. Close a session you no longer need, or wait for a disconnected one to pass its reconnect window, then start again.

If the terminal reports that it is not configured on this install, the agent could not publish the key the terminal checks sessions against. That happens when the agent image is newer than the chart that deployed it; upgrade the chart to the matching version.

If kubectl reports that there is no configuration — or that the connection to localhost:8080 was refused — the install sets terminal.clusterCredentials.enabled=false and the shell holds no cluster credential by design; use the product's views, or supply your own kubeconfig.

If kubectl delete or apply fail from inside the terminal with a permissions error, the ServiceAccount does not hold the write verb: a default install holds no write verb on your workloads, deliberately, and granting terminal writes means reinstalling with rbac.allowWrites=true. Expert Mode is not the flag here and turning it on will not change the result.


Generated from KubeManta 1.5.0 — this page is rendered from the product's own documentation, so it cannot drift from what ships. Manifest built 2026-11-03T12:53:14Z.