Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion images/chromium-headful/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,6 @@ COPY images/chromium-headful/supervisor/services/ /etc/supervisor/conf.d/service

# copy the kernel-images API binary built in the builder stage
COPY --from=server-builder /out/kernel-images-api /usr/local/bin/kernel-images-api
ENV WITH_KERNEL_IMAGES_API=false

RUN useradd -m -s /bin/bash kernel

Expand Down
16 changes: 6 additions & 10 deletions images/chromium-headful/run-docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,15 @@ RUN_ARGS=(
--tmpfs /dev/shm:size=2g
-v "$HOST_RECORDINGS_DIR:/recordings"
--memory 8192m
-p 9222:9222 \
-e DISPLAY_NUM=1 \
-e HEIGHT=768 \
-e WIDTH=1024 \
-e RUN_AS_ROOT="$RUN_AS_ROOT" \
-p 9222:9222
-p 444:10001
-e DISPLAY_NUM=1
-e HEIGHT=768
-e WIDTH=1024
-e RUN_AS_ROOT="$RUN_AS_ROOT"
--mount type=bind,src="$FLAGS_FILE",dst=/chromium/flags,ro
)

if [[ "${WITH_KERNEL_IMAGES_API:-}" == "true" ]]; then
RUN_ARGS+=( -p 444:10001 )
RUN_ARGS+=( -e WITH_KERNEL_IMAGES_API=true )
fi

# noVNC vs WebRTC port mapping
if [[ "${ENABLE_WEBRTC:-}" == "true" ]]; then
echo "Running container with WebRTC"
Expand Down
9 changes: 2 additions & 7 deletions images/chromium-headful/run-unikernel.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,17 @@ trap 'rm -rf "$FLAGS_DIR"' EXIT


deploy_args=(
-M 8192
-M 4096
-p 9222:9222/tls
-p 444:10001/tls
-e DISPLAY_NUM=1
-e HEIGHT=768
-e WIDTH=1024
-e HOME=/
-e RUN_AS_ROOT="$RUN_AS_ROOT" \
-v "$volume_name":/chromium
-n "$NAME"
)

if [[ "${WITH_KERNEL_IMAGES_API:-}" == "true" ]]; then
deploy_args+=( -p 444:10001/tls )
deploy_args+=( -e WITH_KERNEL_IMAGES_API=true )
fi

if [[ "${ENABLE_WEBRTC:-}" == "true" ]]; then
echo "Deploying with WebRTC enabled"
kraft cloud inst create --start \
Expand Down
2 changes: 2 additions & 0 deletions images/chromium-headful/start-chromium.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/dbus/system_bus_socket"
RUN_AS_ROOT="${RUN_AS_ROOT:-false}"

if [[ "$RUN_AS_ROOT" == "true" ]]; then
echo "Running chromium as root"
exec chromium \
--remote-debugging-port="$INTERNAL_PORT" \
--user-data-dir=/home/kernel/user-data \
--password-store=basic \
--no-first-run \
${CHROMIUM_FLAGS:-}
else
echo "Running chromium as kernel user"
exec runuser -u kernel -- env \
DISPLAY=":1" \
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/dbus/system_bus_socket" \
Expand Down
112 changes: 55 additions & 57 deletions images/chromium-headful/wrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -211,68 +211,66 @@ if [[ "${ENABLE_WEBRTC:-}" == "true" ]]; then
echo "[wrapper] Port 8080 is open"
fi

if [[ "${WITH_KERNEL_IMAGES_API:-}" == "true" ]]; then
echo "[wrapper] ✨ Starting kernel-images API."

API_PORT="${KERNEL_IMAGES_API_PORT:-10001}"
API_FRAME_RATE="${KERNEL_IMAGES_API_FRAME_RATE:-10}"
API_DISPLAY_NUM="${KERNEL_IMAGES_API_DISPLAY_NUM:-${DISPLAY_NUM:-1}}"
API_MAX_SIZE_MB="${KERNEL_IMAGES_API_MAX_SIZE_MB:-500}"
API_OUTPUT_DIR="${KERNEL_IMAGES_API_OUTPUT_DIR:-/recordings}"

