Documentation Index
Fetch the complete documentation index at: https://mintlify.com/opensandbox-group/OpenSandbox/llms.txt
Use this file to discover all available pages before exploring further.
OpenSandbox can host fully interactive graphical environments inside a container. The Desktop example starts an XFCE session backed by a virtual framebuffer (Xvfb), exposes it over VNC for native clients, and additionally serves it through noVNC so any browser can connect without extra software. The VS Code example starts code-server — a server-side build of VS Code — and exposes the editor’s HTTP port through the sandbox proxy, giving agents or developers a browser-accessible IDE in seconds.
Desktop (VNC)
VS Code Web
The opensandbox/desktop image ships Xvfb, x11vnc, XFCE, and noVNC. The Python script starts each component as a background process, then prints the VNC endpoint for native clients and a noVNC URL for browsers.Build the image
cd examples/desktop
docker build -t opensandbox/desktop:latest .
Or pull the prebuilt image:docker pull opensandbox/desktop:latest
Start the OpenSandbox server
uv pip install opensandbox-server
opensandbox-server init-config ~/.sandbox.toml --example docker
opensandbox-server
Environment variables
| Variable | Default | Description |
|---|
SANDBOX_DOMAIN | localhost:8080 | Sandbox service address |
SANDBOX_API_KEY | (optional) | API key if your server requires authentication |
SANDBOX_IMAGE | opensandbox/desktop:latest | Sandbox image to use |
VNC_PASSWORD | opensandbox | Password for VNC access |
Create and access the Desktop sandbox
uv pip install opensandbox
VNC_PASSWORD=opensandbox uv run python examples/desktop/main.py
import asyncio
import os
from datetime import timedelta
from opensandbox import Sandbox
from opensandbox.config import ConnectionConfig
from opensandbox.models.execd import RunCommandOpts
def _required_env(name: str) -> str:
value = os.getenv(name)
if not value:
raise RuntimeError(f"{name} is required")
return value
async def _print_logs(label: str, execution) -> None:
for msg in execution.logs.stdout:
print(f"[{label} stdout] {msg.text}")
for msg in execution.logs.stderr:
print(f"[{label} stderr] {msg.text}")
if execution.error:
print(f"[{label} error] {execution.error.name}: {execution.error.value}")
async def main() -> None:
domain = os.getenv("SANDBOX_DOMAIN", "localhost:8080")
api_key = os.getenv("SANDBOX_API_KEY")
image = os.getenv("SANDBOX_IMAGE", "opensandbox/desktop:latest")
python_version = os.getenv("PYTHON_VERSION", "3.11")
vnc_password = _required_env("VNC_PASSWORD")
config = ConnectionConfig(
domain=domain,
api_key=api_key,
request_timeout=timedelta(seconds=60),
)
sandbox = await Sandbox.create(
image,
connection_config=config,
env={
"PYTHON_VERSION": python_version,
"VNC_PASSWORD": vnc_password,
},
)
async with sandbox:
# Start virtual display
xvfb_exec = await sandbox.commands.run(
"Xvfb :0 -screen 0 1280x800x24",
opts=RunCommandOpts(background=True),
)
await _print_logs("xvfb", xvfb_exec)
# Start XFCE session (provides panel, file manager, terminal)
xfce_exec = await sandbox.commands.run(
"DISPLAY=:0 dbus-launch startxfce4",
opts=RunCommandOpts(background=True),
)
await _print_logs("xfce", xfce_exec)
# Start x11vnc VNC server
vnc_exec = await sandbox.commands.run(
'x11vnc -display :0 -passwd "$VNC_PASSWORD" -forever -shared -rfbport 5900',
opts=RunCommandOpts(background=True),
)
await _print_logs("x11vnc", vnc_exec)
# Start noVNC/websockify to expose VNC over WebSocket/HTTP
novnc_exec = await sandbox.commands.run(
"/usr/bin/websockify --web=/usr/share/novnc 6080 localhost:5900",
opts=RunCommandOpts(background=True),
)
await _print_logs("novnc", novnc_exec)
endpoint_vnc = await sandbox.get_endpoint(5900)
endpoint_novnc = await sandbox.get_endpoint(6080)
# Build noVNC URL with host/port/path for routed endpoint
novnc_host_port, novnc_path = endpoint_novnc.endpoint.split("/", 1)
novnc_host, novnc_port = novnc_host_port.split(":")
novnc_url = (
f"http://{endpoint_novnc.endpoint}/vnc.html"
f"?host={novnc_host}&port={novnc_port}&path={novnc_path}"
)
print("\nVNC endpoint (native clients):")
print(f" {endpoint_vnc.endpoint}")
print(f"Password: {vnc_password}")
print("\nnoVNC (browser):")
print(f" {novnc_url}")
print(f"Password: {vnc_password}")
print("\nKeeping sandbox alive for 5 minutes. Press Ctrl+C to exit sooner.")
try:
await asyncio.sleep(300)
except KeyboardInterrupt:
print("Stopping...")
finally:
await sandbox.kill()
if __name__ == "__main__":
asyncio.run(main())
The script prints both the native VNC endpoint and the browser-accessible noVNC URL. The sandbox stays alive for 5 minutes by default; interrupt with Ctrl+C to stop sooner. The opensandbox/vscode image ships code-server (VS Code Web) with a workspace directory at /workspace. The Python script starts code-server as a background process with authentication disabled and prints the HTTP endpoint.Build the image
cd examples/vscode
docker build -t opensandbox/vscode:latest .
Or pull the prebuilt image:docker pull sandbox-registry.cn-zhangjiakou.cr.aliyuncs.com/opensandbox/vscode:latest
Start the OpenSandbox server
uv pip install opensandbox-server
opensandbox-server init-config ~/.sandbox.toml --example docker
opensandbox-server
Create and access the VS Code sandbox
uv pip install opensandbox
uv run python examples/vscode/main.py
import asyncio
import os
from datetime import timedelta
from opensandbox import Sandbox
from opensandbox.config import ConnectionConfig
from opensandbox.models.execd import RunCommandOpts
async def _print_logs(label: str, execution) -> None:
for msg in execution.logs.stdout:
print(f"[{label} stdout] {msg.text}")
for msg in execution.logs.stderr:
print(f"[{label} stderr] {msg.text}")
if execution.error:
print(f"[{label} error] {execution.error.name}: {execution.error.value}")
async def main() -> None:
domain = os.getenv("SANDBOX_DOMAIN", "localhost:8080")
api_key = os.getenv("SANDBOX_API_KEY")
image = os.getenv("SANDBOX_IMAGE", "opensandbox/vscode:latest")
python_version = os.getenv("PYTHON_VERSION", "3.11")
code_port = int(os.getenv("CODE_PORT", "8443"))
config = ConnectionConfig(
domain=domain,
api_key=api_key,
request_timeout=timedelta(seconds=60),
)
env = {"PYTHON_VERSION": python_version}
sandbox = await Sandbox.create(
image,
connection_config=config,
env=env,
)
async with sandbox:
# code-server is pre-installed in the image
# Start code-server with authentication disabled
start_exec = await sandbox.commands.run(
f"code-server --bind-addr 0.0.0.0:{code_port} --auth none /workspace",
opts=RunCommandOpts(background=True),
)
await _print_logs("code-server", start_exec)
endpoint = await sandbox.get_endpoint(code_port)
print("\nVS Code Web endpoint:")
print(f" http://{endpoint.endpoint}/")
print("\nKeeping sandbox alive for 10 minutes. Press Ctrl+C to exit sooner.")
try:
await asyncio.sleep(600)
except KeyboardInterrupt:
print("Stopping...")
finally:
await sandbox.kill()
if __name__ == "__main__":
asyncio.run(main())
Open the printed URL in a browser to access the full VS Code editor running inside the sandbox. The workspace directory is pre-set to /workspace.Authentication is disabled (--auth none) in this example for convenience. For shared or production deployments, omit the flag and set a password via code-server’s configuration file.
References