Consoles
Every virtual machine has two consoles, as a physical server would: a **serial console** (text, what the guest prints on its first serial port) and a graphical console (its screen, keyboard and mouse). Both work whatever state the guest's network is in — they are how you rescue a machine that has locked itself out.
Part of Compute, in early access. In the browser, the node's web console opens both consoles for you; this page covers the node's command line and the local API underneath.
The serial console on the node
sudo cenvero-str-ctl vm console vm-3f9a1c2e
Your terminal becomes the machine's serial console. Everything you type goes to the guest, Ctrl+C included; Ctrl+] disconnects. Press Enter if the screen stays empty — the guest prints its login prompt again.
- One serial session per machine at a time.
--forcetakes it over from another Stratum session (that one is closed, and told why);--force=falseis the same as leaving it out. - If another program on the node has the machine's serial console open, the console is refused until that program lets go — and while you are connected, that program is refused. Neither ever silently takes the other's keystrokes.
- The machine must be running.
- Input from a pipe or a file instead of your keyboard (
echo … | … vm console) ends the session at the end of that input. - A terminal that stops reading (a suspended job, say) is disconnected once it has left the machine's output unread for 30 seconds, so it cannot hold the serial console.
- Closing the command with a signal (
kill, includingkill -INT) ends the session and puts your terminal back as it was.
Consoles over the API
The local API serves both consoles as WebSockets. A browser cannot put a token on a WebSocket, so you first ask for a ticket — single use, valid for 60 seconds, for one console of one machine:
curl -k -X POST "$NODE/api/v1/vms/vm-3f9a1c2e/console" -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" -d '{"type":"vnc"}'
{
"ticket": "q3J0…",
"expires_in": 60,
"path": "/api/v1/vms/vm-3f9a1c2e/console/vnc?ticket=q3J0…",
"type": "vnc"
}
Then open wss://<node>:7070 + path as a WebSocket:
type | Path | What flows |
|---|---|---|
vnc | …/console/vnc | The graphical console, as VNC (RFB) in binary frames. A standard noVNC client connects to it unchanged; the binary subprotocol is accepted |
serial | …/console/serial | The serial console's bytes. Text or binary frames from you; binary frames back |
Scripts may skip the ticket and send the operator token on the upgrade itself
(Authorization: Bearer …), for example with websocat. "force": true in the
ticket request (or ?force=true with a token) takes the serial console over, as
--force does above; force takes true or false.
A ticket is used up only by the WebSocket connection it was made for. A plain
GET of the path (a browser prefetching a link, a check with curl), a request
that is not a valid WebSocket handshake, or a page on another site is refused
without touching the ticket, so the real viewer can still use it.
Who may open one. An operator token or operator API key. A tenant-scoped key
opens the consoles of its own tenant's machines with a ticket from
POST /api/v1/tenant/{id}/vms/{vmid}/console (the tenant portal, see
API Reference); it is not accepted on the WebSocket itself, and
not while its tenant is suspended. A browser page on another site cannot open a console: the
WebSocket's origin must be the node itself or one you listed in
api_allowed_origins. Failed attempts count towards the API's lock-out, like
any other.
The local API must be enabled on the node (it is off by default — see Installation). The serial console on the node's command line works without it.
A machine on another member of a cluster
In a cluster (agent 1.0.0-rc.81 or later), any
member opens the consoles of every member's machines. Ask the member you are
connected to for the ticket, with /api/v1/nodes/<node id> in front of the
path, where <node id> is the member the machine runs on:
curl -k -X POST "$NODE/api/v1/nodes/7c9e6679-7425-40de-944b-e07fc1f90ae7/vms/vm-3f9a1c2e/console" \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"type":"vnc"}'
The answer's path is then
/api/v1/nodes/7c9e6679-7425-40de-944b-e07fc1f90ae7/vms/vm-3f9a1c2e/console/vnc?ticket=….
Open it on the same member you asked, which passes the console on to the
machine's node. A console on another member always needs a ticket from that
same member, asked for with the same key; a token sent on the WebSocket alone
is not enough. The member you call needs clustering in its licence, and tenant
keys open consoles only on the node that issued them. The machine's node applies
its own address allowlist (api_allowed_ips) to your address: if it does not
accept it, the ticket and the console are refused with 403
forbidden: source address not allowed. The same limits apply, and the session
also closes when either node leaves the cluster.
Limits and timeouts
| Sessions per machine | Up to 4 graphical sessions (they share the screen) and 1 serial session |
| Idle | A session closes after 30 minutes without input from you. On the graphical console only keyboard, mouse and clipboard count as input — an open, forgotten tab does not keep it alive |
| Ticket | Single use, 60 seconds |
| Machine stops or is deleted | Its sessions close, with the reason |
| The key is revoked | A session lasts only as long as the key or token that opened it (the one that asked for the ticket, or the one sent on the WebSocket). Revoking it — or a tenant key expiring — closes the session within a few seconds, and an unused ticket it asked for is refused |
| Web console sign-out | A session opened from the web console closes when you sign out or that sign-in ends (idle, 12 hours) |
| Tenant suspended | A session opened with a tenant's ticket closes within a few seconds of the tenant being suspended or closed, or of the machine no longer being the tenant's |
| Agent restarts or updates | Sessions close ("the agent is stopping"); the machine keeps running. Reconnect once the agent is back |
A session ends with a normal close whose reason says why, in plain words. A console that cannot be opened is refused with a plain reason; the details are in the agent's log.
The licence
Opening a console changes nothing on the node, so it is treated like looking at a machine: it works while the licence is frozen, and on a plan without Compute, as long as the machine exists (and runs). Getting a ticket works the same way. Starting, stopping and changing machines still need an active licence that includes Compute.
Every session is recorded
Opening, closing and every refusal are recorded in the node's audit log (who,
from where, which machine and console, how long it was open — see
Monitoring), written to the agent's log as audit entries
(audit=true, with the bytes each way) and published as
compute.console_opened and compute.console_closed events, so the
event stream and webhooks carry them.