fix(kiosk): Fix race conditions and startup failures

Major kiosk mode rewrite to fix boot failures on both VMs and hardware:

New secubox-kiosk-launcher script that handles:
- Dynamic UID detection (no more hardcoded UID 1000)
- Proper dependency waiting (nginx, network, dummy0)
- User creation if missing
- Fallback URL handling (primary -> localhost)
- VT setup without race conditions

Fixed systemd services:
- Added proper After= dependencies (nginx, networkd, firstboot)
- Removed problematic chvt command (let X11 handle VT)
- Increased TimeoutStartSec to 180s for slow hardware
- Added StartLimitInterval/Burst for restart protection

Simplified xinitrc/start-kiosk.sh:
- Removed redundant wait loops (launcher handles this)
- Added error suppression for headless environments
- Added logging via logger

Build script updates:
- Copy kiosk-launcher and wayland service to images
- Removed inline service definition (use systemd/ files)

Fixes: Kiosk blank screen, race conditions, UID mismatch,
       missing dependencies, VT switching failures

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-04-01 10:11:34 +02:00
parent 5425dbc9a8
commit 93475f93a7
5 changed files with 431 additions and 254 deletions

View File

@ -797,8 +797,8 @@ log "5/8 Installing SecuBox scripts..."
mkdir -p "${ROOTFS}/usr/sbin"
mkdir -p "${ROOTFS}/usr/lib/secubox"
# Copy scripts
for script in secubox-net-detect secubox-kiosk-setup secubox-cmdline-handler; do
# Copy scripts (including kiosk-launcher for robust startup)
for script in secubox-net-detect secubox-kiosk-setup secubox-cmdline-handler secubox-kiosk-launcher; do
if [[ -f "${SCRIPT_DIR}/sbin/${script}" ]]; then
cp "${SCRIPT_DIR}/sbin/${script}" "${ROOTFS}/usr/sbin/"
chmod +x "${ROOTFS}/usr/sbin/${script}"
@ -811,9 +811,9 @@ if [[ -f "${SCRIPT_DIR}/firstboot.sh" ]]; then
chmod +x "${ROOTFS}/usr/lib/secubox/firstboot.sh"
fi
# Systemd services
# Systemd services (including wayland variant for kiosk)
mkdir -p "${ROOTFS}/etc/systemd/system"
for svc in secubox-net-detect secubox-cmdline secubox-kiosk; do
for svc in secubox-net-detect secubox-cmdline secubox-kiosk secubox-kiosk-wayland; do
if [[ -f "${SCRIPT_DIR}/systemd/${svc}.service" ]]; then
cp "${SCRIPT_DIR}/systemd/${svc}.service" "${ROOTFS}/etc/systemd/system/"
fi
@ -877,28 +877,26 @@ XWRAP
cat > "${ROOTFS}/home/secubox-kiosk/.xinitrc" <<'XINITRC'
#!/bin/bash
# SecuBox Kiosk X11 Launcher
# Note: secubox-kiosk-launcher already waits for services before starting
# Wait for services to be ready
for i in {1..30}; do
if curl -sk https://192.168.255.1:9443/ >/dev/null 2>&1; then
break
fi
sleep 1
done
# Kiosk URL (local SecuBox WebUI via dummy interface)
# URL from environment (set by launcher) or fallback
URL="${KIOSK_URL:-https://192.168.255.1:9443/}"
# Disable screen blanking
xset s off
xset -dpms
xset s noblank
# Log startup
logger -t secubox-kiosk "Starting Chromium X11 kiosk: $URL"
# Disable screen blanking (ignore errors on headless)
xset s off 2>/dev/null || true
xset -dpms 2>/dev/null || true
xset s noblank 2>/dev/null || true
# Hide cursor after 3 seconds of inactivity
unclutter -idle 3 -root &
if command -v unclutter &>/dev/null; then
unclutter -idle 3 -root &
fi
# Set background to black
xsetroot -solid black
xsetroot -solid black 2>/dev/null || true
# Chromium flags for kiosk mode (X11)
CHROMIUM_FLAGS=(
@ -939,55 +937,13 @@ XINITRC
touch "${ROOTFS}/var/lib/secubox/.kiosk-enabled"
echo "x11" > "${ROOTFS}/var/lib/secubox/.kiosk-mode"
# Copy X11 kiosk service (not Wayland/Cage)
cat > "${ROOTFS}/etc/systemd/system/secubox-kiosk.service" <<'KIOSK_SVC'
[Unit]
Description=SecuBox Kiosk Mode (X11/Chromium)
After=systemd-user-sessions.service plymouth-quit-wait.service
Wants=network-online.target
Conflicts=getty@tty1.service
[Service]
Type=simple
# Check if kiosk is enabled
ExecStartPre=+/bin/sh -c '[ -f /var/lib/secubox/.kiosk-enabled ] || exit 1'
# Run on tty7
TTYPath=/dev/tty7
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
# Create runtime directory AS ROOT
ExecStartPre=+/bin/mkdir -p /run/user/1000
ExecStartPre=+/bin/chown 1000:1000 /run/user/1000
ExecStartPre=+/bin/chmod 700 /run/user/1000
# Switch VT to tty7
ExecStartPre=+/bin/chvt 7
User=secubox-kiosk
Group=secubox-kiosk
SupplementaryGroups=video audio input render tty
Environment=XDG_RUNTIME_DIR=/run/user/1000
Environment=XDG_SESSION_TYPE=x11
Environment=DISPLAY=:0
Environment=HOME=/home/secubox-kiosk
Environment=KIOSK_URL=https://192.168.255.1:9443/
ExecStart=/usr/bin/startx /home/secubox-kiosk/.xinitrc -- :0 vt7 -nolisten tcp
Restart=on-failure
RestartSec=5
TimeoutStartSec=90
MemoryMax=1G
TasksMax=200
[Install]
WantedBy=graphical.target
KIOSK_SVC
# Use the fixed kiosk service (already copied from systemd/ directory)
# The service uses secubox-kiosk-launcher which handles:
# - Dynamic UID detection (no hardcoded 1000)
# - Proper dependency waiting (nginx, network)
# - User creation if needed
# - Fallback URL handling
log "Kiosk service already copied from systemd/ directory"
# Enable kiosk service and set graphical target
chroot "${ROOTFS}" systemctl enable secubox-kiosk.service 2>/dev/null || true

287
image/sbin/secubox-kiosk-launcher Executable file
View File

@ -0,0 +1,287 @@
#!/bin/bash
# ══════════════════════════════════════════════════════════════════
# secubox-kiosk-launcher — Robust Kiosk Startup Wrapper
# Handles all dependencies before starting X11/Chromium
# Fixes race conditions and provides proper error handling
# ══════════════════════════════════════════════════════════════════
set -u
# Configuration
KIOSK_USER="${KIOSK_USER:-secubox-kiosk}"
KIOSK_HOME="${KIOSK_HOME:-/home/secubox-kiosk}"
KIOSK_URL="${KIOSK_URL:-https://192.168.255.1:9443/}"
FALLBACK_URL="${FALLBACK_URL:-https://127.0.0.1/}"
MAX_WAIT="${MAX_WAIT:-60}"
LOG_TAG="secubox-kiosk"
# Logging
log() {
echo "[kiosk-launcher] $*"
logger -t "$LOG_TAG" "$*" 2>/dev/null || true
}
err() {
echo "[kiosk-launcher] ERROR: $*" >&2
logger -t "$LOG_TAG" -p err "$*" 2>/dev/null || true
}
# ── Step 1: Verify kiosk user exists ─────────────────────────────
verify_user() {
log "Checking kiosk user..."
if ! id "$KIOSK_USER" &>/dev/null; then
log "Creating kiosk user $KIOSK_USER..."
useradd -r -m -d "$KIOSK_HOME" -s /usr/sbin/nologin \
-G video,audio,input,render,tty "$KIOSK_USER" 2>/dev/null || {
err "Failed to create kiosk user"
return 1
}
fi
# Get actual UID
KIOSK_UID=$(id -u "$KIOSK_USER")
KIOSK_GID=$(id -g "$KIOSK_USER")
export KIOSK_UID KIOSK_GID
log "Kiosk user: $KIOSK_USER (UID=$KIOSK_UID)"
return 0
}
# ── Step 2: Setup XDG runtime directory ──────────────────────────
setup_runtime_dir() {
local runtime_dir="/run/user/${KIOSK_UID}"
log "Setting up XDG_RUNTIME_DIR: $runtime_dir"
mkdir -p "$runtime_dir"
chown "${KIOSK_UID}:${KIOSK_GID}" "$runtime_dir"
chmod 700 "$runtime_dir"
export XDG_RUNTIME_DIR="$runtime_dir"
return 0
}
# ── Step 3: Wait for network interface ───────────────────────────
wait_for_network() {
log "Waiting for dummy0 interface..."
local count=0
while [[ $count -lt 30 ]]; do
# Check if dummy0 has the expected IP
if ip addr show dummy0 2>/dev/null | grep -q "192.168.255.1"; then
log "dummy0 interface ready"
return 0
fi
# Also check if any interface has connectivity
if ip route get 8.8.8.8 &>/dev/null; then
log "Network connectivity available"
break
fi
sleep 1
((count++))
done
# Don't fail - we might still work with localhost
log "Network check complete (dummy0 may not be ready)"
return 0
}
# ── Step 4: Wait for nginx/webui ─────────────────────────────────
wait_for_webui() {
log "Waiting for SecuBox WebUI..."
local count=0
local url_to_use="$KIOSK_URL"
while [[ $count -lt $MAX_WAIT ]]; do
# Try primary URL
if curl -sk --connect-timeout 2 "$KIOSK_URL" >/dev/null 2>&1; then
log "WebUI ready at $KIOSK_URL"
export KIOSK_URL
return 0
fi
# Try fallback URL
if curl -sk --connect-timeout 2 "$FALLBACK_URL" >/dev/null 2>&1; then
log "WebUI ready at fallback $FALLBACK_URL"
export KIOSK_URL="$FALLBACK_URL"
return 0
fi
# Check if nginx is at least running
if systemctl is-active nginx &>/dev/null; then
if [[ $count -gt 10 ]]; then
log "nginx running but URL not responding, trying localhost..."
if curl -sk --connect-timeout 2 "https://localhost/" >/dev/null 2>&1; then
export KIOSK_URL="https://localhost/"
log "Using localhost as fallback"
return 0
fi
fi
fi
sleep 1
((count++))
done
# Last resort: use the URL anyway, chromium will show error
err "WebUI not responding after ${MAX_WAIT}s, proceeding anyway"
export KIOSK_URL
return 0
}
# ── Step 5: Setup VT (virtual terminal) ──────────────────────────
setup_vt() {
local target_vt="${1:-7}"
log "Setting up VT${target_vt}..."
# Ensure tty device exists
if [[ ! -c "/dev/tty${target_vt}" ]]; then
log "Creating /dev/tty${target_vt}..."
mknod "/dev/tty${target_vt}" c 4 "$target_vt" 2>/dev/null || true
fi
# Don't switch VT here - let X11 handle it with vt7 parameter
# chvt before X starts can cause issues
return 0
}
# ── Step 6: Create/verify xinitrc ────────────────────────────────
setup_xinitrc() {
local xinitrc="${KIOSK_HOME}/.xinitrc"
if [[ ! -f "$xinitrc" ]]; then
log "Creating .xinitrc..."
mkdir -p "${KIOSK_HOME}/.config"
cat > "$xinitrc" <<'XINITRC'
#!/bin/bash
# SecuBox Kiosk X11 Launcher (generated by kiosk-launcher)
# URL from environment (set by launcher)
URL="${KIOSK_URL:-https://192.168.255.1:9443/}"
# Disable screen blanking
xset s off 2>/dev/null || true
xset -dpms 2>/dev/null || true
xset s noblank 2>/dev/null || true
# Hide cursor after 3 seconds of inactivity
if command -v unclutter &>/dev/null; then
unclutter -idle 3 -root &
fi
# Set background to black
xsetroot -solid black 2>/dev/null || true
# Chromium flags for kiosk mode
CHROMIUM_FLAGS=(
--kiosk
--no-first-run
--no-sandbox
--disable-gpu-sandbox
--disable-translate
--disable-infobars
--disable-session-crashed-bubble
--disable-restore-background-contents
--disable-sync
--disable-features=TranslateUI
--ignore-certificate-errors
--noerrdialogs
--enable-features=OverlayScrollbar
--start-fullscreen
--window-position=0,0
--check-for-update-interval=604800
--disable-component-update
--disable-default-apps
--disable-extensions
--disable-background-networking
--disable-domain-reliability
--disable-client-side-phishing-detection
"$URL"
)
# Run Chromium
exec chromium "${CHROMIUM_FLAGS[@]}"
XINITRC
chmod +x "$xinitrc"
chown "${KIOSK_UID}:${KIOSK_GID}" "$xinitrc"
fi
return 0
}
# ── Step 7: Launch X11 ───────────────────────────────────────────
launch_x11() {
local vt="${1:-7}"
local display="${2:-:0}"
log "Launching X11 on VT${vt} display ${display}..."
log "KIOSK_URL=$KIOSK_URL"
# Export environment for xinitrc
export HOME="$KIOSK_HOME"
export DISPLAY="$display"
export XDG_SESSION_TYPE=x11
export KIOSK_URL
# Switch to kiosk user and run startx
exec su -s /bin/bash "$KIOSK_USER" -c \
"export HOME='$KIOSK_HOME' DISPLAY='$display' XDG_RUNTIME_DIR='$XDG_RUNTIME_DIR' XDG_SESSION_TYPE=x11 KIOSK_URL='$KIOSK_URL'; exec /usr/bin/startx '$KIOSK_HOME/.xinitrc' -- $display vt${vt} -nolisten tcp -keeptty"
}
# ── Main ─────────────────────────────────────────────────────────
main() {
local mode="${1:-x11}"
local vt="${2:-7}"
log "════════════════════════════════════════════════════"
log "SecuBox Kiosk Launcher starting (mode=$mode, vt=$vt)"
log "════════════════════════════════════════════════════"
# Check if enabled
if [[ ! -f /var/lib/secubox/.kiosk-enabled ]]; then
err "Kiosk not enabled (missing /var/lib/secubox/.kiosk-enabled)"
exit 1
fi
# Run setup steps
verify_user || exit 1
setup_runtime_dir || exit 1
wait_for_network
wait_for_webui
setup_vt "$vt"
setup_xinitrc
# Launch based on mode
case "$mode" in
x11)
launch_x11 "$vt" ":0"
;;
wayland)
log "Launching Cage/Wayland..."
export HOME="$KIOSK_HOME"
export XDG_SESSION_TYPE=wayland
export KIOSK_URL
export WLR_LIBINPUT_NO_DEVICES=1
export WLR_NO_HARDWARE_CURSORS=1
export WLR_RENDERER_ALLOW_SOFTWARE=1
export WLR_RENDERER=pixman
exec su -s /bin/bash "$KIOSK_USER" -c \
"export HOME='$KIOSK_HOME' XDG_RUNTIME_DIR='$XDG_RUNTIME_DIR' XDG_SESSION_TYPE=wayland KIOSK_URL='$KIOSK_URL' WLR_LIBINPUT_NO_DEVICES=1 WLR_NO_HARDWARE_CURSORS=1 WLR_RENDERER_ALLOW_SOFTWARE=1 WLR_RENDERER=pixman; exec /usr/bin/cage -s -- '$KIOSK_HOME/start-kiosk.sh'"
;;
*)
err "Unknown mode: $mode"
exit 1
;;
esac
}
main "$@"

