diff --git a/images/chromium-headless/image/Dockerfile b/images/chromium-headless/image/Dockerfile
index 7be9610e..cc4f55c9 100644
--- a/images/chromium-headless/image/Dockerfile
+++ b/images/chromium-headless/image/Dockerfile
@@ -102,6 +102,8 @@ ARG TARGETARCH
ARG TARGETOS
ARG CACHEIDPREFIX=${TARGETOS:-linux}-${TARGETARCH:-amd64}-ubuntu2204
+ENV DEBIAN_FRONTEND=noninteractive
+
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-apt-cache \
--mount=type=cache,target=/var/lib/apt,sharing=locked,id=$CACHEIDPREFIX-apt-lib \
set -xe; \
@@ -143,7 +145,10 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=$CACHEIDPREFIX-ap
fonts-noto-color-emoji \
fonts-nanum \
software-properties-common \
- supervisor; \
+ supervisor \
+ x11vnc \
+ novnc \
+ websockify; \
fc-cache -f
# install chromium and sqlite3 for debugging the cookies file
@@ -223,6 +228,7 @@ COPY images/chromium-headless/image/wrapper.sh /usr/bin/wrapper.sh
# Supervisord configuration
COPY images/chromium-headless/image/supervisord.conf /etc/supervisor/supervisord.conf
COPY images/chromium-headless/image/supervisor/services/ /etc/supervisor/conf.d/services/
+COPY images/chromium-headless/image/novnc-view.html /usr/share/novnc/index.html
COPY shared/envoy/supervisor-envoy.conf /etc/supervisor/conf.d/services/envoy.conf
# Install Envoy proxy
diff --git a/images/chromium-headless/image/novnc-view.html b/images/chromium-headless/image/novnc-view.html
new file mode 100644
index 00000000..78e69ebe
--- /dev/null
+++ b/images/chromium-headless/image/novnc-view.html
@@ -0,0 +1,48 @@
+
+
+
+ Live View
+
+
+
+
+
+
+
+
+
diff --git a/images/chromium-headless/image/supervisor/services/chromium.conf b/images/chromium-headless/image/supervisor/services/chromium.conf
index 7018e12a..ae1f22e9 100644
--- a/images/chromium-headless/image/supervisor/services/chromium.conf
+++ b/images/chromium-headless/image/supervisor/services/chromium.conf
@@ -1,5 +1,5 @@
[program:chromium]
-command=/usr/local/bin/chromium-launcher --headless
+command=/usr/local/bin/chromium-launcher
autostart=false
autorestart=true
startsecs=0
diff --git a/images/chromium-headless/image/supervisor/services/novnc.conf b/images/chromium-headless/image/supervisor/services/novnc.conf
new file mode 100644
index 00000000..efb95099
--- /dev/null
+++ b/images/chromium-headless/image/supervisor/services/novnc.conf
@@ -0,0 +1,7 @@
+[program:novnc]
+command=websockify --web /usr/share/novnc 8080 localhost:5900
+autostart=false
+autorestart=true
+startsecs=2
+stdout_logfile=/var/log/supervisord/novnc
+redirect_stderr=true
diff --git a/images/chromium-headless/image/supervisor/services/x11vnc.conf b/images/chromium-headless/image/supervisor/services/x11vnc.conf
new file mode 100644
index 00000000..908a93a6
--- /dev/null
+++ b/images/chromium-headless/image/supervisor/services/x11vnc.conf
@@ -0,0 +1,7 @@
+[program:x11vnc]
+command=x11vnc -display :1 -forever -shared -nopw -rfbport 5900 -noxdamage
+autostart=false
+autorestart=true
+startsecs=2
+stdout_logfile=/var/log/supervisord/x11vnc
+redirect_stderr=true
diff --git a/images/chromium-headless/image/wrapper.sh b/images/chromium-headless/image/wrapper.sh
index 7faff130..d09c0ff4 100755
--- a/images/chromium-headless/image/wrapper.sh
+++ b/images/chromium-headless/image/wrapper.sh
@@ -79,6 +79,10 @@ export HOSTNAME="${HOSTNAME:-kernel-vm}"
# NOTE: --disable-background-networking was intentionally removed because it prevents
# Chrome from fetching extensions via ExtensionInstallForcelist enterprise policy.
# Enterprise extensions require Chrome to make HTTP requests to fetch update.xml and .crx files.
+#
+# Chromium renders to Xvfb (DISPLAY=:1) so that screenshots, recordings, xdotool
+# input, and live view all work. Flags like --ozone-platform=headless and
+# --disable-software-rasterizer are intentionally absent.
if [ -z "${CHROMIUM_FLAGS:-}" ]; then
CHROMIUM_FLAGS="--accept-lang=en-US,en \
--allow-pre-commit-input \
@@ -106,24 +110,23 @@ if [ -z "${CHROMIUM_FLAGS:-}" ]; then
--disable-prompt-on-repost \
--disable-renderer-backgrounding \
--disable-search-engine-choice-screen \
- --disable-software-rasterizer \
--enable-use-zoom-for-dsf=false \
--export-tagged-pdf \
--force-color-profile=srgb \
--hide-crash-restore-bubble \
- --hide-scrollbars \
--metrics-recording-only \
--mute-audio \
--no-default-browser-check \
--no-first-run \
--no-sandbox \
--no-service-autorun \
- --ozone-platform=headless \
--password-store=basic \
--unsafely-disable-devtools-self-xss-warnings \
--use-angle=swiftshader \
--use-gl=angle \
- --use-mock-keychain"
+ --use-mock-keychain \
+ --window-size=${WIDTH:-1920},${HEIGHT:-1080} \
+ --window-position=0,0"
fi
export CHROMIUM_FLAGS
@@ -216,6 +219,8 @@ cleanup () {
echo "[wrapper] Cleaning up..."
# Re-enable scale-to-zero if the script terminates early
enable_scale_to_zero
+ supervisorctl -c /etc/supervisor/supervisord.conf stop novnc || true
+ supervisorctl -c /etc/supervisor/supervisord.conf stop x11vnc || true
supervisorctl -c /etc/supervisor/supervisord.conf stop chromedriver || true
supervisorctl -c /etc/supervisor/supervisord.conf stop chromium || true
supervisorctl -c /etc/supervisor/supervisord.conf stop xvfb || true
@@ -274,6 +279,16 @@ echo "[wrapper] Starting ChromeDriver via supervisord"
supervisorctl -c /etc/supervisor/supervisord.conf start chromedriver
wait_for_tcp_port 127.0.0.1 9225 "ChromeDriver" 50 0.2 "10s" || true
+if [[ "${ENABLE_LIVE_VIEW:-}" == "true" ]]; then
+ echo "[wrapper] Starting x11vnc via supervisord"
+ supervisorctl -c /etc/supervisor/supervisord.conf start x11vnc
+ wait_for_tcp_port 127.0.0.1 5900 "x11vnc" 50 0.2 "10s" || true
+
+ echo "[wrapper] Starting noVNC via supervisord"
+ supervisorctl -c /etc/supervisor/supervisord.conf start novnc
+ wait_for_tcp_port 127.0.0.1 8080 "noVNC" 50 0.2 "10s" || true
+fi
+
echo "[wrapper] startup complete!"
# Re-enable scale-to-zero once startup has completed (when not under Docker)
if [[ -z "${WITHDOCKER:-}" ]]; then
diff --git a/images/chromium-headless/run-docker.sh b/images/chromium-headless/run-docker.sh
index 56f582bf..303ea32d 100755
--- a/images/chromium-headless/run-docker.sh
+++ b/images/chromium-headless/run-docker.sh
@@ -17,7 +17,9 @@ RUN_ARGS=(
-p 9222:9222
-p 9224:9224
-p 444:10001
+ -p 8080:8080
-v "$HOST_RECORDINGS_DIR:/recordings"
+ -e ENABLE_LIVE_VIEW="${ENABLE_LIVE_VIEW:-true}"
)
if [[ -n "${PLAYWRIGHT_ENGINE:-}" ]]; then