Lease Capabilities
Read when:
- adding
--desktop,--browser, or--codeto a workflow; - choosing a Linux desktop environment with
--desktop-env; - changing how Crabbox detects whether a lease can host a visible desktop;
- adding a new lease capability flag.
Lease capabilities are opt-in features that extend what a runner can do beyond running headless commands. They are distinct from the provider *feature set* declared in ProviderSpec.Features: a feature set says "this provider *can* host a desktop"; a capability label says "this lease *was created* with a desktop and exposes one right now".
#The three capabilities
--desktop visible desktop with a loopback VNC server (XFCE, Wayland, or GNOME)
--browser Chrome/Chromium installed and exported via $BROWSER and $CHROME_BIN
--code code-server bound to a loopback port for the portal code bridge
All three default to off. They must be requested when the lease is created (crabbox warmup --desktop) and are then reused on later commands. A lease created without a capability cannot grow it later; warm a new lease instead.
The desktop flavor is selected with --desktop-env xfce|wayland|gnome (default xfce). Wayland and GNOME require --target linux.
#Selection and validation
Capability flags follow a two-step validation, both in internal/cli/capabilities.go.
- Provider feature check (
validateRequestedCapabilities). When you set a
capability flag, Crabbox looks up the selected provider's Spec().Features and rejects the request if the matching feature (FeatureDesktop, FeatureBrowser, FeatureCode) is missing. Hetzner Linux supports all three; the delegated-run providers support none. Additional guards:
--codeis restricted to managed Linux leases; Windows, macOS, and static--target windows --windows-mode wsl2rejects--desktop(useprovider=azure --target windowssupports SSH, sync, run, and--desktop-env wayland|gnomerequires--target linux.
SSH are rejected.
--windows-mode normal for a desktop, or omit --desktop for WSL2).
desktop/VNC only; --browser, --code, and --tailscale need Linux or AWS Windows.
- Lease label check (
enforceManagedLeaseCapabilities). When you reuse a
lease with --id, Crabbox checks the matching label (desktop=true, browser=true, code=true) on the existing record. If the label is missing, it refuses with a hint to warm a new lease. A non-default --desktop-env must also match the lease's stored desktop_env label.
Label enforcement is skipped for static SSH targets, because Crabbox does not own the host. There the capability is detected probe-by-probe instead (see Static targets). A macOS lease is treated as desktop-capable without a desktop=true label, because Screen Sharing is the desktop.
#Desktop
When a managed Linux lease is created with --desktop (default xfce), bootstrap (internal/cli/bootstrap.go) installs and enables systemd units for:
- resize-capable TigerVNC on display
:99; - an XFCE4 session (
xfce4-session, panel, terminal, settings, theme); - VNC bound to
127.0.0.1:5900with-localhost yes; - a randomized VNC password at
/var/lib/crabbox/vnc.password; - screenshot and capture tooling:
scrot,ffmpeg, plus input helpers
(xdotool, wmctrl, xclip, xsel).
With --desktop-env wayland or gnome, the lease runs a Wayland compositor (labwc) with WayVNC on the same loopback 127.0.0.1:5900.
crabbox vnc --id ... opens an SSH tunnel to that loopback port; your local VNC viewer connects through the tunnel using the password the CLI reads from the lease. There is no public VNC port — the loopback bind is the security boundary.
The VNC password lives at an OS-specific path:
/var/lib/crabbox/vnc.password # Linux
/var/db/crabbox/vnc.password # macOS
C:\ProgramData\crabbox\vnc.password # Windows
When a run injects environment for a desktop lease, Crabbox probes the lease's desktop env file and sets CRABBOX_DESKTOP=1 plus the relevant display variables. For X11 it sets:
DISPLAY=:99
CRABBOX_DESKTOP=1
For a Wayland/GNOME desktop it instead forwards WAYLAND_DISPLAY, XDG_RUNTIME_DIR, and related variables detected on the host. Tools that respect these draw onto the desktop the lease created.
For per-OS detail and known limits, see:
#Browser
--browser adds a usable browser to the lease without provisioning a full desktop.
On managed Linux, bootstrap installs:
- Google Chrome stable when the repo is reachable;
- Chromium (or
chromium-browser) as a fallback; - build helpers (
build-essential,python3, etc.) so dependency installs - a managed Chrome policy and a launcher wrapper, whose path is written to
that compile against Chromium succeed;
/var/lib/crabbox/browser.env as BROWSER and CHROME_BIN.
On static and macOS/Windows targets, Crabbox probes for an existing browser (probeBrowserEnv) and aborts before the command runs if none is found:
- macOS:
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome; - Windows:
chrome.exeormsedge.exefrom PATH or the standard install - Linux:
$BROWSER,$CHROME_BIN, thengoogle-chrome,chromium, or
directories;
chromium-browser from PATH.
The resolved path is exported into the run:
BROWSER=/path/to/browser
CHROME_BIN=/path/to/browser
CRABBOX_BROWSER=1
Test runners that read BROWSER or CHROME_BIN (Vitest, Playwright, etc.) work without extra plumbing.
For browser QA where the remote service is sensitive to source IP (login flows, regional CDN behavior), pair --browser with mediated egress: crabbox egress start opens a lease-local proxy that exits through the operator machine, and crabbox desktop launch --egress passes that proxy to Chrome.
#Code
--code provisions code-server on managed Linux leases. Bootstrap:
- installs the binary at
/usr/local/bin/code-server(standalone install, - binds it to a loopback port (default
8080); - relies on coordinator state for the access token.
--prefix=/usr/local);
crabbox code --id ... and the portal open a code-server tab through the authenticated portal bridge at /portal/leases/{id-or-slug}/code/. The bridge proxies HTTP and WebSocket traffic to the loopback port and injects the auth token, so you never handle it directly. There is no public code-server port.
Code is managed-Linux-only because the bridge depends on the lease shape and the cloud-init that installs the binary. Windows, macOS, and static SSH are intentionally unsupported today.
#Capability labels
Managed lease records carry capability labels (internal/cli/provider_labels.go) so list, status, and the portal can render the capability matrix without re-probing the host:
desktop=true
desktop_env=xfce|wayland|gnome # only when desktop=true
browser=true
code=true
enforceManagedLeaseCapabilities reads these labels to gate --desktop, --browser, --code, and --desktop-env on --id reuse paths. The labels are written at lease creation and never flipped on a live lease.
#Composing capabilities
Capabilities are independent — any combination is allowed where the provider supports them:
crabbox warmup --desktop # desktop only (XFCE)
crabbox warmup --desktop --desktop-env gnome # GNOME desktop
crabbox warmup --desktop --browser # browser on the desktop
crabbox warmup --desktop --browser --code # full interactive box
crabbox warmup --browser # headless browser, no VNC
crabbox warmup --code # editor-only Linux lease
Capability bootstrap adds installation time. A bare lease warms fastest; a lease with all three takes longest. Use the lightest combination that satisfies the workflow.
#Static targets
For static SSH hosts, capability validation degrades to probe-based detection, because Crabbox does not install software on operator-owned machines:
--desktop: probe loopback VNC at127.0.0.1:5900over SSH (X11 checks for--browser: probe for a browser binary using the OS-specific search list;--codeis rejected (managed Linux only).
Xtigervnc or legacy Xvfb/x11vnc; Wayland/GNOME checks for the compositor and WayVNC). Fail with a clear error if the desktop is not running.
fail if none is found.
This is intentional: if a static box does not expose the capability, the run should fail loudly rather than silently fall back. macOS hosts can enable Screen Sharing; Windows hosts need a VNC server bound to 127.0.0.1:5900.