#!/bin/sh # check-kiosk.sh โ€” read-only report on a mirror kiosk client. Run ON THE CLIENT. # # sudo sh check-kiosk.sh # # PASS/FAIL describe this machine; WARN means "configured fine, but the thing # you can see on the screen will still be wrong". Exits non-zero on FAIL. # # Nothing here needs the console: every check is readable over SSH, which is # the whole point of a kiosk you never plug a keyboard into. KIOSK_USER="${KIOSK_USER:-kiosk}" FAILS=0 ok() { printf 'PASS %s\n' "$*"; } bad() { printf 'FAIL %s\n' "$*"; FAILS=$((FAILS + 1)); } warn() { printf 'WARN %s\n' "$*"; } info() { printf 'info %s\n' "$*"; } SUDO="" [ "$(id -u)" -eq 0 ] || SUDO="sudo" printf '%s\n' '--- machine ---' if [ -f /etc/os-release ]; then info "$( . /etc/os-release && printf '%s %s' "$NAME" "$VERSION_ID" ) on $(uname -m)" fi if command -v rpm-ostree >/dev/null 2>&1; then info "booted deployment: $(rpm-ostree status 2>/dev/null | sed -n 's/^ *โ— *//p' | head -1)" info "layered: $(rpm-ostree status 2>/dev/null | sed -n 's/^ *LayeredPackages: //p' | head -1)" fi printf '\n%s\n' '--- packages ---' for p in gnome-kiosk gnome-kiosk-script-session firefox; do if rpm -q "$p" >/dev/null 2>&1; then ok "$p installed"; else bad "$p not installed (rpm-ostree install $p)"; fi done printf '\n%s\n' '--- user ---' if id -u "$KIOSK_USER" >/dev/null 2>&1; then HOME_DIR=$(getent passwd "$KIOSK_USER" | cut -d: -f6) ok "user $KIOSK_USER exists, home $HOME_DIR" else bad "user $KIOSK_USER does not exist" HOME_DIR="" fi printf '\n%s\n' '--- payload ---' check_file() { path=$1 needle=$2 label=$3 if [ -f "$path" ]; then if [ -n "$needle" ] && ! $SUDO grep -q "$needle" "$path" 2>/dev/null; then bad "$label: $path exists but has no '$needle'" else ok "$label: $path" fi else bad "$label: $path is missing" fi } URL="" if [ -n "$HOME_DIR" ]; then check_file "$HOME_DIR/.local/bin/gnome-kiosk-script" "firefox --kiosk" "kiosk script" if [ -f "$HOME_DIR/.config/mirror/kiosk.conf" ]; then URL=$($SUDO sed -n 's/^MIRROR_KIOSK_URL="\{0,1\}\([^"]*\)"\{0,1\}$/\1/p' \ "$HOME_DIR/.config/mirror/kiosk.conf" 2>/dev/null | head -1) ok "kiosk URL: ${URL:-}" case "$URL" in */watch) : ;; "") bad "kiosk URL is empty" ;; *) warn "kiosk URL is not the /watch wall: $URL" ;; esac else bad "kiosk config $HOME_DIR/.config/mirror/kiosk.conf is missing" fi check_file "$HOME_DIR/.config/gnome-initial-setup-done" "" "initial-setup guard" fi check_file /etc/firefox/policies/policies.json "DisableAppUpdate" "firefox policy" check_file /usr/local/share/gnome-kiosk/window-config.ini "org.mozilla" "kiosk window rules" printf '\n%s\n' '--- session wiring ---' ACCT="/var/lib/AccountsService/users/$KIOSK_USER" if [ -f "$ACCT" ] && $SUDO grep -q '^Session=gnome-kiosk-script-wayland' "$ACCT"; then ok "AccountsService default session is the kiosk" else bad "AccountsService session for $KIOSK_USER is not gnome-kiosk-script-wayland" [ -f "$ACCT" ] && info "$($SUDO cat "$ACCT" 2>/dev/null | tr '\n' ' ')" fi if [ -f /etc/gdm/custom.conf ] && $SUDO grep -qi "^AutomaticLogin=$KIOSK_USER\$" /etc/gdm/custom.conf && $SUDO grep -qi "^AutomaticLoginEnable=True" /etc/gdm/custom.conf; then ok "gdm auto-login targets $KIOSK_USER" else bad "gdm auto-login is not enabled for $KIOSK_USER" fi printf '\n%s\n' '--- running state ---' SEAT_USER=$(loginctl list-sessions --no-legend 2>/dev/null | awk '$4=="seat0"{print $3; exit}') if [ -z "$SEAT_USER" ]; then warn "nobody is logged in on seat0 (sudo systemctl restart gdm)" elif [ "$SEAT_USER" = "$KIOSK_USER" ]; then ok "seat0 is logged in as $KIOSK_USER" else bad "seat0 is logged in as '$SEAT_USER', not $KIOSK_USER (sudo systemctl restart gdm)" fi SEAT_SESSION=$(loginctl list-sessions --no-legend 2>/dev/null | awk '$4=="seat0"{print $1; exit}') if [ -n "$SEAT_SESSION" ]; then info "seat0 session $SEAT_SESSION: class=$(loginctl show-session "$SEAT_SESSION" -p Class --value 2>/dev/null) type=$(loginctl show-session "$SEAT_SESSION" -p Type --value 2>/dev/null) vt=$(loginctl show-session "$SEAT_SESSION" -p VTHint --value 2>/dev/null)" fi if [ -n "$HOME_DIR" ]; then KUID=$(id -u "$KIOSK_USER") FF=$(pgrep -u "$KUID" -a firefox 2>/dev/null | head -1) if [ -z "$FF" ]; then warn "no firefox running as $KIOSK_USER yet" else case "$FF" in *--kiosk*) ok "$FF" ;; *) warn "firefox is running without --kiosk: $FF" ;; esac fi if [ -f "$HOME_DIR/.local/state/mirror-kiosk.log" ]; then info "last kiosk log lines:" $SUDO tail -5 "$HOME_DIR/.local/state/mirror-kiosk.log" 2>/dev/null | sed 's/^/ /' fi fi printf '\n%s\n' '--- what the screen will show ---' if [ -n "$URL" ]; then BODY=$(curl -fsSL -m 8 "$URL" 2>/dev/null) if [ -z "$BODY" ]; then warn "$URL is not reachable from this machine right now" else CODE=$(curl -s -o /dev/null -w '%{http_code}' -m 8 "$URL" 2>/dev/null) if printf '%s' "$BODY" | grep -q "Watch ยท mirror"; then ok "$URL serves the mirror watch page (HTTP $CODE)" else warn "$URL answered HTTP $CODE but it is NOT the mirror watch page โ€” the kiosk" warn "will happily display whatever this is. Check DNS and the nginx vhost." info "title: $(printf '%s' "$BODY" | sed -n 's/.*\(.*\)<\/title>.*/\1/p' | head -1)" fi fi else info "no URL configured, nothing to fetch" fi printf '\n' if [ "$FAILS" -gt 0 ]; then printf '%s check(s) FAILED.\n' "$FAILS" exit 1 fi printf 'All checks passed.\n'