Files
mirror/docs/kiosk-silverblue/mirror-kiosk-console-guard
ducoterra 7d4bcf7e23 fix(kiosk): stop GDM covering the wall with a greeter after auto-login
Auto-login succeeded and the wall kept streaming, but about ten seconds
after the kiosk session came up GDM autospawned a greeter on the same GPU
and a login screen covered it. gnome-kiosk ships X-GDM-SessionRegisters=false,
so nothing ever registers and GDM concludes the display is still free — which
is why every remote check (loginctl, the mirror roster) stayed green while
the physical screen showed a password prompt.

Override that session file with the flag set to true, keeping the file name
and session id identical: inventing an id makes GDM quietly fall back to the
plain GNOME session, top bar and all.

Add a per-minute guard that reclaims the foreground VT, because this class
of failure is invisible from the outside, and have the checker assert both
the foreground VT and the greeter-session count. That count had a silent
false green: journalctl has no --no-legend, so the check read an empty
stream and passed unconditionally.

Also keep a copy of the payload in /usr/local/share/mirror-kiosk. /tmp is
cleared at every boot, which deletes the checker just after the one event
you are most likely to want to re-run it for.

Verified on the reference client: a cold boot now creates no greeter session
at all, the kiosk compositor and Firefox come up undisturbed, and a console
stolen with chvt is taken back within a minute.

LLM-Generated: true
2026-11-01 19:46:17 -05:00

55 lines
2.3 KiB
Bash

#!/bin/sh
# mirror-kiosk-console-guard — make sure the kiosk owns the console.
#
# Run by mirror-kiosk-console-guard.timer once a minute as root.
#
# The failure this exists for is invisible remotely: the kiosk session keeps
# running (loginctl says active, the mirror roster counts the wall as a viewer)
# while some other session holds the foreground VT, so the screen shows a login
# prompt and every check says everything is fine. That is exactly how the
# greeter-autospawn bug presented itself.
#
# It deliberately does very little: if the kiosk HAS a seat0 session and that
# session is not the foreground one, activate it. It never restarts gdm and
# never logs anyone out, because a display manager is a bad thing to fight
# automatically. If there is no kiosk session at all it only says so — that is a
# problem for a human, and the message lands in the journal.
#
# Debugging the console by hand? Stop the fight:
# sudo systemctl stop mirror-kiosk-console-guard.timer
set -eu
KIOSK_USER="${KIOSK_USER:-kiosk}"
FG_VT=/sys/class/tty/tty0/active
say() { logger -t mirror-kiosk-guard -- "$*"; }
[ "$(id -u)" -eq 0 ] || { printf 'run me as root\n' >&2; exit 1; }
# SESSION UID USER SEAT ... — the kiosk's own session on the physical seat. The
# greeter also sits on seat0 but under the gdm-greeter user, so the name filter
# is what keeps this from chasing the greeter.
session=$(loginctl list-sessions --no-legend 2>/dev/null |
awk -v u="$KIOSK_USER" '$3 == u && $4 == "seat0" { print $1; exit }')
if [ -z "$session" ]; then
say "no $KIOSK_USER session on seat0: auto-login did not produce one. Not touching gdm."
exit 0
fi
active=$(loginctl show-session "$session" -p Active --value 2>/dev/null || echo unknown)
tty=$(loginctl show-session "$session" -p TTY --value 2>/dev/null || echo "")
foreground=$(cat "$FG_VT" 2>/dev/null || echo "")
if [ "$active" = "yes" ] && [ -n "$tty" ] && [ "$foreground" = "$tty" ]; then
exit 0 # the wall already has the screen
fi
say "console is on ${foreground:-unknown}, kiosk session $session is on ${tty:-unknown} (Active=$active) — activating it"
if loginctl activate "$session" 2>/dev/null; then
say "kiosk session $session brought back to the foreground"
else
say "could not activate kiosk session $session — look at journalctl -b -u gdm"
fi