Skip to Content
DocsCloud OSWeb Terminal

Web Terminal

Cloud OS includes a browser-based terminal that provides direct shell access to your server without requiring SSH.

The web terminal requires the web_terminal license feature. The local terminal runs as the quazzar service account with limited rights, not as root. Root access is in Control Center → Terminal (see below).

Accessing the Terminal

  1. Click Terminal in the dock (Server and Cluster modes), use Open Terminal in the command palette (Ctrl/⌘+K), or the Terminal quick action on the Overview widget board
  2. A floating terminal window opens; drag it by the title bar, resize it from the bottom-right corner, and close it with Ctrl+Esc or the ✕
  3. You get a bash shell as the quazzar user (see Limited rights); the window remembers its size and position

Features

FeatureDescription
Full PTYReal terminal with proper line editing, tab completion, and signal handling
ResizeTerminal automatically resizes when you resize the browser window
Copy & PasteStandard clipboard operations work (Ctrl+Shift+C / Ctrl+Shift+V)
Idle TimeoutSessions automatically close after 30 minutes of inactivity

How It Works

The terminal uses a WebSocket connection to a PTY (pseudo-terminal) on the server:

  1. The browser connects via WebSocket to /api/terminal/ws
  2. The server opens a PTY running /bin/bash as quazzar, in its own systemd scope (quazzar-terminal-<id>.scope)
  3. Keystrokes are sent from the browser to the PTY via WebSocket
  4. PTY output is streamed back to the browser in real time
  5. Window resize events are sent as control messages

Limited rights in the local terminal

The local terminal runs as quazzar and is not root-equivalent:

  • It is not in the docker group. docker ps, logs, start, stop and restart work only for containers Quazzar manages (labelled quazzar.managed=true). Other docker commands, such as docker run, answer “not available here”.
  • sudo is limited to a short list of Quazzar admin operations. Run quazzar-allowed to see them; sudo quazzar-setup priv list prints the same operations. A refused sudo (for example sudo cat /etc/shadow) prints that list, and exit code 126 shows a hint.
  • A banner at the start of the session says so.
  • Each session runs in its own systemd scope, so background jobs keep running when Cloud OS restarts.

For full root use Control Center → Terminal below. See Security Hardening for the complete model and its known limits.

Administrator confirmation

Some actions on files and packages need the administrator’s password on top of the admin role:

  • opening or changing root-owned files in the File Manager (and “read with password”);
  • adding or removing custom APT sources on the Packages page (the dialog asks for the password);
  • hooks of native apps that are not in the built-in catalogue.

Enter the password of root, or of a user in the sudo / admin / wheel group (an empty password never works). The confirmation lasts 15 minutes and is bound to your browser session; API keys can’t elevate. A wrong password counts against a limit of 5 attempts per minute per user. File Manager limits: writes up to 512 MiB, reads up to 64 MiB, no moves across disks, and system roots such as /, /etc, /usr, /var and /home can’t be deleted or moved.

Remote Terminal via Control Panel

When the node is enrolled in a Control Panel, workspace owners and admins can open a shell on it from the node’s Terminal tab in the Control Panel. The session runs over the node’s secure agent connection (no inbound port is needed).

The remote shell opens as root: a login shell with home /root, a clean environment and the host’s real filesystem (not the Cloud OS service sandbox). It runs in its own systemd scope, so restarting the Cloud OS service doesn’t kill what you started from it (the interactive shell itself ends with the connection). The local terminal on this page runs as the quazzar user with limited rights.

Every open carries a ticket that the Control Panel signs with its license key. A ticket is bound to this node, lasts about 90 seconds and works once. The node trusts the Control Panel’s key automatically from the first license it receives live from the Control Panel. Show the pinned key with sudo quazzar-cli admin cp-trust show; reset it with sudo quazzar-cli admin cp-trust reset (the next live license pins the new Control Panel). With an older Control Panel, a missing ticket or a refusal, you get the limited quazzar shell with a banner that explains why. Each root grant is logged in the node’s journal (tag quazzar-setup). Turn the switch below off if you don’t want anyone in the Control Panel to get root on this node.

You decide whether this node accepts it: Settings → Control Center → Remote shell from the Control Center. It is on by default for nodes enrolled in a Control Panel; only an admin of the node can change it, and turning it off ends any open remote session immediately. The setting is also available as GET / PUT /api/cc/remote-shell ({"enabled": true|false}).

Remote sessions close after 15 minutes without activity or 2 hours at most, and when the agent connection drops. At most four run at a time. The Control Panel records the start and end of every session in its audit log, and the node logs them in its own journal.

The remote terminal, the Control Panel’s Logs tab and other live features use the agent’s WebSocket tunnel, which is separate from the regular heartbeat. If the heartbeat works but the tunnel is down, Settings → Control Center shows Connected (tunnel reconnecting) (hover it for the last error) and the node keeps retrying; each attempt gives up after 30 seconds, and a tunnel that goes silent is dropped after 75 seconds and reconnected.

Security

  • Terminal sessions require JWT authentication
  • All terminal I/O is transmitted over encrypted WebSocket connections
  • Sessions are logged in the audit trail
  • Idle sessions are terminated after 30 minutes
  • The local terminal runs without root and without the docker group