Fix kiosk mode

This commit is contained in:
Audiobuzz
2026-06-17 13:20:52 +00:00
parent fd84ba4180
commit 4b0e0135b3
5 changed files with 111 additions and 55 deletions
+44 -17
View File
@@ -1,22 +1,49 @@
#!/bin/bash
# kiosk-session — launched by cage (Wayland) from kiosk.service.
# Starts Chromium fullscreen on the configured URL.
# kiosk-session — main process of kiosk.service.
#
# KIOSK_URL comes from /etc/kiosk/kiosk.env (baked from the kiosk_url Packer
# var; a runtime config-agent could override it later). The Chromium profile is
# pinned to a tmpfs path so writes land in RAM (the root is read-only erofs +
# volatile overlay) — watch RAM if the page is heavy.
# Launches the weston compositor in the FOREGROUND (so it owns the logind seat
# session systemd set up via PAMName=login) and, once weston's Wayland socket is
# up, runs Chromium fullscreen in the BACKGROUND with a crash-restart loop.
#
# VM/GPU notes: --disable-gpu + the pixman wlroots renderer (WLR_RENDERER in
# kiosk.env) keep this working on VMs with no real GPU. On hardware with a GPU,
# drop --disable-gpu (and set WLR_RENDERER=gles2) for compositing.
set -euo pipefail
# Why a wrapper instead of weston.ini [autolaunch]: EPEL 9 ships weston 8.0,
# which has neither kiosk-shell.so nor [autolaunch] (both weston 9.0). So weston
# runs desktop-shell.so (see weston.ini) and we start Chromium here.
#
# Process model: systemd -> this script -> exec weston. The Chromium loop is
# forked before the exec, so it lives in the unit's cgroup; when weston exits the
# service is torn down (KillMode=control-group) and the loop dies with it. If
# Chromium alone crashes, the loop relaunches it without taking weston down.
#
# KIOSK_URL comes from /etc/kiosk/kiosk.env. The Chromium profile/cache live on
# tmpfs (root is read-only erofs + volatile overlay) — writes land in RAM; watch
# RAM if the page is heavy (it can starve the NVMe-oF keep-alive — see TODO).
set -uo pipefail
BROWSER=$(command -v chromium-browser || command -v chromium)
: "${KIOSK_URL:?KIOSK_URL not set in /etc/kiosk/kiosk.env}"
export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
SOCK=wayland-kiosk
exec "$BROWSER" \
--kiosk --noerrdialogs --disable-infobars --incognito --no-first-run \
--disable-session-crashed-bubble --start-maximized \
--ozone-platform=wayland --disable-gpu \
--user-data-dir=/tmp/kiosk-profile --disk-cache-dir=/tmp/kiosk-cache \
"${KIOSK_URL:?KIOSK_URL not set in /etc/kiosk/kiosk.env}"
BROWSER=$(command -v chromium-browser || command -v chromium || true)
: "${BROWSER:?chromium not found (expected chromium-browser or chromium in PATH)}"
# Background: wait (up to ~60s) for weston's socket, then keep Chromium running.
(
for _ in $(seq 1 120); do
[ -S "$XDG_RUNTIME_DIR/$SOCK" ] && break
sleep 0.5
done
export WAYLAND_DISPLAY="$SOCK"
while :; do
"$BROWSER" \
--kiosk --noerrdialogs --disable-infobars --incognito --no-first-run \
--disable-session-crashed-bubble --start-maximized \
--ozone-platform=wayland --disable-gpu \
--user-data-dir=/tmp/kiosk-profile --disk-cache-dir=/tmp/kiosk-cache \
"$KIOSK_URL" || true
sleep 2
done
) &
# weston as the foreground process (owns the seat; service restarts if it dies).
# desktop-shell + explicit socket; --use-pixman = software rendering for VMs.
exec weston --use-pixman --socket="$SOCK" --config=/etc/xdg/weston/weston.ini
+14 -10
View File
@@ -1,5 +1,5 @@
[Unit]
Description=Wayland kiosk (weston kiosk-shell + Chromium)
Description=Wayland kiosk (weston desktop-shell + Chromium)
Documentation=man:weston(1) man:weston.ini(5)
# Take over tty1 from the login getty and start after the network is up (the
# kiosk loads a URL). plymouth-quit lets the splash hand off cleanly.
@@ -10,10 +10,15 @@ Conflicts=getty@tty1.service
[Service]
Type=simple
User=kiosk
# A real PAM login session on tty1 so logind assigns seat0 — cage/wlroots needs
# a seat for DRM master + libinput. (PAMName runs account/session, not auth, so
# the passwordless kiosk user is fine.)
# A real PAM login session on tty1 so logind assigns seat0 — weston needs a seat
# for DRM master + libinput. (PAMName runs account/session, not auth, so the
# passwordless kiosk user is fine.) XDG_SEAT/XDG_VTNR are set into the PAM
# environment before pam_open_session, so pam_systemd registers the session on
# seat0/vt1 — WITHOUT them logind's auto-derivation failed and weston died with
# "logind: failed to get session seat" -> "failed to create compositor backend".
PAMName=login
Environment=XDG_SEAT=seat0
Environment=XDG_VTNR=1
TTYPath=/dev/tty1
TTYReset=yes
TTYVHangup=yes
@@ -24,12 +29,11 @@ StandardError=journal
UtmpIdentifier=tty1
UtmpMode=user
EnvironmentFile=/etc/kiosk/kiosk.env
# weston with kiosk-shell (every app fullscreen). --use-pixman = software
# rendering for VMs/no-GPU. weston.ini's [autolaunch] runs /usr/local/bin/
# kiosk-session (Chromium) and, with watch=true, weston exits if it dies — so
# Restart=always relaunches the whole stack. cage (the original choice) isn't
# packaged for EL9; weston kiosk-shell is the minimal EL9-available equivalent.
ExecStart=/usr/bin/weston --use-pixman --config=/etc/xdg/weston/weston.ini
# kiosk-session launches weston (foreground, owns the seat) + Chromium. weston
# 8.0 (EPEL 9) lacks kiosk-shell.so/[autolaunch], so the wrapper does what those
# would have — see kiosk-session and weston.ini. If weston dies, Restart=always
# relaunches the whole stack; a Chromium-only crash is handled inside the wrapper.
ExecStart=/usr/local/bin/kiosk-session
Restart=always
RestartSec=2
+16 -9
View File
@@ -1,12 +1,15 @@
# weston kiosk configuration (consumed by kiosk.service: weston --config=...).
# weston kiosk configuration (consumed by kiosk-session: weston --config=...).
#
# kiosk-shell makes every client fullscreen with no decorations/desktop — the
# kiosk behaviour cage gave us. The [autolaunch] app is the Chromium wrapper;
# watch=true makes weston exit when it exits, so kiosk.service (Restart=always)
# relaunches the whole stack on a browser crash.
# Target is EPEL 9's weston 8.0, which has NEITHER kiosk-shell.so NOR the
# [autolaunch] section (both arrived in weston 9.0). So we use desktop-shell.so —
# the only packaged shell that Chromium's xdg-shell surfaces work with — stripped
# down to a bare black surface, and launch Chromium ourselves from kiosk-session.
# Chromium --kiosk then fullscreens over this shell.
[core]
shell=kiosk-shell.so
# desktop-shell.so is the shell; fullscreen-shell needs a special client protocol
# Chromium doesn't speak, and kiosk-shell isn't in this weston.
shell=desktop-shell.so
# No screen blanking on a kiosk.
idle-time=0
# Don't refuse to start if no input device is present (headless/VM consoles).
@@ -14,6 +17,10 @@ require-input=false
# No X11 apps here — Chromium runs native Wayland (--ozone-platform=wayland).
xwayland=false
[autolaunch]
path=/usr/local/bin/kiosk-session
watch=true
[shell]
# Bare kiosk surface: no panel, solid black background, no animations, no lock.
# Chromium --kiosk draws fullscreen on top of this.
panel-position=none
background-color=0xff000000
animation=none
locking=false