Terminal Access
Proxima Console provides secure, browser-based interactive terminal access to managed hosts. Engineers connect to hosts directly from the Console UI without needing separate SSH tools.
Architecture
Key Features
- Browser-based — xterm.js terminal emulator in the Console UI, no plugins needed
- RBAC-controlled — Teleport-style role definitions control which users can access which hosts as which Linux users
- Deny-overrides-allow — deny rules always win, default deny for unlisted hosts/logins
- Label-based matching — roles match hosts by labels (env, client, etc.) from inventory data
- SSO-derived logins — role templates resolve Linux usernames from OIDC identity claims (e.g.,
{{.email_prefix}}), enabling dynamic login names without hardcoding every possible username - Session JWT signed with ed25519 — backend signs a short-lived (1 min) token using the NATS account keypair; agent verifies signature, expiry, and
agent_idbefore allocating the PTY - First-message WebSocket auth — the session token is sent as the first WebSocket message, never as a URL query parameter, preventing token leakage in server logs and browser history
- Audit logged — every session recorded in
terminal_sessionstable + audit log events - Idle timeout + TTL — configurable per-role, enforced by backend
- Auto-reconnect — sessions survive brief disconnects with configurable PTY linger (
disconnect_timeout, default 30s) - No new infrastructure — uses existing NATS for agent communication, no JetStream (Core NATS only)
- K8s node terminal — DaemonSet agents use
nsenterto enter the host namespace, providing full node access (processes, network, filesystem) from the browser - Auto-create host users — agent creates Linux users on connect when configured, with keep/drop lifecycle modes
- Sudoers management — per-user
/etc/sudoers.d/files written with mode0440, validated withvisudo, and cleaned up automatically in drop mode - Custom default shell — configurable per role; agent verifies the binary exists before use
- Stable UID ranges — deterministic UIDs computed via FNV-1a hash of the username, ensuring the same UID across all hosts (important for NFS/shared storage)
- Least-permissive multi-role merge — when a user holds multiple roles, options are merged with the most restrictive values winning
- Connect button on host list — hosts list and card view show an inline Connect button that opens a login dropdown; selecting a login navigates directly to the host terminal tab and auto-connects
- Admin session management — admins can list all active sessions and force-terminate any session
- Session recording — PTY output recorded in asciicast v2 format, stored in Cloudflare R2 with server-side encryption, playable with a custom xterm.js player with speed control and timeline scrubbing
Security Model
Terminal access uses a multi-layered security approach:
| Layer | Mechanism |
|---|---|
| Session authentication | Backend signs a short-lived (1 min) ed25519 JWT using the NATS account keypair. Agent verifies the signature, expiry, and host_id before allocating the PTY. No valid token = no shell. |
| Transport encryption | All NATS connections use TLS with strong cipher suites. WebSocket connections use WSS (TLS). |
| Subject isolation | NATS subscriptions use exact proxima.{client}.{env}.{host}.terminal.* subjects. Agent JWT permissions restrict publish/subscribe to the agent's own host prefix. |
| RBAC enforcement | Backend checks role's terminal_spec before issuing a session token. Deny rules override allow rules. |
| Login verification | Agent verifies the token's login claim matches the requested Linux user, preventing login substitution. |
Transport Security
PTY traffic (keystrokes and output) is encrypted in transit via NATS TLS between each hop. The backend relays traffic but does not store it. This is equivalent to how Teleport's proxy handles SSH sessions — the proxy terminates and re-encrypts the transport.
Requirements
- Proxima Agent v1.3+ deployed on target host
- User must have a role with
terminal:connectpermission and aterminal_specconfigured - Target host must have the requested Linux user account (or
create_host_user_modeset tokeep/drop) - Agent must run as root for host user auto-creation features (
useradd,chage, etc.). Without root, the agent still supports terminal access for pre-existing users - The following binaries must be available on the host for user management:
useradd,userdel,groupadd,usermod,getent,chage,visudo,chsh - Kubernetes DaemonSet agents support terminal access via
nsenter. The DaemonSet must havehostPID: trueand theSYS_PTRACEandSYS_ADMINcapabilities to enter the host's namespaces. See Node Agent K8s Deployment for the required security context.