Files
ansible/roles/pi_kiosk
Martin Bauer 831a1b50a4 Run the kiosk on Chromium, and take the stray media server off musicdolphin
Chromium: same page, same machine, idle, Firefox 24.2% of a core against Chromium's
11.4%. The build comes from archive.raspberrypi.com (a "+rpt" version) and is patched
for this board's V3D GPU; Debian ships a much older chromium, so the archive matters.
The whole userland here is 32-bit armhf on a 64-bit kernel, which Firefox handles worse
than Chromium does. --use-gl=egl, --enable-gpu-rasterization, --ignore-gpu-blocklist
and --enable-zero-copy are what keep rasterization on the GPU: Chromium's blocklist
does not recognise this driver and silently falls back to software without them.
pi_kiosk_browser: firefox still works, as the fallback if an update ever regresses.

Debug mode also gains xdotool, scrot and --remote-debugging-port=9222 (on 127.0.0.1),
because firing XTEST key events at a window lands about half the time and a benchmark
you cannot verify the state of is worse than none.

pi_squeezeserver gains an absent path, and mediapis.yml derives its state from
mediapi_has_squeezeserver, which defaults to false for the whole group. false means
"actively remove", not "skip": musicdolphin has been running a Logitech Media Server
that no playbook installs and nothing talks to - every squeezelite in the fleet points
at pi_squeezelite_squeezeserver (192.168.178.80, the server) - while costing ~30 MB
resident and ~47 MB of swap on a 2 GB Pi that also drives the kiosk. The absent path
stops it, purges the package, unregisters it from sysdweb, drops the port 80 -> 9000
redirect and deletes its database and logs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 15:13:16 +02:00
..

pi_kiosk

Turns a Pi with a monitor attached into a full-screen browser display: an autologin console user runs startx, whose .xinitrc starts Openbox and then the browser pointed at pi_kiosk_url, relaunching it if it ever exits. If X itself crashes, .bash_profile restarts it.

Vars:

  • pi_kiosk_user (default kiosk) - the account that autologs into tty1.
  • pi_kiosk_url (default http://localhost:8080) - what the browser shows.
  • pi_kiosk_browser (default chromium) - chromium or firefox, see below.
  • pi_kiosk_mode (default kiosk) - kiosk or debug, see below.

Meant to run alongside pi_musicmouse on the same host when it's serving the page locally (the default pi_kiosk_url), gated in mediapis.yml by mediapi_has_monitor.

Why Chromium

Firefox was the original choice and lost on measurement. Same page, same machine, idle: Firefox 24.2% of a core, Chromium 11.4%. Two reasons, and they compound:

  • Chromium here comes from archive.raspberrypi.com (versions carry a +rpt suffix) and is patched by Raspberry Pi for this board's V3D GPU. Debian also ships a much older chromium; pinning the wrong archive would quietly undo the point of choosing it.
  • The whole userland on these images is 32-bit armhf on a 64-bit kernel (dpkg --print-architecture says armhf, uname -m says aarch64), and Firefox fares worse than Chromium on that target.

The flags in .xinitrc are not decoration: --use-gl=egl, --enable-gpu-rasterization, --ignore-gpu-blocklist and --enable-zero-copy are what keep rasterization on the GPU. Chromium's blocklist does not recognise this driver, so without --ignore-gpu-blocklist it quietly falls back to software.

pi_kiosk_browser: firefox still works and is the fallback if a Chromium update ever regresses.

Why there is a window manager

This role used to run no WM at all, on the theory that Firefox is the only X client and --kiosk makes it full-screen by itself. It doesn't. --kiosk asks to be full-screen, over EWMH, and with no window manager running there is nobody to answer: Firefox falls back to its default window size in the top-left corner. On the 1920x1080 monitor on musicdolphin that came out as a 1280x972 window with black bands down the right edge and along the bottom - looking for all the world like an overscan problem, which it is not. Openbox answers the request and otherwise stays out of the way.

Debug mode

pi_kiosk_mode: debug turns the device's own screen into something you can work on:

  • Firefox runs as an ordinary window with its chrome, so the URL bar and devtools are reachable, and it is not relaunched when you close it.
  • The pointer is visible (no -nocursor, no unclutter).
  • Openbox is the session leader. Right-click the desktop for a menu with a terminal, both ways of opening the page again, and "End this X session", which drops back to the autologin loop and starts a fresh one.
  • xterm, x11-utils, mesa-utils, xdotool and scrot get installed, so xwininfo, xprop, glxinfo, glxgears, synthetic input and screenshots are all available over ssh.
  • Chromium gets --remote-debugging-port=9222, bound to 127.0.0.1. curl localhost:9222/json lists the tabs, and the DevTools protocol will drive and measure the page properly - which beats firing XTEST key events at a window and hoping they land, as they only do about half the time. (The menu's Terminal entry runs x-terminal-emulator, which on the Pi OS image is zutty, not the xterm we install - both work; xterm is the fallback if the alternatives link ever points somewhere that doesn't.)

Switch a host over in host_vars, or for one run:

just run mediapis.yml musicdolphin -e pi_kiosk_mode=debug
just run mediapis.yml musicdolphin -e pi_kiosk_mode=kiosk

Either way the session restarts itself: the templates notify the getty handler, and restarting getty@tty1 takes X down with it because Xorg lives in that unit's cgroup. Going back to kiosk does not uninstall the debug packages; they are small and inert.

niri was considered instead of Openbox, but isn't packaged for Debian Bookworm yet (no official apt package, only third-party .debs or a from-source Rust build) - revisit once it is.