# Start via supervisord (env overrides are read by the service's command)
supervisorctl -c /etc/supervisor/supervisord.conf start kernel-images-api
# close the "--no-sandbox unsupported flag" warning when running as root
# in the unikernel runtime we haven't been able to get chromium to launch as non-root without cryptic crashpad errors
# and when running as root you must use the --no-sandbox flag, which generates a warning
if [[ "${RUN_AS_ROOT:-}" == "true" ]]; then
echo "[wrapper] Running as root, attempting to dismiss the --no-sandbox unsupported flag warning"
if read -r WIDTH HEIGHT <<< "$(xdotool getdisplaygeometry 2>/dev/null)"; then
# Work out an x-coordinate slightly inside the right-hand edge of the
OFFSET_X=$(( WIDTH - 30 ))
if (( OFFSET_X < 0 )); then
OFFSET_X=0
fi
echo "[wrapper] ✨ Starting kernel-images API."

API_PORT="${KERNEL_IMAGES_API_PORT:-10001}"
API_FRAME_RATE="${KERNEL_IMAGES_API_FRAME_RATE:-10}"
API_DISPLAY_NUM="${KERNEL_IMAGES_API_DISPLAY_NUM:-${DISPLAY_NUM:-1}}"
API_MAX_SIZE_MB="${KERNEL_IMAGES_API_MAX_SIZE_MB:-500}"
API_OUTPUT_DIR="${KERNEL_IMAGES_API_OUTPUT_DIR:-/recordings}"

# Start via supervisord (env overrides are read by the service's command)
supervisorctl -c /etc/supervisor/supervisord.conf start kernel-images-api
# close the "--no-sandbox unsupported flag" warning when running as root
# in the unikernel runtime we haven't been able to get chromium to launch as non-root without cryptic crashpad errors
# and when running as root you must use the --no-sandbox flag, which generates a warning
if [[ "${RUN_AS_ROOT:-}" == "true" ]]; then
echo "[wrapper] Running as root, attempting to dismiss the --no-sandbox unsupported flag warning"
if read -r WIDTH HEIGHT <<< "$(xdotool getdisplaygeometry 2>/dev/null)"; then
# Work out an x-coordinate slightly inside the right-hand edge of the
OFFSET_X=$(( WIDTH - 30 ))
if (( OFFSET_X < 0 )); then
OFFSET_X=0
fi

# Wait for kernel-images API port to be ready.
echo "[wrapper] Waiting for kernel-images API port 127.0.0.1:${API_PORT}..."
while ! nc -z 127.0.0.1 "${API_PORT}" 2>/dev/null; do
sleep 0.5
done
echo "[wrapper] Port ${API_PORT} is open"

# Wait for Chromium window to open before dismissing the --no-sandbox warning.
target='New Tab - Chromium'
echo "[wrapper] Waiting for Chromium window \"${target}\" to appear and become active..."
while :; do
win_id=$(xwininfo -root -tree 2>/dev/null | awk -v t="$target" '$0 ~ t {print $1; exit}')
if [[ -n $win_id ]]; then
win_id=${win_id%:}
if xdotool windowactivate --sync "$win_id"; then
echo "[wrapper] Focused window $win_id ($target) on $DISPLAY"
break
fi
# Wait for kernel-images API port to be ready.
echo "[wrapper] Waiting for kernel-images API port 127.0.0.1:${API_PORT}..."
while ! nc -z 127.0.0.1 "${API_PORT}" 2>/dev/null; do
sleep 0.5
done
echo "[wrapper] Port ${API_PORT} is open"