View File

@ -159,18 +159,14 @@ create_wayland_script() {
cat > "${KIOSK_HOME}/start-kiosk.sh" <<'KIOSK'
#!/bin/bash
# SecuBox Kiosk Launcher (Wayland)
# Note: secubox-kiosk-launcher already waits for services before starting
# Wait for services to be ready
for i in {1..30}; do
if curl -sk https://192.168.255.1:9443/ >/dev/null 2>&1; then
break
fi
sleep 1
done
# Kiosk URL (local SecuBox WebUI via dummy interface)
# URL from environment (set by launcher) or fallback
URL="${KIOSK_URL:-https://192.168.255.1:9443/}"
# Log startup
logger -t secubox-kiosk "Starting Chromium Wayland kiosk: $URL"
# Chromium flags for kiosk mode (native Wayland via Ozone)
CHROMIUM_FLAGS=(
--ozone-platform=wayland
@ -209,28 +205,26 @@ create_x11_xinitrc() {
cat > "${KIOSK_HOME}/.xinitrc" <<'XINITRC'
#!/bin/bash
# SecuBox Kiosk X11 Launcher
# Note: secubox-kiosk-launcher already waits for services before starting
# Wait for services to be ready
for i in {1..30}; do
if curl -sk https://192.168.255.1:9443/ >/dev/null 2>&1; then
break
fi
sleep 1
done
# Kiosk URL (local SecuBox WebUI via dummy interface)
# URL from environment (set by launcher) or fallback
URL="${KIOSK_URL:-https://192.168.255.1:9443/}"
# Disable screen blanking
xset s off
xset -dpms
xset s noblank
# Log startup
logger -t secubox-kiosk "Starting Chromium X11 kiosk: $URL"
# Disable screen blanking (ignore errors on headless)
xset s off 2>/dev/null || true
xset -dpms 2>/dev/null || true
xset s noblank 2>/dev/null || true
# Hide cursor after 3 seconds of inactivity
unclutter -idle 3 -root &
if command -v unclutter &>/dev/null; then
unclutter -idle 3 -root &
fi
# Set background to black
xsetroot -solid black
xsetroot -solid black 2>/dev/null || true
# Chromium flags for kiosk mode (X11)
CHROMIUM_FLAGS=(
@ -283,118 +277,65 @@ EOF
log "Root autologin enabled on tty2 (Ctrl+Alt+F2 to access)"
}
# ── Update Service File with Correct UID ─────────────────────────
# ── Update Service File (using launcher script) ─────────────────────────
update_service_file() {
local KIOSK_UID="${1:-1000}"
local mode="${2:-x11}"
if [[ "$mode" == "wayland" ]]; then
# Wayland service (Cage)
cat > /etc/systemd/system/secubox-kiosk.service <<EOF
# Use the robust launcher script that handles:
# - Dynamic UID detection (no hardcoded values)
# - Proper dependency waiting (nginx, network, dummy0)
# - User creation if needed
# - Fallback URL handling
# - VT setup without race conditions
cat > /etc/systemd/system/secubox-kiosk.service <<EOF
[Unit]
Description=SecuBox Kiosk Mode (Wayland/Cage)
After=systemd-user-sessions.service plymouth-quit-wait.service
Description=SecuBox Kiosk Mode (${mode})
Documentation=https://secubox.in/docs/kiosk
# Proper dependency chain
After=systemd-user-sessions.service
After=plymouth-quit-wait.service
After=network-online.target
After=nginx.service
After=systemd-networkd.service
After=secubox-firstboot.service
Wants=network-online.target
Wants=nginx.service
Conflicts=getty@tty1.service
PartOf=graphical.target
[Service]
Type=simple
# Check if kiosk is enabled
ExecStartPre=+/bin/sh -c '[ -f ${ENABLED_MARKER} ] || exit 1'
ExecStartPre=+/bin/sh -c '[ -f /var/lib/secubox/.kiosk-enabled ] || exit 1'
# Run on tty7
TTYPath=/dev/tty7
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
# Create runtime directory AS ROOT
ExecStartPre=+/bin/mkdir -p /run/user/${KIOSK_UID}
ExecStartPre=+/bin/chown ${KIOSK_UID}:${KIOSK_UID} /run/user/${KIOSK_UID}
ExecStartPre=+/bin/chmod 700 /run/user/${KIOSK_UID}
# Switch VT to tty7
ExecStartPre=+/bin/chvt 7
User=${KIOSK_USER}
Group=${KIOSK_USER}
SupplementaryGroups=video audio input render tty
Environment=XDG_RUNTIME_DIR=/run/user/${KIOSK_UID}
Environment=XDG_SESSION_TYPE=wayland
Environment=KIOSK_URL=${KIOSK_URL}
Environment=WLR_LIBINPUT_NO_DEVICES=1
Environment=WLR_NO_HARDWARE_CURSORS=1
Environment=WLR_RENDERER_ALLOW_SOFTWARE=1
Environment=WLR_RENDERER=pixman
Environment=WLR_DRM_NO_ATOMIC=1
ExecStart=/usr/bin/cage -s -- ${KIOSK_HOME}/start-kiosk.sh
# Use launcher script (handles all setup internally)
ExecStart=/usr/sbin/secubox-kiosk-launcher ${mode} 7
Restart=on-failure
RestartSec=5
TimeoutStartSec=90
RestartSec=10
StartLimitInterval=300
StartLimitBurst=5
TimeoutStartSec=180
TimeoutStopSec=30
MemoryMax=1G
TasksMax=200
StandardOutput=journal
StandardError=journal
SyslogIdentifier=secubox-kiosk
[Install]
WantedBy=graphical.target
EOF
else
# X11 service (startx)
cat > /etc/systemd/system/secubox-kiosk.service <<EOF
[Unit]
Description=SecuBox Kiosk Mode (X11/Chromium)
After=systemd-user-sessions.service plymouth-quit-wait.service
Wants=network-online.target
Conflicts=getty@tty1.service
[Service]
Type=simple
# Check if kiosk is enabled
ExecStartPre=+/bin/sh -c '[ -f ${ENABLED_MARKER} ] || exit 1'
# Run on tty7
TTYPath=/dev/tty7
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
# Create runtime directory AS ROOT
ExecStartPre=+/bin/mkdir -p /run/user/${KIOSK_UID}
ExecStartPre=+/bin/chown ${KIOSK_UID}:${KIOSK_UID} /run/user/${KIOSK_UID}
ExecStartPre=+/bin/chmod 700 /run/user/${KIOSK_UID}
# Switch VT to tty7
ExecStartPre=+/bin/chvt 7
User=${KIOSK_USER}
Group=${KIOSK_USER}
SupplementaryGroups=video audio input render tty
Environment=XDG_RUNTIME_DIR=/run/user/${KIOSK_UID}
Environment=XDG_SESSION_TYPE=x11
Environment=DISPLAY=:0
Environment=HOME=${KIOSK_HOME}
Environment=KIOSK_URL=${KIOSK_URL}
ExecStart=/usr/bin/startx ${KIOSK_HOME}/.xinitrc -- :0 vt7 -nolisten tcp
Restart=on-failure
RestartSec=5
TimeoutStartSec=90
MemoryMax=1G
TasksMax=200
[Install]
WantedBy=graphical.target
EOF
fi
systemctl daemon-reload
log "Updated service file with UID ${KIOSK_UID} (mode: ${mode})"
log "Service file updated (mode: ${mode}, using launcher)"
}
# ── Enable Kiosk Mode ─────────────────────────────────────────────

View File

@ -1,58 +1,52 @@
[Unit]
Description=SecuBox Kiosk Mode (Wayland/Cage)
After=systemd-user-sessions.service plymouth-quit-wait.service
Documentation=https://secubox.in/docs/kiosk
# Proper dependency chain - wait for everything to be ready
After=systemd-user-sessions.service
After=plymouth-quit-wait.service
After=network-online.target
After=nginx.service
After=systemd-networkd.service
After=secubox-firstboot.service
# Soft dependencies (don't fail if missing)
Wants=network-online.target
Wants=nginx.service
# Conflicts with console on tty1
Conflicts=getty@tty1.service
# Only start if graphical target is active
PartOf=graphical.target
[Service]
Type=simple
# Check if kiosk is enabled (+ prefix runs as root before User= switch)
# Check if kiosk is enabled (run as root with + prefix)
ExecStartPre=+/bin/sh -c '[ -f /var/lib/secubox/.kiosk-enabled ] || exit 1'
# Run on tty7 (like normal display managers)
TTYPath=/dev/tty7
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
# Create runtime directory AS ROOT (before switching to User)
ExecStartPre=+/bin/mkdir -p /run/user/1000
ExecStartPre=+/bin/chown 1000:1000 /run/user/1000
ExecStartPre=+/bin/chmod 700 /run/user/1000
# Switch VT to tty7 before starting
ExecStartPre=+/bin/chvt 7
# Now switch to kiosk user
User=secubox-kiosk
Group=secubox-kiosk
# Wayland/DRM access
SupplementaryGroups=video audio input render tty
# Environment for Wayland (cage creates its own display)
Environment=XDG_RUNTIME_DIR=/run/user/1000
Environment=XDG_SESSION_TYPE=wayland
Environment=KIOSK_URL=https://192.168.255.1:9443/
# wlroots environment (VM compatibility - may still fail)
Environment=WLR_LIBINPUT_NO_DEVICES=1
Environment=WLR_NO_HARDWARE_CURSORS=1
Environment=WLR_RENDERER_ALLOW_SOFTWARE=1
Environment=WLR_RENDERER=pixman
Environment=WLR_DRM_NO_ATOMIC=1
# Cage compositor running kiosk script
ExecStart=/usr/bin/cage -s -- /home/secubox-kiosk/start-kiosk.sh
# Use the robust launcher script (runs as root, handles user switching internally)
ExecStart=/usr/sbin/secubox-kiosk-launcher wayland 7
# Restart policy
Restart=on-failure
RestartSec=5
TimeoutStartSec=90
RestartSec=10
StartLimitInterval=300
StartLimitBurst=5
# Generous timeout for slow hardware/VMs
TimeoutStartSec=180
TimeoutStopSec=30
# Resource limits
MemoryMax=1G
TasksMax=200
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=secubox-kiosk
[Install]
WantedBy=graphical.target

View File

@ -1,53 +1,52 @@
[Unit]
Description=SecuBox Kiosk Mode (X11/Chromium)
After=systemd-user-sessions.service plymouth-quit-wait.service
Documentation=https://secubox.in/docs/kiosk
# Proper dependency chain - wait for everything to be ready
After=systemd-user-sessions.service
After=plymouth-quit-wait.service
After=network-online.target
After=nginx.service
After=systemd-networkd.service
After=secubox-firstboot.service
# Soft dependencies (don't fail if missing)
Wants=network-online.target
Wants=nginx.service
# Conflicts with console on tty1
Conflicts=getty@tty1.service
# Only start if graphical target is active
PartOf=graphical.target
[Service]
Type=simple
# Check if kiosk is enabled (+ prefix runs as root before User= switch)
# Check if kiosk is enabled (run as root with + prefix)
ExecStartPre=+/bin/sh -c '[ -f /var/lib/secubox/.kiosk-enabled ] || exit 1'
# Run on tty7 (like normal display managers)
TTYPath=/dev/tty7
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
# Create runtime directory AS ROOT (before switching to User)
ExecStartPre=+/bin/mkdir -p /run/user/1000
ExecStartPre=+/bin/chown 1000:1000 /run/user/1000
ExecStartPre=+/bin/chmod 700 /run/user/1000
# Switch VT to tty7 before starting
ExecStartPre=+/bin/chvt 7
# Now switch to kiosk user
User=secubox-kiosk
Group=secubox-kiosk
# X11/DRM access
SupplementaryGroups=video audio input render tty
# Environment for X11
Environment=XDG_RUNTIME_DIR=/run/user/1000
Environment=XDG_SESSION_TYPE=x11
Environment=DISPLAY=:0
Environment=HOME=/home/secubox-kiosk
Environment=KIOSK_URL=https://192.168.255.1:9443/
# Start X11 with xinit
ExecStart=/usr/bin/startx /home/secubox-kiosk/.xinitrc -- :0 vt7 -nolisten tcp
# Use the robust launcher script (runs as root, handles user switching internally)
ExecStart=/usr/sbin/secubox-kiosk-launcher x11 7
# Restart policy
Restart=on-failure
RestartSec=5
TimeoutStartSec=90
RestartSec=10
StartLimitInterval=300
StartLimitBurst=5
# Generous timeout for slow hardware/VMs
TimeoutStartSec=180
TimeoutStopSec=30
# Resource limits
MemoryMax=1G
TasksMax=200
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=secubox-kiosk
[Install]
WantedBy=graphical.target