mirror of
https://github.com/BetterCorp/BetterFrame.git
synced 2026-05-26 20:16:35 +00:00
feat(deploy): Pi kiosk bring-up via cage + low-priv bfkiosk user
Replace the user-mode kiosk service with a system unit that runs cage (single-app Wayland compositor) on tty1 as a dedicated unprivileged user. No desktop, no display manager, auto-restart on crash via Restart=always. setup-pi-kiosk.sh provisions the user, installs cage + seatd, disables any display manager, points default.target at multi-user, drops the PAM stack, and enables the service. Idempotent. Screen wake "auto-login": with no DM and no lockscreen, DPMS-driven sleep just turns the panel back on — the kiosk process is already running.
This commit is contained in:
parent
122509de0d
commit
81a64766ae
3 changed files with 111 additions and 12 deletions
8
deploy/pam.d/cage
Normal file
8
deploy/pam.d/cage
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
# PAM stack for cage when invoked via systemd's PAMName=cage.
|
||||||
|
# Permissive auth (no password) because the session is launched by systemd as
|
||||||
|
# bfkiosk after auto-login at the multi-user target. pam_systemd sets up the
|
||||||
|
# XDG_RUNTIME_DIR + session, pam_loginuid wires the audit id.
|
||||||
|
auth required pam_permit.so
|
||||||
|
account required pam_permit.so
|
||||||
|
session required pam_loginuid.so
|
||||||
|
session required pam_systemd.so
|
||||||
75
deploy/scripts/setup-pi-kiosk.sh
Normal file
75
deploy/scripts/setup-pi-kiosk.sh
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Provision a Raspberry Pi (Bookworm or later) as a BetterFrame kiosk.
|
||||||
|
#
|
||||||
|
# - Creates the unprivileged `bfkiosk` user
|
||||||
|
# - Installs `cage` (single-app Wayland compositor) and `seatd`
|
||||||
|
# - Disables any installed display manager and sets multi-user.target
|
||||||
|
# - Disables getty on tty1 (cage owns the tty)
|
||||||
|
# - Installs the betterframe-kiosk system unit + PAM stack
|
||||||
|
# - Enables + starts the service
|
||||||
|
#
|
||||||
|
# Re-run safely: every step is idempotent. The kiosk binary itself must
|
||||||
|
# already be installed at /opt/betterframe/kiosk/betterframe-kiosk.
|
||||||
|
#
|
||||||
|
# Usage: sudo ./deploy/scripts/setup-pi-kiosk.sh
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "error: must run as root (sudo $0)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||||
|
|
||||||
|
echo "==> Installing cage + seatd"
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y --no-install-recommends cage seatd
|
||||||
|
|
||||||
|
echo "==> Enabling seatd"
|
||||||
|
systemctl enable --now seatd
|
||||||
|
|
||||||
|
echo "==> Ensuring bfkiosk user exists"
|
||||||
|
if ! id -u bfkiosk >/dev/null 2>&1; then
|
||||||
|
useradd -m -s /usr/sbin/nologin bfkiosk
|
||||||
|
fi
|
||||||
|
# nologin shell means no interactive login. The systemd unit launches cage
|
||||||
|
# directly so a shell is not needed. The user joins the hardware-access
|
||||||
|
# groups required by GStreamer/GTK/cage.
|
||||||
|
for grp in video render input audio seat; do
|
||||||
|
if getent group "$grp" >/dev/null; then
|
||||||
|
usermod -a -G "$grp" bfkiosk
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "==> Disabling any display manager"
|
||||||
|
for dm in lightdm gdm gdm3 sddm; do
|
||||||
|
systemctl disable --now "${dm}.service" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
systemctl set-default multi-user.target
|
||||||
|
|
||||||
|
echo "==> Disabling getty on tty1 (cage owns it)"
|
||||||
|
systemctl disable --now getty@tty1.service 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "==> Installing PAM stack and systemd unit"
|
||||||
|
install -m 644 "${REPO_ROOT}/deploy/pam.d/cage" /etc/pam.d/cage
|
||||||
|
install -m 644 "${REPO_ROOT}/deploy/systemd/betterframe-kiosk.service" \
|
||||||
|
/etc/systemd/system/betterframe-kiosk.service
|
||||||
|
|
||||||
|
if [ ! -e /etc/default/betterframe-kiosk ]; then
|
||||||
|
cat > /etc/default/betterframe-kiosk <<'EOF'
|
||||||
|
# Runtime env for betterframe-kiosk. Edit and `systemctl restart betterframe-kiosk`.
|
||||||
|
# BETTERFRAME_SERVER=http://192.168.1.10
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -x /opt/betterframe/kiosk/betterframe-kiosk ]; then
|
||||||
|
echo "warn: /opt/betterframe/kiosk/betterframe-kiosk is missing or not executable."
|
||||||
|
echo " Build the kiosk with 'cargo build --release' and copy the binary there"
|
||||||
|
echo " before starting the service."
|
||||||
|
fi
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl enable betterframe-kiosk.service
|
||||||
|
|
||||||
|
echo "==> Done. Reboot to take effect, or 'systemctl start betterframe-kiosk' now."
|
||||||
|
|
@ -1,22 +1,38 @@
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=BetterFrame Kiosk
|
Description=BetterFrame Kiosk (cage + betterframe-kiosk)
|
||||||
Documentation=https://github.com/BetterCorp/BetterFrame
|
Documentation=https://github.com/BetterCorp/BetterFrame
|
||||||
After=graphical-session.target network-online.target
|
After=systemd-user-sessions.service plymouth-quit-wait.service network-online.target seatd.service
|
||||||
Wants=network-online.target
|
Wants=network-online.target
|
||||||
PartOf=graphical-session.target
|
Conflicts=getty@tty1.service
|
||||||
|
After=getty@tty1.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
WorkingDirectory=%h/.betterframe-kiosk
|
User=bfkiosk
|
||||||
Environment=XDG_RUNTIME_DIR=/run/user/%U
|
Group=bfkiosk
|
||||||
Environment=WAYLAND_DISPLAY=wayland-0
|
SupplementaryGroups=video render input audio seat
|
||||||
Environment=NO_AT_BRIDGE=1
|
PAMName=cage
|
||||||
Environment=GST_DEBUG=1
|
TTYPath=/dev/tty1
|
||||||
ExecStart=/opt/betterframe/kiosk/betterframe-kiosk
|
TTYReset=yes
|
||||||
Restart=on-failure
|
TTYVHangup=yes
|
||||||
RestartSec=3
|
TTYVTDisallocate=yes
|
||||||
|
StandardInput=tty-fail
|
||||||
StandardOutput=journal
|
StandardOutput=journal
|
||||||
StandardError=journal
|
StandardError=journal
|
||||||
|
UtmpIdentifier=tty1
|
||||||
|
UtmpMode=user
|
||||||
|
WorkingDirectory=/home/bfkiosk
|
||||||
|
EnvironmentFile=-/etc/default/betterframe-kiosk
|
||||||
|
Environment=XDG_SESSION_TYPE=wayland
|
||||||
|
Environment=XDG_SESSION_CLASS=user
|
||||||
|
Environment=GST_DEBUG=1
|
||||||
|
Environment=BETTERFRAME_SERVER=http://localhost
|
||||||
|
ExecStart=/usr/bin/cage -s -- /opt/betterframe/kiosk/betterframe-kiosk
|
||||||
|
Restart=always
|
||||||
|
RestartSec=2
|
||||||
|
# After 10 fast restarts, back off for 30s so a broken binary doesn't burn the CPU.
|
||||||
|
StartLimitIntervalSec=60
|
||||||
|
StartLimitBurst=10
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=graphical-session.target
|
WantedBy=multi-user.target
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue