-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstart.sh
More file actions
110 lines (101 loc) · 4.74 KB
/
Copy pathstart.sh
File metadata and controls
110 lines (101 loc) · 4.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/bin/sh
# Launch ONE long-lived Chromium + Xvfb + x11vnc + noVNC + socat CDP bridge.
# Chromium's lifecycle is independent of the VNC session, so a human login
# persists for an agent driving CDP. If Chromium dies, the script exits so the
# orchestrator (e.g. K8s) restarts the container. All knobs are env-driven.
set -eu
PROFILE="${PROFILE_DIR:-/data}"
DISP="${DISPLAY:-:99}"
CDP_PORT="${CDP_PORT:-9222}"
CDP_INTERNAL_PORT="${CDP_INTERNAL_PORT:-9223}"
NOVNC_PORT="${NOVNC_PORT:-6080}"
VNC_PORT="${VNC_PORT:-5900}"
SCREEN="${SCREEN:-1440x900x24}"
CHROME_EXTRA_FLAGS="${CHROME_EXTRA_FLAGS:-}"
VNC_PASSWORD="${VNC_PASSWORD:-}"
export DISPLAY="$DISP"
# Window size derived from SCREEN (WxHxDEPTH) so Chromium fills the display.
WIN_W="$(echo "$SCREEN" | cut -dx -f1)"
WIN_H="$(echo "$SCREEN" | cut -dx -f2)"
mkdir -p "$PROFILE"
# Clear any stale SingletonLock from an unclean restart (would block Chromium).
rm -f "$PROFILE"/Singleton* 2>/dev/null || true
# Virtual display.
Xvfb "$DISP" -screen 0 "$SCREEN" -ac +extension RANDR >/tmp/xvfb.log 2>&1 &
sleep 2
# The one persistent Chromium. Runs as a non-root uid WITH the sandbox enabled
# (no --no-sandbox), so Google stops flagging the session as insecure; the node
# must allow unprivileged user namespaces. CDP binds loopback (M113 requires a
# non-public bind); socat re-exposes it on CDP_PORT. Flags (WHY each matters):
# --disable-dev-shm-usage : containers have a tiny /dev/shm; without this a
# heavy page can crash the renderer (we still mount a 2Gi /dev/shm too).
# --disable-gpu : no GPU in the container; SwiftShader churn can
# wedge the renderer.
# --disable-background-timer-throttling / --disable-backgrounding-occluded-
# windows / --disable-renderer-backgrounding : a headful tab nobody is
# looking at gets throttled/suspended, which stalls CDP commands and
# drops the long-lived debugger socket. Keep the page hot.
# --restore-last-session + NO positional URL : reopen the last tabs after a roll;
# a startup URL (e.g. about:blank) overrides restore, so the browser comes
# back blank and drops the logged-in tab on every restart.
chromium \
--disable-dev-shm-usage \
--disable-gpu \
--disable-background-timer-throttling \
--disable-backgrounding-occluded-windows \
--disable-renderer-backgrounding \
--user-data-dir="$PROFILE" \
--remote-debugging-port="$CDP_INTERNAL_PORT" \
--remote-debugging-address=127.0.0.1 \
--remote-allow-origins='*' \
--no-first-run --no-default-browser-check \
--password-store=basic \
--window-size="${WIN_W},${WIN_H}" --start-maximized \
--restore-last-session \
$CHROME_EXTRA_FLAGS \
>/tmp/chromium.log 2>&1 &
CHROMIUM_PID=$!
# Forward pod SIGTERM to Chromium and wait for its clean exit so cookies + session
# state flush to /data before SIGKILL. Without this, a clean shutdown purges the
# session-scoped login cookie and the next boot starts logged out. Paired with
# --restore-last-session above, which re-adopts session cookies on every boot.
term() {
kill -TERM "$CHROMIUM_PID" 2>/dev/null || true
wait "$CHROMIUM_PID" 2>/dev/null || true
exit 0
}
trap term TERM INT
# Bridge 0.0.0.0:CDP_PORT -> 127.0.0.1:CDP_INTERNAL_PORT for the CDP client.
# Hardened for a long-lived debugger WebSocket (trace 019e7733: the socket was
# dropped between every action, forcing reconnects):
# keepalive + keepidle/keepintvl/keepcnt : probe the TCP path so an idle-but-
# alive CDP connection is kept open instead of silently half-closing.
# -T 0 : disable socat's inactivity timeout so an idle CDP socket is NEVER
# cut (a busy agent may pause between commands).
sleep 4
socat -T 0 \
TCP-LISTEN:"$CDP_PORT",fork,reuseaddr,keepalive,keepidle=30,keepintvl=10,keepcnt=3 \
TCP:127.0.0.1:"$CDP_INTERNAL_PORT",keepalive \
>/tmp/socat.log 2>&1 &
# Human view: x11vnc mirrors the display (disconnect does NOT stop Chromium).
# Empty VNC_PASSWORD => -nopw (open, intended for cluster-internal only). Set it
# => hash via x11vnc -storepasswd and serve with -rfbauth.
if [ -n "$VNC_PASSWORD" ]; then
x11vnc -storepasswd "$VNC_PASSWORD" /tmp/vncpass >/dev/null 2>&1
AUTH="-rfbauth /tmp/vncpass"
else
AUTH="-nopw"
fi
# shellcheck disable=SC2086
x11vnc -display "$DISP" -forever -shared $AUTH -rfbport "$VNC_PORT" -quiet \
>/tmp/x11vnc.log 2>&1 &
sleep 1
websockify --web /usr/share/novnc "$NOVNC_PORT" "localhost:$VNC_PORT" \
>/tmp/novnc.log 2>&1 &
# Tie container life to Chromium: exit (→ restart) only if Chromium dies. Loop so
# the TERM trap can fire, flush cookies, and exit cleanly instead of being
# SIGKILLed. The CDP bridge and VNC stack are disposable; the session is the asset.
while kill -0 "$CHROMIUM_PID" 2>/dev/null; do
wait "$CHROMIUM_PID" 2>/dev/null && break
done
echo "chromium exited; shutting down" >&2