# Wait for Chromium window to open before dismissing the --no-sandbox warning.
target='New Tab - Chromium'
echo "[wrapper] Waiting for Chromium window \"${target}\" to appear and become active..."
while :; do
win_id=$(xwininfo -root -tree 2>/dev/null | awk -v t="$target" '$0 ~ t {print $1; exit}')
if [[ -n $win_id ]]; then
win_id=${win_id%:}
if xdotool windowactivate --sync "$win_id"; then
echo "[wrapper] Focused window $win_id ($target) on $DISPLAY"
break
fi
sleep 0.5
done

# wait... not sure but this just increases the likelihood of success
# without the sleep you often open the live view and see the mouse hovering over the "X" to dismiss the warning, suggesting that it clicked before the warning or chromium appeared
sleep 5

# Attempt to click the warning's close button
echo "[wrapper] Clicking the warning's close button at x=$OFFSET_X y=115"
if curl -s -o /dev/null -X POST \
http://localhost:${API_PORT}/computer/click_mouse \
-H "Content-Type: application/json" \
-d "{\"x\":${OFFSET_X},\"y\":115}"; then
echo "[wrapper] Successfully clicked the warning's close button"
else
echo "[wrapper] Failed to click the warning's close button" >&2
fi
sleep 0.5
done

# wait... not sure but this just increases the likelihood of success
# without the sleep you often open the live view and see the mouse hovering over the "X" to dismiss the warning, suggesting that it clicked before the warning or chromium appeared
sleep 5

# Attempt to click the warning's close button
echo "[wrapper] Clicking the warning's close button at x=$OFFSET_X y=115"
if curl -s -o /dev/null -X POST \
http://localhost:${API_PORT}/computer/click_mouse \
-H "Content-Type: application/json" \
-d "{\"x\":${OFFSET_X},\"y\":115}"; then
echo "[wrapper] Successfully clicked the warning's close button"
else
echo "[wrapper] xdotool failed to obtain display geometry; skipping sandbox warning dismissal." >&2
echo "[wrapper] Failed to click the warning's close button" >&2
fi
else
echo "[wrapper] xdotool failed to obtain display geometry; skipping sandbox warning dismissal." >&2
fi
fi

