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) installkubectl get secretin 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(orrbac.tenantNamespaceswhenrbac.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 intoterminal.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-getandyumneed root and a writable root filesystem, and the shell has neither. Nothing you install goes into/usr. - No container runtime.
dockerandpodmanare 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 whatkubectlin 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.