tools: preview the plymouth splash unprivileged; #137 attempt 1 reverted
All checks were successful
Check / eval (push) Successful in 3m49s

Answering "how do I give you root": you don't. tools/plymouth-preview.sh
renders the splash — LUKS dialog included — into X11 windows in ~10s with
no reboot, no root and no DRM:

- unshare -rm = user + mount namespace; every mount dies with it.
- /run/plymouth is BOTH the socket dir and the compiled-in plugin path
  (`strings plymouthd` → /run/plymouth/plugins/), so we bind a writable dir
  over it AND recreate its symlinks — miss those and plymouth can't find
  x11.so, silently skips X11 and reaches for a tty.
- never pass --tty (main.c:2133 takes the X11 path only while default_tty
  is unset); /dev/dri is masked so a preview physically cannot mode-set a
  real output — which matters on a docked session (#127).
- PLY_CREATE_FAKE_MULTI_HEAD_SETUP fakes 800x600 + 640x480 heads.
- debug wants plymouth.debug=stream: — `file:` buffers and yields nothing.

What it proved immediately: with a STABLE two-head canvas the current theme
centres correctly on both heads. So the geometry is fine and #137 really is
the timing bug (positions frozen at parse time vs a canvas that resizes
when a head arrives) — recorded in the item.

And it caught my own fix: hoisting positions into layout() rendered the
background on both heads and nothing else — no logo, no bar — with NO parse
error logged. Reverted rather than shipped, because that script draws the
passphrase box on an encrypted machine. #137 carries the failure, the prime
suspect (plymouth script scope: assignment lands in `local` unless the name
already exists) and the fast edit/render loop for the next attempt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 12:42:31 +01:00
parent 3e6cc6fe84
commit 0cd6212b9c
3 changed files with 118 additions and 13 deletions

64
tools/plymouth-preview.sh Executable file
View File

@@ -0,0 +1,64 @@
#!/usr/bin/env bash
# Render the Plymouth splash in X11 windows — no root, no reboot, no DRM (#137).
#
# tools/plymouth-preview.sh [<theme-store-path>]
#
# Plymouth is otherwise untestable without rebooting, which is a poor loop for
# a script that draws the LUKS passphrase box on an encrypted machine. This
# gives you a real render in seconds:
#
# * `unshare -rm` = user + mount namespace. We are root only in here, and
# every mount below dies with the process.
# * /run/plymouth is both the daemon's socket dir AND its compiled-in plugin
# path (`strings plymouthd` → /run/plymouth/plugins/). So we bind a
# writable dir over it and recreate its symlinks — miss those and plymouth
# cannot find x11.so, silently skips X11, and goes looking for a tty.
# * X11 is first in plymouth's renderer order (ply-renderer.c:283) and is
# taken only while default_tty is unset — so never pass --tty. /dev/dri is
# masked as well: a preview must not be able to mode-set the real outputs.
# * PLY_CREATE_FAKE_MULTI_HEAD_SETUP (renderers/x11/plugin.c) fakes two heads
# (800x600 + 640x480) — the multi-monitor case, on a single-monitor desk.
#
# Caveat: the fake heads are created up front, so this proves rendering and
# centring, NOT #137's canvas-change bug (a head arriving mid-splash).
set -u
THEME="${1:-}"
PLY=$(nix build --no-link --print-out-paths nixpkgs#plymouth 2>/dev/null | head -1)
[ -n "$PLY" ] || { echo "could not build plymouth" >&2; exit 1; }
[ -n "${DISPLAY:-}" ] || { echo "no DISPLAY — the x11 renderer needs Xwayland" >&2; exit 1; }
export PLY THEME
unshare -rm -- bash -euc '
rm -rf /tmp/plyrig; mkdir -p /tmp/plyrig/run /tmp/plyrig/dri /tmp/plyrig/themes
if [ -n "$THEME" ]; then
cp -rL "$THEME/share/plymouth/themes/nomarchy" /tmp/plyrig/themes/
# The .plymouth bakes absolute store paths at build time; point them at the
# copy so the script here is the one that renders (edit + rerun = seconds).
sed -i "s|^ScriptFile=.*|ScriptFile=/tmp/plyrig/themes/nomarchy/nomarchy.script|;
s|^ImageDir=.*|ImageDir=/tmp/plyrig/themes/nomarchy|" \
/tmp/plyrig/themes/nomarchy/nomarchy.plymouth
ln -s /tmp/plyrig/themes /tmp/plyrig/run/themes
else
ln -s /etc/plymouth/themes /tmp/plyrig/run/themes
fi
ln -s /etc/plymouth/plugins /tmp/plyrig/run/plugins
ln -s /etc/plymouth/plymouthd.defaults /tmp/plyrig/run/plymouthd.defaults
mount --bind /tmp/plyrig/run /run/plymouth
mount --bind /tmp/plyrig/dri /dev/dri 2>/dev/null || true
export PLY_CREATE_FAKE_MULTI_HEAD_SETUP=1
"$PLY/sbin/plymouthd" --no-daemon --mode=boot --no-boot-log \
--kernel-command-line="plymouth.debug=stream:/tmp/plyrig/dbg.log splash" \
>/dev/null 2>&1 &
d=$!
sleep 2
"$PLY/bin/plymouth" show-splash >/dev/null 2>&1
echo "splash up — two windows (800x600, 640x480). Ctrl+C or wait 20s."
sleep 8
"$PLY/bin/plymouth" ask-for-password --prompt="Unlock" --number-of-tries=1 >/dev/null 2>&1 &
echo "password dialog requested (the LUKS path)"
sleep 10
"$PLY/bin/plymouth" quit >/dev/null 2>&1; sleep 1; kill $d 2>/dev/null
cp /tmp/plyrig/dbg.log /tmp/plymouth-preview.log 2>/dev/null
echo "log: /tmp/plymouth-preview.log"
'