Expand Down
3 changes: 2 additions & 1 deletion images/chromium-headless/image/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ RUN set -eux; \
# Remove upower to prevent spurious D-Bus activations and logs
RUN apt-get -yqq purge upower || true && rm -rf /var/lib/apt/lists/*

ENV WITHDOCKER=true

# Create a non-root user with a home directory
RUN useradd -m -s /bin/bash kernel

Expand All @@ -84,6 +86,5 @@ COPY images/chromium-headless/image/supervisor/services/ /etc/supervisor/conf.d/

# Copy the kernel-images API binary built in the builder stage
COPY --from=server-builder /out/kernel-images-api /usr/local/bin/kernel-images-api
ENV WITH_KERNEL_IMAGES_API=false

ENTRYPOINT [ "/usr/bin/wrapper.sh" ]
1 change: 1 addition & 0 deletions images/chromium-headless/image/start-chromium.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ if [[ "$RUN_AS_ROOT" == "true" ]]; then
--no-first-run \
${CHROMIUM_FLAGS:-}
else
echo "Running chromium as kernel user"
exec runuser -u kernel -- env \
DISPLAY=":1" \
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/dbus/system_bus_socket" \
Expand Down
27 changes: 16 additions & 11 deletions images/chromium-headless/image/wrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
set -o pipefail -o errexit -o nounset

# If we are outside Docker-in-Docker make sure /dev/shm exists
if [ -z "${WITH_DOCKER:-}" ]; then
if [ -z "${WITHDOCKER:-}" ]; then
mkdir -p /dev/shm
chmod 777 /dev/shm
mount -t tmpfs tmpfs /dev/shm
Expand Down Expand Up @@ -90,26 +90,33 @@ export CHROMIUM_FLAGS
# -----------------------------------------------------------------------------
if [[ "${RUN_AS_ROOT:-}" != "true" ]]; then
dirs=(
/home/kernel/user-data
/home/kernel/.config/chromium
/home/kernel/.pki/nssdb
/home/kernel/.cache/dconf
/tmp
/var/log
/var/log/supervisord
)

for dir in "${dirs[@]}"; do
if [ ! -d "$dir" ]; then
mkdir -p "$dir"
fi
done

# Ensure correct ownership (ignore errors if already correct)
chown -R kernel:kernel /home/kernel/.pki /home/kernel/.cache 2>/dev/null || true
chown -R kernel:kernel /home/kernel /home/kernel/user-data /home/kernel/.config /home/kernel/.pki /home/kernel/.cache 2>/dev/null || true
else
# When running as root, just create the necessary directories without ownership changes
dirs=(
/tmp
/var/log
/var/log/supervisord
/home/kernel
/home/kernel/user-data
)

for dir in "${dirs[@]}"; do
if [ ! -d "$dir" ]; then
mkdir -p "$dir"
Expand Down Expand Up @@ -215,15 +222,13 @@ for i in {1..100}; do
sleep 0.2
done

if [[ "${WITH_KERNEL_IMAGES_API:-}" == "true" ]]; then
echo "[wrapper] ✨ Starting kernel-images API via supervisord."
supervisorctl -c /etc/supervisor/supervisord.conf start kernel-images-api
API_PORT="${KERNEL_IMAGES_API_PORT:-10001}"
echo "[wrapper] Waiting for kernel-images API on 127.0.0.1:${API_PORT}..."
while ! (echo >/dev/tcp/127.0.0.1/"${API_PORT}") >/dev/null 2>&1; do
sleep 0.5
done
fi
echo "[wrapper] ✨ Starting kernel-images API via supervisord."
supervisorctl -c /etc/supervisor/supervisord.conf start kernel-images-api
API_PORT="${KERNEL_IMAGES_API_PORT:-10001}"
echo "[wrapper] Waiting for kernel-images API on 127.0.0.1:${API_PORT}..."
while ! (echo >/dev/tcp/127.0.0.1/"${API_PORT}") >/dev/null 2>&1; do
sleep 0.5
done

echo "[wrapper] startup complete!"
# Re-enable scale-to-zero once startup has completed (when not under Docker)
Expand Down
9 changes: 2 additions & 7 deletions images/chromium-headless/run-docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,10 @@ RUN_ARGS=(
--privileged
--tmpfs /dev/shm:size=2g
-p 9222:9222
-e WITH_DOCKER=true
-p 444:10001
-v "$HOST_RECORDINGS_DIR:/recordings"
)

if [[ "${WITH_KERNEL_IMAGES_API:-}" == "true" ]]; then
RUN_ARGS+=( -p 444:10001 )
RUN_ARGS+=( -e WITH_KERNEL_IMAGES_API=true )
RUN_ARGS+=( -v "$HOST_RECORDINGS_DIR:/recordings" )
fi

# If a positional argument is given, use it as the entrypoint
ENTRYPOINT_ARG=()
if [[ $# -ge 1 && -n "$1" ]]; then
Expand Down
16 changes: 9 additions & 7 deletions images/chromium-headless/run-unikernel.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@ source ../../shared/ensure-common-build-run-vars.sh chromium-headless

kraft cloud inst rm "$NAME" || true

RUN_AS_ROOT="${RUN_AS_ROOT:-false}"

deploy_args=(
--start
-M 1G
--scale-to-zero idle
--scale-to-zero-cooldown 3000ms
--scale-to-zero-stateful
-M 1024
-e RUN_AS_ROOT="$RUN_AS_ROOT"
-p 9222:9222/tls
--vcpus 1
-p 444:10001/tls
--vcpus 2
-n "$NAME"
)

if [[ "${WITH_KERNEL_IMAGES_API:-}" == "true" ]]; then
deploy_args+=( -p 444:10001/tls )
deploy_args+=( -e WITH_KERNEL_IMAGES_API=true )
fi

kraft cloud inst create "${deploy_args[@]}" "$IMAGE"
Loading
Loading