Terminal Plugin
The terminal plugin is the reference SDK plugin implementation. It provides a WebSocket-based interactive shell relay so operators can open a live terminal session to any connected device directly from the Umoo platform — no separate SSH access or VPN required.
Overview
| Property | Value |
|---|---|
| Plugin ID | terminal |
| Tier | SDK (pluginsdk.BackendPlugin) |
| Version | 1.0.0 |
| HTTP routes | Yes — WebSocket + REST |
| Prometheus metrics | Yes |
| Bus subscriptions | evt.terminal.v1.*, cmd.terminal.v1.* |
| DB schema | Yes — session table |
HTTP Routes
All routes are mounted under /api/v1/plugins/terminal/ and go through the standard middleware stack:
Rate limit → JWT auth → Tenant auth → per-route RBAC check
| Method | Path | Permission | Description |
|---|---|---|---|
GET | /api/v1/plugins/terminal/ws/{device_id} | terminal/session:open | Upgrade to WebSocket; open interactive shell |
GET | /api/v1/plugins/terminal/sessions | terminal/session:read | List all currently active terminal sessions |
WebSocket Terminal (GET /ws/{device_id})
Opens a bidirectional WebSocket connection that relays raw terminal I/O between the browser and the target device agent.
Connection lifecycle:
- Client sends
GET /api/v1/plugins/terminal/ws/{device_id}withUpgrade: websocket. - Server validates RBAC (
terminal/session:open), looks up the device, and opens a relay channel via the message bus. - The device agent receives a
cmd.terminal.v1.opencommand and spawns a shell process. - Raw bytes flow bidirectionally: client → server → device, device → server → client.
- When either end closes, the server sends a
cmd.terminal.v1.closecommand and tears down the session.
Shell defaults:
| Config key | Default | Description |
|---|---|---|
shell | /bin/bash | Shell executable on the device |
persistence | true | Keep session alive if the WebSocket drops temporarily |
enable_color | false | Advertise TERM=xterm-256color to the shell |
⚠️ Docs correction: Earlier versions of the guide listed
/bin/sh,persistence=false, andenable_color=trueas defaults. The source-of-truth defaults are shown above.
List Sessions (GET /sessions)
Returns all sessions that are currently tracked by the server (connected or reconnecting).
Response (JSON array):
[
{
"session_id": "sess_abc123",
"device_id": "550e8400-e29b-41d4-a716-446655440000",
"tenant_id": "660f9511-...",
"user_id": "770a0622-...",
"opened_at": "2025-03-25T10:00:00Z",
"state": "connected"
}
]RBAC Permissions
Permissions are seeded automatically at startup (SDKPluginManager.Init()). They are stored in the platform permissions table and enforced by the same PermissionCache that guards ConnectRPC handlers.
| Permission | Default roles | Description |
|---|---|---|
terminal/session:read | viewer, operator, tenant_admin | List active sessions |
terminal/session:open | operator, tenant_admin | Open a WebSocket shell to a device |
To check programmatically from the Web UI:
can(perms, 'terminal/session', 'read') // show sessions list
can(perms, 'terminal/session', 'open') // show "Open Terminal" buttonMessage Bus
The terminal plugin publishes and subscribes on the following bus topics:
| Direction | Topic | Payload | Description |
|---|---|---|---|
| Subscribe | evt.terminal.v1.* | — | Incoming terminal state events from devices |
| Subscribe | cmd.terminal.v1.* | — | Internal command routing |
| Publish | cmd.terminal.v1.open | {session_id, device_id, shell, tenant_id} | Tell device agent to spawn a shell |
| Publish | cmd.terminal.v1.close | {session_id} | Tell device agent to terminate the shell |
Prometheus Metrics
All metrics are registered under the terminal_ namespace:
| Metric | Type | Labels | Description |
|---|---|---|---|
terminal_active_sessions | Gauge | — | Number of currently open WebSocket sessions |
terminal_sessions_opened_total | Counter | — | Lifetime count of sessions opened |
terminal_sessions_closed_total | Counter | — | Lifetime count of sessions closed |
terminal_bytes_relayed_total | Counter | direction (ingress|egress) | Total bytes relayed through the terminal proxy |
Plugin Configuration
Configuration is stored per-tenant using SetPluginConfig / GetPluginConfig RPCs (resource: plugin, action: write/read).
| Key | Type | Default | Description |
|---|---|---|---|
shell | string | /bin/bash | Shell to spawn on the device |
persistence | bool | true | Whether to maintain session on transient WebSocket disconnects |
enable_color | bool | false | Set TERM=xterm-256color in the shell environment |
max_sessions | int | 10 | Maximum concurrent sessions per tenant |
idle_timeout_sec | int | 300 | Seconds of inactivity before auto-closing a session |
Agent-Side Plugin
The device agent runs a corresponding terminal agent plugin that:
- Subscribes to
cmd.terminal.v1.opencommands addressed to its device ID. - Spawns the configured shell and attaches stdin/stdout/stderr.
- Relays I/O back to the server over the existing agent connection.
- Handles
cmd.terminal.v1.closeby sending SIGHUP to the shell process.
The agent plugin is hot-reconfigurable: if SetPluginConfig changes shell or enable_color, the change takes effect for new sessions without agent restart.
See Also
- Terminal User Guide — end-user walkthrough
- Auth & RBAC — full permission model
- WireGuard Plugin — another plugin reference