VM console via WebSocket in browser #36
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_compute#36
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Description
Implement a browser-based VM console (terminal) so users can interact with their VMs directly from the hero_compute dashboard without needing SSH or Mycelium.
Background
Kristof built a WebSocket-based PTY terminal in hero_proc (branch , now merged to ). We should follow the same pattern and adapt it for VM console access via chvm's vsock.
hero_proc reference implementation
{"resize":{"cols":N,"rows":N}}hero_proc_server/src/web.rs— PTY WebSocket handlerhero_proc_server/src/supervisor/executor.rs— PTY creationhero_proc_ui/templates/index.html— xterm.js frontendhero_proc_ui/src/routes.rs— UI WebSocket proxyRequirements
Backend (hero_compute_server or hero_compute_ui)
GET /console/{vm_sid}(upgrades to WebSocket)hypervisor_id~/.chvm/vms/{hypervisor_id}/vsock.sockCONNECT 1025handshake to vsock{"resize":{"cols":N,"rows":N}}Frontend (hero_compute_ui)
ws://host/console/{vm_sid}?secret=...binaryType = 'arraybuffer'on WebSocketterm.write()Protocol
{"resize":{"cols":N,"rows":N}}Differences from hero_proc
portable_pty(local PTY)~/.chvm/vms/{id}/vsock.sock)tokio::sync::broadcast(multi-client)Implementation Notes
~/.chvm/vms/{hypervisor_id}/vsock.sock— we already havehypervisor_idon the VM recordportable_pty— the VM already has a TTY, we just bridge to itOpen Questions
Implementation Spec for Issue #36: VM Console via WebSocket
Architecture
Implementation Steps
hero_compute_ui/Cargo.toml.with_upgrades()in HTTP serverhero_compute_ui/src/server.rs/console/{vm_sid}WebSocket route + vsock bridgehero_compute_ui/src/server.rsstatic/js/xterm*.js,static/css/xterm.min.csstemplates/base.htmlstatic/js/dashboard.jsBackend (Step 3 detail)
GET /console/{vm_sid}?secret=...→ WebSocket upgradeComputeService.get_vmvia SDK to verify secret + gethypervisor_id~/.chvm/vms/{hypervisor_id}/vsock.sockCONNECT 1025\nhandshake, verifyOK\nresponse{"resize":{...}}silently discarded (no vsock resize protocol)Frontend (Steps 5-6 detail)
modal-xl, 500px terminal height) with xterm.jsws.binaryType = 'arraybuffer', ResizeObserver for auto-fitKey Dependencies
axumwithwsfeaturefutures0.3 forStreamExt/SinkExtNotes
.with_upgrades()critical — without it, WebSocket upgrade fails silentlyTest Results (2026-03-21)
Command:
cargo test -p hero_compute_server -p hero_compute_explorer -p hero_compute_uiBranch:
development(commitb96d904)Status: ALL PASSED
All 32 unit tests passed. 5 doc-tests were ignored (expected).
Implementation Summary
New files (3)
crates/hero_compute_ui/static/js/xterm.min.js— xterm.js terminal emulator (copied from hero_proc)crates/hero_compute_ui/static/js/xterm-addon-fit.min.js— FitAddon for auto-sizing (copied from hero_proc)crates/hero_compute_ui/static/css/xterm.min.css— xterm.js styles (copied from hero_proc)Modified files (5)
Cargo.toml(workspace) — Addedwsfeature to axum, addedfuturesworkspace depcrates/hero_compute_ui/Cargo.toml— Addedfuturesdependencycrates/hero_compute_ui/src/server.rs— Added.with_upgrades(),/console/:vm_sidWebSocket route,console_ws_handler(VM auth + vsock lookup),console_bridge(bidirectional WebSocket↔vsock bridge withCONNECT 1025handshake)crates/hero_compute_ui/templates/base.html— Added xterm.js CSS/JS includes, addedvmConsoleModal(dark-themed, modal-xl, 500px terminal)crates/hero_compute_ui/static/js/dashboard.js— Added Console button tovmActionButtons+renderVmDetailDialog, addedopenVmConsole/closeVmConsole/openVmConsoleFromDetailfunctionsTest Results
Implementation committed:
cde350bBrowse:
cde350b