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:
"""Helper to print execution logs"""
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 = os.getenv("VNC_PASSWORD", "opensandbox")
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 desktop session
xfce_exec = await sandbox.commands.run(
"DISPLAY=:0 dbus-launch startxfce4",
opts=RunCommandOpts(background=True),
)
await _print_logs("xfce", xfce_exec)
# Start x11vnc 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 for browser access
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)
# Get endpoints
endpoint_vnc = await sandbox.get_endpoint(5900)
endpoint_novnc = await sandbox.get_endpoint(6080)
# Build noVNC URL
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())