#!/usr/bin/env bash # Start Xvfb + x11vnc + noVNC so a human can complete Reddit login # through the dashboard, then exec the Node bot which drives Chromium # on that virtual display. set -euo pipefail DISPLAY_NUM="${VNC_DISPLAY_NUM:-99}" VNC_PORT="${VNC_PORT:-5900}" NOVNC_PORT="${NOVNC_PORT:-6080}" GEOMETRY="${SCREEN_GEOMETRY:-1280x800x24}" export DISPLAY=":${DISPLAY_NUM}" # noVNC ships under different paths depending on the distro; find the web root once. if [ -d /usr/share/novnc ]; then NOVNC_WEB_DIR=/usr/share/novnc elif [ -d /usr/share/webapps/novnc ]; then NOVNC_WEB_DIR=/usr/share/webapps/novnc else echo "[entrypoint] could not locate noVNC web root" >&2 exit 1 fi # Make / on the noVNC server land on vnc.html with autoconnect. if [ ! -e "${NOVNC_WEB_DIR}/index.html" ] && [ -e "${NOVNC_WEB_DIR}/vnc.html" ]; then ln -sf vnc.html "${NOVNC_WEB_DIR}/index.html" fi echo "[entrypoint] starting Xvfb on ${DISPLAY} (${GEOMETRY})" Xvfb "${DISPLAY}" -screen 0 "${GEOMETRY}" -ac +extension RANDR & XVFB_PID=$! # Give Xvfb a moment to come up. Requires x11-utils (xdpyinfo). for i in $(seq 1 50); do if xdpyinfo -display "${DISPLAY}" >/dev/null 2>&1; then echo "[entrypoint] Xvfb is ready after ${i} checks" break fi sleep 0.2 if [ "${i}" = "50" ]; then echo "[entrypoint] WARNING: Xvfb did not respond after 10s" >&2 fi done # Minimal window manager so dialogs and tabs aren't stuck behind the root window. if command -v fluxbox >/dev/null 2>&1; then fluxbox >/dev/null 2>&1 & fi VNC_ARGS=(-display "${DISPLAY}" -forever -shared -rfbport "${VNC_PORT}" -nopw_warn) if [ -n "${VNC_PASSWORD:-}" ]; then mkdir -p /root/.vnc x11vnc -storepasswd "${VNC_PASSWORD}" /root/.vnc/passwd >/dev/null VNC_ARGS+=(-rfbauth /root/.vnc/passwd) echo "[entrypoint] x11vnc starting with password auth" else VNC_ARGS+=(-nopw) echo "[entrypoint] WARNING: VNC_PASSWORD not set — VNC has no auth" fi x11vnc "${VNC_ARGS[@]}" >/var/log/x11vnc.log 2>&1 & X11VNC_PID=$! echo "[entrypoint] starting noVNC (websockify) on :${NOVNC_PORT}" websockify --web "${NOVNC_WEB_DIR}" "${NOVNC_PORT}" "localhost:${VNC_PORT}" \ >/var/log/websockify.log 2>&1 & NOVNC_PID=$! cleanup() { echo "[entrypoint] shutting down" kill "${NOVNC_PID}" "${X11VNC_PID}" "${XVFB_PID}" 2>/dev/null || true wait || true } trap cleanup TERM INT EXIT echo "[entrypoint] launching bot" exec node dist/index.js