Enhance VNC sandbox images with Yao branding and sudo support

- Add passwordless sudo for sandbox user in playwright and desktop images
- Configure Yao branding for Fluxbox (CUI dark theme, centered logo)
- Configure Yao branding for XFCE (panel icons, wallpaper, workspace shortcut)
- Add D-Bus support for XFCE desktop environment
- Add dynamic wallpaper generation with configurable resolution and logo size
- Hide Fluxbox toolbar for cleaner Playwright automation view
- Create chromium wrapper script using Playwright's bundled browser
- Add feh and imagemagick for wallpaper management in Fluxbox
- Update .gitignore for config scripts and TODO file

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Max 2026-02-05 18:23:15 +08:00
parent 69058787f9
commit 55164c5665
12 changed files with 277 additions and 2 deletions

2
.gitignore vendored
View file

@ -57,8 +57,10 @@ agent/test/UPGRADE_PLAN.md
introduction/*
!sandbox/docker/build.sh
!sandbox/docker/vnc/*.sh
!sandbox/docker/desktop/config/*.sh
sandbox/docker/yao-bridge-*
sandbox/docker/claude-proxy-*
sandbox/docker/claude/claude-proxy-*
sandbox/proxy/claude-proxy-linux-*
release/*
sandbox/TODO-VNC.md

View file

@ -16,6 +16,8 @@ RUN sed -i 's|http://ports.ubuntu.com/ubuntu-ports|http://mirrors.mit.edu/ubuntu
# Install X11, VNC, and XFCE desktop environment
RUN apt-get update && apt-get install -y --no-install-recommends \
# Sudo for sandbox user
sudo \
# Virtual display
xvfb \
# VNC server
@ -23,6 +25,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
# noVNC (HTML5 VNC client) and websockify
novnc \
python3-websockify \
# D-Bus (required for XFCE)
dbus-x11 \
# XFCE Desktop (full-featured but lightweight)
xfce4 \
xfce4-terminal \
@ -40,6 +44,14 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
&& apt-get remove -y xfce4-screensaver xscreensaver || true \
&& rm -rf /var/lib/apt/lists/*
# Configure passwordless sudo for sandbox user
RUN echo "sandbox ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/sandbox && \
chmod 0440 /etc/sudoers.d/sandbox
# Create chromium wrapper script (uses Playwright's Chromium, starts maximized)
RUN echo '#!/bin/bash\nexec /home/sandbox/.cache/ms-playwright/chromium-1208/chrome-linux/chrome --no-sandbox --start-maximized "$@"' > /usr/local/bin/chromium && \
chmod +x /usr/local/bin/chromium
# Optional: Install Playwright system dependencies (requires root)
# Users can run browser automation in desktop mode too
RUN npx playwright install-deps chromium || true
@ -58,6 +70,16 @@ COPY vnc/start-vnc.sh /usr/local/bin/start-vnc.sh
COPY vnc/entrypoint-vnc.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/start-vnc.sh /usr/local/bin/entrypoint.sh
# Copy Yao branding assets
RUN mkdir -p /usr/share/yao
COPY desktop/config/yao-logo-48.png /usr/share/yao/yao-logo-48.png
COPY desktop/config/yao-logo-128.png /usr/share/yao/yao-logo-128.png
COPY desktop/config/yao-logo-256.png /usr/share/yao/yao-logo-256.png
COPY desktop/config/panel-launcher-chromium.desktop /usr/share/yao/panel-launcher-chromium.desktop
COPY desktop/config/workspace.desktop /usr/share/yao/workspace.desktop
COPY desktop/config/setup-xfce.sh /usr/local/bin/setup-xfce.sh
RUN chmod +x /usr/local/bin/setup-xfce.sh
# Environment variables for VNC
ENV DISPLAY=:99
ENV VNC_PORT=5900
@ -65,6 +87,8 @@ ENV NOVNC_PORT=6080
ENV RESOLUTION=1920x1080x24
ENV SANDBOX_VNC_ENABLED=true
ENV SANDBOX_DESKTOP=xfce
# Set hostname for XFCE panel display
ENV HOSTNAME="Yao Sandbox"
# Node.js environment - ensure global modules are accessible
ENV NODE_PATH=/home/sandbox/.npm-global/lib/node_modules

View file

@ -0,0 +1,12 @@
[Desktop Entry]
Version=1.0
Type=Application
Name=Chromium
Comment=Access the Internet
GenericName=Web Browser
Exec=/usr/local/bin/chromium %U
Icon=org.xfce.webbrowser
Terminal=false
Categories=Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/vnd.mozilla.xul+xml;application/rss+xml;application/rdf+xml;x-scheme-handler/http;x-scheme-handler/https;
StartupNotify=true

View file

@ -0,0 +1,160 @@
#!/bin/bash
# XFCE desktop configuration script
# Runs on container startup to set up Yao branding and default applications
set -e
XFCE_CONFIG_DIR="$HOME/.config/xfce4"
XFDESKTOP_DIR="$HOME/.config/xfce4/xfconf/xfce-perchannel-xml"
ICONS_DIR="$HOME/.local/share/icons/hicolor"
APPS_DIR="$HOME/.local/share/applications"
DESKTOP_DIR="$HOME/Desktop"
# Create necessary directories
mkdir -p "$XFCE_CONFIG_DIR/panel"
mkdir -p "$XFDESKTOP_DIR"
mkdir -p "$ICONS_DIR/48x48/apps"
mkdir -p "$ICONS_DIR/128x128/apps"
mkdir -p "$ICONS_DIR/256x256/apps"
mkdir -p "$APPS_DIR"
mkdir -p "$DESKTOP_DIR"
# Copy Yao logo to user icons directory
if [ -f /usr/share/yao/yao-logo-48.png ]; then
cp /usr/share/yao/yao-logo-48.png "$ICONS_DIR/48x48/apps/yao.png"
cp /usr/share/yao/yao-logo-128.png "$ICONS_DIR/128x128/apps/yao.png"
cp /usr/share/yao/yao-logo-256.png "$ICONS_DIR/256x256/apps/yao.png"
# Also copy to system location for panel icon
sudo cp /usr/share/yao/yao-logo-48.png /usr/share/pixmaps/yao.png 2>/dev/null || true
gtk-update-icon-cache "$ICONS_DIR" 2>/dev/null || true
fi
# Copy Chromium launcher to applications
if [ -f /usr/share/yao/panel-launcher-chromium.desktop ]; then
cp /usr/share/yao/panel-launcher-chromium.desktop "$APPS_DIR/chromium-browser.desktop"
fi
# Configure xfdesktop - hide default icons (File System, Home, Trash), keep only custom shortcuts
cat > "$XFDESKTOP_DIR/xfce4-desktop.xml" << 'XMLEOF'
<?xml version="1.0" encoding="UTF-8"?>
<channel name="xfce4-desktop" version="1.0">
<property name="desktop-icons" type="empty">
<property name="style" type="int" value="2"/>
<property name="file-icons" type="empty">
<property name="show-home" type="bool" value="false"/>
<property name="show-filesystem" type="bool" value="false"/>
<property name="show-trash" type="bool" value="false"/>
<property name="show-removable" type="bool" value="false"/>
</property>
</property>
</channel>
XMLEOF
# Copy workspace shortcut to desktop (named "Workspace" with folder icon)
if [ -f /usr/share/yao/workspace.desktop ]; then
cp /usr/share/yao/workspace.desktop "$DESKTOP_DIR/workspace.desktop"
chmod +x "$DESKTOP_DIR/workspace.desktop"
fi
# Set Chromium as default browser
xdg-settings set default-web-browser chromium-browser.desktop 2>/dev/null || true
# Configure XFCE panel - set Applications menu icon to Yao logo
# This will be applied when xfce4-panel starts
cat > "$XFDESKTOP_DIR/xfce4-panel.xml" << 'XMLEOF'
<?xml version="1.0" encoding="UTF-8"?>
<channel name="xfce4-panel" version="1.0">
<property name="configver" type="int" value="2"/>
<property name="panels" type="array">
<value type="int" value="1"/>
<value type="int" value="2"/>
<property name="dark-mode" type="bool" value="true"/>
<property name="panel-1" type="empty">
<property name="position" type="string" value="p=6;x=0;y=0"/>
<property name="length" type="uint" value="100"/>
<property name="position-locked" type="bool" value="true"/>
<property name="icon-size" type="uint" value="16"/>
<property name="size" type="uint" value="26"/>
<property name="plugin-ids" type="array">
<value type="int" value="1"/>
<value type="int" value="2"/>
<value type="int" value="3"/>
<value type="int" value="4"/>
<value type="int" value="5"/>
<value type="int" value="6"/>
<value type="int" value="7"/>
<value type="int" value="8"/>
<value type="int" value="9"/>
<value type="int" value="10"/>
<value type="int" value="11"/>
</property>
</property>
<property name="panel-2" type="empty">
<property name="autohide-behavior" type="uint" value="1"/>
<property name="position" type="string" value="p=10;x=960;y=1054"/>
<property name="length" type="uint" value="1"/>
<property name="position-locked" type="bool" value="true"/>
<property name="size" type="uint" value="48"/>
<property name="plugin-ids" type="array">
<value type="int" value="12"/>
<value type="int" value="13"/>
<value type="int" value="14"/>
<value type="int" value="15"/>
<value type="int" value="16"/>
<value type="int" value="17"/>
</property>
</property>
</property>
<property name="plugins" type="empty">
<property name="plugin-1" type="string" value="applicationsmenu">
<property name="button-icon" type="string" value="yao"/>
<property name="button-title" type="string" value=""/>
<property name="show-button-title" type="bool" value="false"/>
</property>
<property name="plugin-2" type="string" value="tasklist">
<property name="grouping" type="uint" value="1"/>
</property>
<property name="plugin-3" type="string" value="separator">
<property name="expand" type="bool" value="true"/>
<property name="style" type="uint" value="0"/>
</property>
<property name="plugin-4" type="string" value="pager"/>
<property name="plugin-5" type="string" value="separator">
<property name="style" type="uint" value="0"/>
</property>
<property name="plugin-6" type="string" value="systray">
<property name="square-icons" type="bool" value="true"/>
</property>
<property name="plugin-7" type="string" value="pulseaudio">
<property name="enable-keyboard-shortcuts" type="bool" value="true"/>
<property name="show-notifications" type="bool" value="true"/>
</property>
<property name="plugin-8" type="string" value="power-manager-plugin"/>
<property name="plugin-9" type="string" value="notification-plugin"/>
<property name="plugin-10" type="string" value="separator">
<property name="style" type="uint" value="0"/>
</property>
<property name="plugin-11" type="string" value="clock"/>
<property name="plugin-12" type="string" value="showdesktop"/>
<property name="plugin-13" type="string" value="separator"/>
<property name="plugin-14" type="string" value="launcher">
<property name="items" type="array">
<value type="string" value="xfce4-terminal.desktop"/>
</property>
</property>
<property name="plugin-15" type="string" value="launcher">
<property name="items" type="array">
<value type="string" value="thunar.desktop"/>
</property>
</property>
<property name="plugin-16" type="string" value="launcher">
<property name="items" type="array">
<value type="string" value="chromium-browser.desktop"/>
</property>
</property>
<property name="plugin-17" type="string" value="separator"/>
</property>
</channel>
XMLEOF
echo "[XFCE Setup] Configuration complete"

View file

@ -0,0 +1,9 @@
[Desktop Entry]
Version=1.0
Type=Application
Name=Workspace
Comment=Open Workspace folder
Icon=folder
Exec=thunar /workspace
Terminal=false
Categories=System;FileManager;

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="719.664453px" height="610.367745px" viewBox="0 0 719.664453 610.367745" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Yaobots</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Yaobots" transform="translate(-151.5657, -188.764)" fill-rule="nonzero">
<polygon id="Path" points="0 0 1024 0 1024 1024 0 1024"></polygon>
<path d="M486.884,189.207 C495.1615,188.4345 505.165,188.919 513.59,188.864 C599.61,188.302 684.55,217.9475 749.645,274.6415 C820.74,337.335 864.11,425.629 870.28,520.215 C874.69,585.13 864.71,657.9 819.94,708.215 C766.135,768.695 672.935,788.13 595.875,795.7 C576.14,797.64 557.055,797.635 537.68,798.92 C436.9495,800.75 298.6425,791.955 218.4915,723.25 C173.8735,685 156.2745,627.825 152.411,570.625 C145.8345,474.4635 177.8325,379.6425 241.3305,307.127 C292.7155,248.288 362.5635,208.649 439.428,194.7065 C455.6785,191.7125 470.5135,190.32 486.884,189.207 Z" id="Path" fill="#3371FC"></path>
<g id="Eye-left" transform="translate(352.7054, 366.1909)" fill="#FFFFFE">
<path d="M54.3200771,0.00131773874 C90.5575771,-0.297352792 107.046077,50.2461472 109.269077,79.1841472 C111.987077,114.573147 98.0685771,173.204147 55.0560771,176.574147 C19.8370771,176.004147 3.26007709,132.680147 0.574577092,103.311147 C-2.06042291,74.4961472 4.20857709,41.4316472 22.6780771,18.3306472 C30.9835771,7.94264721 41.0875771,1.40214721 54.3200771,0.00131773874 Z M67.8166257,49.886467 L66.8260771,49.8991472 C34.0975771,56.7616472 37.5585771,132.225647 70.5330771,131.761147 C103.215077,124.145147 100.147077,48.7151472 66.8260771,49.8991472 Z" id="Combined-Shape"></path>
</g>
<g id="Eye-right" transform="translate(562.8175, 366.1247)" fill="#FFFFFE">
<path d="M76.7075112,8.55926237 C96.7425112,24.6522624 104.512511,49.8777624 107.982511,74.3482624 C112.957511,109.387262 99.1125112,171.335262 57.0025112,176.520262 C47.7325112,176.880262 37.7225112,173.635262 30.7025112,167.460262 C-8.8974888,132.641762 -8.5574888,58.3082624 22.3475112,18.0877624 C30.2475112,7.80826237 40.7175112,1.45976237 53.2275112,0.0662623674 C61.0975112,-0.590737633 70.7075112,3.73926237 76.7075112,8.55926237 Z M39.6166685,49.9369618 L38.6575112,49.9567624 C5.9375112,57.6252624 10.0475112,133.248262 43.3725112,131.767262 C76.3675112,122.553262 70.8975112,48.5472624 38.6575112,49.9567624 Z" id="Combined-Shape"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -16,6 +16,8 @@ RUN sed -i 's|http://ports.ubuntu.com/ubuntu-ports|http://mirrors.mit.edu/ubuntu
# Install X11, VNC, and minimal window manager
RUN apt-get update && apt-get install -y --no-install-recommends \
# Sudo for sandbox user
sudo \
# Virtual display
xvfb \
# VNC server
@ -25,6 +27,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
python3-websockify \
# Minimal window manager (lightweight, perfect for Playwright)
fluxbox \
# Background/wallpaper utilities
feh \
imagemagick \
# Fonts (required for proper browser rendering)
fonts-liberation \
fonts-noto-cjk \
@ -36,6 +41,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
pulseaudio \
&& rm -rf /var/lib/apt/lists/*
# Configure passwordless sudo for sandbox user
RUN echo "sandbox ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/sandbox && \
chmod 0440 /etc/sudoers.d/sandbox
# Install Playwright system dependencies (requires root)
# This installs system libraries needed by Chromium/Firefox
RUN npx playwright install-deps chromium firefox || true
@ -50,11 +59,16 @@ RUN npm install -g playwright && \
USER root
# Copy VNC startup scripts
# Create directories for branding assets
RUN mkdir -p /usr/local/share/yao
# Copy VNC startup scripts and branding assets
# Note: Build context should be sandbox/docker/, so paths are relative to that
COPY vnc/start-vnc.sh /usr/local/bin/start-vnc.sh
COPY vnc/entrypoint-vnc.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/start-vnc.sh /usr/local/bin/entrypoint.sh
COPY playwright/config/setup-fluxbox.sh /usr/local/bin/setup-fluxbox.sh
COPY playwright/config/yao-logo.png /usr/local/share/yao/yao-logo.png
RUN chmod +x /usr/local/bin/start-vnc.sh /usr/local/bin/entrypoint.sh /usr/local/bin/setup-fluxbox.sh
# Environment variables for VNC
ENV DISPLAY=:99

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -31,20 +31,58 @@ if ! kill -0 $XVFB_PID 2>/dev/null; then
fi
echo "[VNC] Xvfb started (PID: $XVFB_PID)"
# Start D-Bus session bus (required for XFCE)
if [ "$DESKTOP" = "xfce" ] || [ "$DESKTOP" = "xfce4" ]; then
echo "[VNC] Starting D-Bus session bus..."
if command -v dbus-launch &> /dev/null; then
eval $(dbus-launch --sh-syntax)
export DBUS_SESSION_BUS_ADDRESS
echo "[VNC] D-Bus started: $DBUS_SESSION_BUS_ADDRESS"
else
echo "[VNC] WARNING: dbus-launch not found, XFCE may have limited functionality"
fi
fi
# Start window manager / desktop environment
echo "[VNC] Starting ${DESKTOP}..."
case "$DESKTOP" in
xfce|xfce4)
# Run XFCE setup script if exists (for Yao branding)
if [ -x /usr/local/bin/setup-xfce.sh ]; then
echo "[VNC] Running XFCE setup..."
/usr/local/bin/setup-xfce.sh || true
fi
# XFCE desktop environment
startxfce4 &
;;
fluxbox)
# Run Fluxbox setup script if exists (Yao branding, disable toolbar)
if [ -x /usr/local/bin/setup-fluxbox.sh ]; then
echo "[VNC] Running Fluxbox setup..."
/usr/local/bin/setup-fluxbox.sh || true
fi
# Minimal window manager for Playwright
fluxbox &
sleep 1
# Set wallpaper with feh if available (for Yao branding)
WALLPAPER="$HOME/.local/share/wallpapers/yao-wallpaper.png"
if [ -f "$WALLPAPER" ] && command -v feh &> /dev/null; then
echo "[VNC] Setting wallpaper..."
feh --bg-center "$WALLPAPER" || true
fi
;;
*)
# Default to fluxbox
if [ -x /usr/local/bin/setup-fluxbox.sh ]; then
/usr/local/bin/setup-fluxbox.sh || true
fi
fluxbox &
sleep 1
# Set wallpaper with feh if available
WALLPAPER="$HOME/.local/share/wallpapers/yao-wallpaper.png"
if [ -f "$WALLPAPER" ] && command -v feh &> /dev/null; then
feh --bg-center "$WALLPAPER" || true
fi
;;
esac
sleep 2