diff --git a/diskless.pkr.hcl b/diskless.pkr.hcl index c70b510..3104dc7 100644 --- a/diskless.pkr.hcl +++ b/diskless.pkr.hcl @@ -258,33 +258,36 @@ build { ] } - # --- 2b. Kiosk mode: Wayland (cage) + fullscreen Chromium --------------- + # --- 2b. Kiosk mode: Wayland (weston kiosk-shell) + fullscreen Chromium -- # Post-pivot graphical kiosk (no initramfs impact). Baked into the immutable - # root, fleet-generic. Empty kiosk_url skips it. EPEL is enabled for cage + + # root, fleet-generic. Empty kiosk_url skips it. EPEL is enabled for weston + # chromium — a supply-chain surface (accepted for the lab; see TODO #4). - # NOTE: pulls in Chromium + Mesa (~hundreds of MB) — grows the uncompressed - # erofs namespace noticeably. Graphical bring-up needs a display to verify; - # likely tweak points: cage availability in EPEL, chromium ozone/wayland, - # WLR_RENDERER, --disable-gpu, and SELinux AVCs for the GUI stack. + # weston kiosk-shell is used because cage isn't packaged for EL9; weston 8.0 + # (EPEL 9) ships kiosk-shell.so and is far lighter than GDM+gnome-kiosk. + # NOTE: pulls in Chromium + Mesa + weston (~hundreds of MB) — grows the + # uncompressed erofs namespace noticeably. Graphical bring-up needs a display + # to verify; likely tweak points: chromium ozone/wayland, --disable-gpu vs a + # real GPU, /dev/dri present in the VM, and SELinux AVCs for the GUI stack. provisioner "shell" { environment_vars = ["KIOSK_URL=${var.kiosk_url}"] inline = [ "set -e", "if [ -z \"$KIOSK_URL\" ]; then echo 'kiosk_url empty -> skipping kiosk install.'; exit 0; fi", - "echo '==> Enabling EPEL + installing kiosk stack (cage, chromium, mesa)'", + "echo '==> Enabling EPEL + installing kiosk stack (weston, chromium, mesa)'", "dnf install -y epel-release", - "dnf install -y cage chromium mesa-dri-drivers mesa-libEGL mesa-libgbm dejavu-sans-fonts", + "dnf install -y weston chromium mesa-dri-drivers mesa-libEGL mesa-libgbm dejavu-sans-fonts", # Unprivileged, passwordless kiosk user; video/input as a seat fallback. "id kiosk >/dev/null 2>&1 || useradd -m -G video,input kiosk", - # Install the staged unit + wrapper. + # Install the staged unit, weston config, and session wrapper. "install -D -m0755 /tmp/kiosk/kiosk-session /usr/local/bin/kiosk-session", "install -D -m0644 /tmp/kiosk/kiosk.service /etc/systemd/system/kiosk.service", - # URL (from the var) + software wlroots renderer for VMs without a GPU. + "install -D -m0644 /tmp/kiosk/weston.ini /etc/xdg/weston/weston.ini", + # URL from the var (weston renderer is set via --use-pixman in the unit). "install -d -m0755 /etc/kiosk", - "printf 'KIOSK_URL=%s\\nWLR_RENDERER=pixman\\n' \"$KIOSK_URL\" > /etc/kiosk/kiosk.env", + "printf 'KIOSK_URL=%s\\n' \"$KIOSK_URL\" > /etc/kiosk/kiosk.env", "chmod 0644 /etc/kiosk/kiosk.env", # Label the new files so they survive into the enforcing erofs. - "restorecon -R /usr/local/bin/kiosk-session /etc/systemd/system/kiosk.service /etc/kiosk", + "restorecon -R /usr/local/bin/kiosk-session /etc/systemd/system/kiosk.service /etc/xdg/weston /etc/kiosk", # Boot graphical and start the kiosk (replaces the tty1 getty). "systemctl enable kiosk.service", "systemctl set-default graphical.target", diff --git a/docs/TODO.md b/docs/TODO.md index 38f55de..fc13910 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -83,28 +83,33 @@ step 8 and §5). Retire/reset the errata afterward. Needs the design-doc source ## [~] 4. Kiosk mode — autologin + fullscreen Chromium loading a URL -**First cut implemented (2026-06-16) — needs a display to verify.** `cage` -(Wayland single-app compositor) + Chromium from EPEL, baked into the root: +**First cut implemented (2026-06-16) — needs a display to verify.** Wayland +kiosk + Chromium from EPEL, baked into the root. **cage is NOT packaged for EL9** +(`dnf install cage` → "Unable to find a match"), so switched to **weston +kiosk-shell** (weston 8.0.0-10.el9 is in EPEL; kiosk-shell.so landed in weston +8.0; far lighter than the GDM+gnome-kiosk alternative). - `kiosk_url` Packer var (default `https://www.reddit.com`; empty disables the whole install). Wired in CI as `KIOSK_URL` env. -- Provisioner enables EPEL, installs `cage chromium mesa-dri-drivers mesa-libEGL - mesa-libgbm dejavu-sans-fonts`, creates a passwordless unprivileged `kiosk` - user (video/input groups). -- `files/kiosk/kiosk.service` — runs `cage -s -- /usr/local/bin/kiosk-session` - as `kiosk` on tty1 via `PAMName=login`+`TTYPath` (gets seat0 for DRM/input), - `Conflicts=getty@tty1`, `WantedBy=graphical.target`; default target set to - graphical. +- Provisioner enables EPEL, installs `weston chromium mesa-dri-drivers + mesa-libEGL mesa-libgbm dejavu-sans-fonts`, creates a passwordless + unprivileged `kiosk` user (video/input groups). +- `files/kiosk/kiosk.service` — runs `weston --use-pixman + --config=/etc/xdg/weston/weston.ini` as `kiosk` on tty1 via + `PAMName=login`+`TTYPath` (gets seat0 for DRM/input), `Conflicts=getty@tty1`, + `WantedBy=graphical.target`; default target set to graphical. +- `files/kiosk/weston.ini` — `shell=kiosk-shell.so`, `idle-time=0`, + `require-input=false`, `xwayland=false`, `[autolaunch] path=/usr/local/bin/ + kiosk-session watch=true`. - `files/kiosk/kiosk-session` — Chromium with `--kiosk --ozone-platform=wayland --disable-gpu` + tmpfs profile/cache; URL from `/etc/kiosk/kiosk.env`. -- `WLR_RENDERER=pixman` in kiosk.env for VMs without a GPU. -- **Verify on a VM with a console (Proxmox VNC/SPICE):** cage comes up on tty1, - Chromium loads the URL over the booted network. Likely tweak points: - `cage` availability in EPEL 9 (else fall back to `weston --shell=kiosk-shell`), - Chromium ozone/wayland support, dropping `--disable-gpu` on real GPUs, and - **SELinux AVCs** for the GUI stack (check `ausearch -m avc`; now that the image - is enforcing with labels, the kiosk may need a small policy module or booleans - — do NOT just set permissive). Admin SSH (the key user) still works for debug - even if the kiosk fails (it lands at graphical.target either way). +- **Verify on a VM with a console (Proxmox VNC/SPICE):** weston comes up on + tty1, Chromium loads the URL over the booted network. Likely tweak points: + Chromium ozone/wayland support, dropping `--disable-gpu` on real GPUs, + `/dev/dri` present in the VM (weston needs a DRM device — set Display to + VirtIO-GPU/std), and **SELinux AVCs** for the GUI stack (check `ausearch -m + avc`; the kiosk user is unconfined so likely none — but do NOT set permissive + if they appear; add a policy module). Admin SSH (the key user) still works for + debug even if the kiosk fails (it lands at graphical.target either way). - **Image size:** Chromium+Mesa add hundreds of MB to the *uncompressed* erofs — feeds the "shrink the rootfs" concern (and #7); reconsider whether a lighter browser/render path is viable. diff --git a/files/kiosk/kiosk.service b/files/kiosk/kiosk.service index d598d28..229e8cb 100644 --- a/files/kiosk/kiosk.service +++ b/files/kiosk/kiosk.service @@ -1,6 +1,6 @@ [Unit] -Description=Wayland kiosk (cage + Chromium) -Documentation=https://github.com/cage-kiosk/cage +Description=Wayland kiosk (weston kiosk-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. After=systemd-user-sessions.service plymouth-quit-wait.service getty@tty1.service network-online.target @@ -24,8 +24,12 @@ StandardError=journal UtmpIdentifier=tty1 UtmpMode=user EnvironmentFile=/etc/kiosk/kiosk.env -# cage -s: single-client kiosk compositor; runs the wrapper, exits when it does. -ExecStart=/usr/bin/cage -s -- /usr/local/bin/kiosk-session +# 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 Restart=always RestartSec=2 diff --git a/files/kiosk/weston.ini b/files/kiosk/weston.ini new file mode 100644 index 0000000..f92890a --- /dev/null +++ b/files/kiosk/weston.ini @@ -0,0 +1,19 @@ +# weston kiosk configuration (consumed by kiosk.service: 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. + +[core] +shell=kiosk-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). +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