Interactive Desktop & Signed Panel Proxy
Computer-use and browser-automation agents frequently need a real X11 display, Chromium DevTools Protocol (CDP), human-in-the-loop VNC viewing, and a live browser shell — without forcing non-GUI sandboxes to pay idle RAM overhead or punch per-sandbox firewall holes in Kubernetes.
CubePod solves this with two tightly integrated mechanisms (CEP-0004, CEP-0021): a lazy on-demand desktop stack (images/desktop/) and a stateless HMAC-SHA256 /panel/{token}/ reverse proxy (pkg/gateway/panel.go).
1. Zero-Idle-Cost Lazy Desktop Stack
Section titled “1. Zero-Idle-Cost Lazy Desktop Stack”Containers built from CubePod’s desktop image (images/desktop/) boot into CMD ["sleep", "infinity"] with ~0 MiB desktop daemon memory overhead. Graphical daemons remain dormant until a client explicitly starts a desktop session.
All desktop processes are managed by /opt/cubepod/desktop/cubepod-desktop-ctl (start, status, stop), stored separately from /opt/cubepod/bin so runtime binaries remain decoupled:
| Daemon | Bind / Display | Role & Configuration |
|---|---|---|
Xvfb |
Display :99 |
Virtual X11 framebuffer defaulting to 1280x800x24 (customizable via validated WxHx{16|24|32} resolution). |
openbox |
Display :99 |
Lightweight X11 window manager for browser and desktop windows. |
chromium-wrapper |
127.0.0.1:9222 |
Headless/headed Chromium exposing Chrome DevTools Protocol (CDP), optionally navigating to initialUrl. Cleans stale SingletonLock / SingletonSocket / SingletonCookie files from persisted RootFS across sandbox pauses or restarts. |
x11vnc |
127.0.0.1:5900 |
Binds the :99 X display locally over VNC. |
websockify + noVNC |
0.0.0.0:8080 |
Bridges VNC WebSockets into browser-viewable vnc.html. |
ttyd |
:7681 |
Streams an interactive web terminal (/bin/bash) starting in /workspace. |
Reliability & Privilege Safety (cubepod-desktop-ctl)
Section titled “Reliability & Privilege Safety (cubepod-desktop-ctl)”- Privilege Separation: Although
poddspawns control hooks cleanly,cubepod-desktop-ctldrops privileges to UID/GID1000:1000(cubeplex) so browser caches, downloads, and shell sessions run unprivileged and share/workspaceownership automatically. - Concurrency Locking: Operations are serialized via
flockso concurrentstart/stopcalls never spawn duplicateXvfborx11vncinstances. - RootFS-Safe Chromium Recovery: Because CubePod persists RootFS across pod restarts, Chromium’s previous PID profile locks (
Singleton*) would normally prevent relaunching after aPaused->Runningtransition.cubepod-desktop-ctlcleans stale lock files before startingchromium-wrapper.
Protocol Note: The shipping
images/desktop/stack servesnoVNC(:8080),ttyd(:7681), and Chromium CDP (:9222), while CubePod’s panel reverse proxy and architecture blueprint also support proxying WebRTC/Neko streaming endpoints when supplied by custom images.
2. Gateway Desktop API (pkg/gateway/desktop.go)
Section titled “2. Gateway Desktop API (pkg/gateway/desktop.go)”cubepod-gateway exposes three lifecycle endpoints (also available under /v1/sandboxes/{id}/desktop/...):
POST /sandboxes/{id}/desktop/start— validates resolution (WxHx{16|24|32}), auto-resumes the sandbox ifPaused, verifies/opt/cubepod/desktop/cubepod-desktop-ctlexists (returningHTTP 422 desktop_not_installedon non-desktop images), starts the stack viapodd, and returns ready URLs (desktopUrl,terminalUrl,cdpUrl).GET /sandboxes/{id}/desktop/status— returns live status ofXvfb,openbox,chromium,x11vnc/noVNC, andttyd.POST /sandboxes/{id}/desktop/stop— gracefully tears down GUI daemons to reclaim RAM while preserving sandbox compute and files.
Example response URLs returned by start:
desktopUrl:/panel/<signed-token>/vnc.html?autoconnect=true&resize=scaleterminalUrl: interactivettydterminal endpoint (port7681)cdpUrl: Chrome DevTools Protocol (CDP) endpoint for headless/headed Chromium automation (port9222)
3. Stateless Signed Panel Proxy (pkg/gateway/panel.go)
Section titled “3. Stateless Signed Panel Proxy (pkg/gateway/panel.go)”Instead of provisioning per-sandbox Kubernetes Ingress objects or exposing container ports directly, cubepod-gateway issues short-lived, cryptographically signed panel URLs for any port inside a sandbox (desktop 8080, ttyd 7681, Jupyter, Vite/React dev servers, MCP UIs):
- Token Minting (
POST /sandboxes/{id}/endpoints/{port}): Encodes payloadsandboxID:port:expUnix(default TTL3600seconds), signs it with HMAC-SHA256, and outputs:base64url(sandboxID:port:expUnix).base64url(hmacSha256) - Stateless Verification Across Replicas: Any
cubepod-gatewayreplica receivingGET /panel/{token}/{rest...}(or a WebSocket upgrade handshake) verifies the HMAC signature and expiration timestamp without needing central session storage. - Auto-Resume & Live Reverse Proxy: Using
resolveSandbox, the gateway wakes the sandbox if it isPaused, resolves its current<status.podIP>:<port>, and reverse-proxies HTTP assets and bidirectional WebSocket frames (noVNC,ttyd, HMR dev servers) directly to the MicroVM.
Next Steps
Section titled “Next Steps”- Try launching a desktop session in Python from the Quickstart.
- Inspect the full gateway endpoints in the API Reference.
- Read the design specifications in CEP-0004 and CEP-0021.