Files
senior-kiosk/install-kiosk.sh
T
jgitta 165e77b9b8 fix: use getty auto-login instead of systemd TTY service for first-boot setup
Replaces kiosk-firstboot.service (which got SIGHUP'd by getty) with a
simpler approach: configure getty@tty1 to auto-login root, run kiosk-setup
from .bash_profile. Cleaner TTY ownership — no service/getty conflicts.
install-kiosk.sh now removes the auto-login config and kiosk-setup script
on completion so root doesn't auto-login after the kiosk is running.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 23:36:42 +00:00

168 lines
6.4 KiB
Bash
Executable File

#!/bin/bash
set -e
# SeniorNet Kiosk setup script.
# Runs on first boot via kiosk-firstboot.service (which gives it a real TTY).
# Can also be run manually: sudo bash install-kiosk.sh
REPO_BASE="https://gitea.jgitta.com/jgitta/senior-kiosk/raw/branch/master"
clear
echo "============================================"
echo " SeniorNet Kiosk — First-Boot Setup"
echo "============================================"
echo
# ── Prompt for user details ────────────────────────────────────────
while true; do
read -rp "Enter a username for this kiosk (e.g. mary): " KIOSK_USER
KIOSK_USER=$(echo "$KIOSK_USER" | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9_-')
if [ -n "$KIOSK_USER" ]; then break; fi
echo " Invalid — use only letters, numbers, hyphens, underscores."
done
while true; do
read -rp "Enter the senior's display name (e.g. Mary Smith): " KIOSK_NAME
if [ -n "$KIOSK_NAME" ]; then break; fi
echo " Name cannot be empty."
done
echo
echo " Username : $KIOSK_USER"
echo " Name : $KIOSK_NAME"
echo
read -rp "Proceed with setup? [Y/n] " CONFIRM
if [[ "$CONFIRM" =~ ^[Nn] ]]; then echo "Aborted."; exit 1; fi
echo
# ── Paths ──────────────────────────────────────────────────────────
KIOSK_HOME="/home/$KIOSK_USER"
REPO_DIR="$KIOSK_HOME/kiosk-browser"
HOME_DIR="$KIOSK_HOME/kiosk-home"
CHROMIUM_PROFILE="$KIOSK_HOME/chromium-kiosk"
# ── User ───────────────────────────────────────────────────────────
echo "==> Creating user $KIOSK_USER..."
if ! id "$KIOSK_USER" &>/dev/null; then
useradd -m -s /bin/bash -c "$KIOSK_NAME" "$KIOSK_USER"
fi
# ── Packages ───────────────────────────────────────────────────────
echo "==> Installing packages..."
apt-get update -qq
apt-get install -y \
chromium \
openbox \
lightdm \
xserver-xorg \
xdotool \
xprop \
python3 \
python3-pyqt5 \
python3-pip \
sqlite3 \
git \
curl \
openssh-server \
2>&1 | grep -Ev "^(Reading|Selecting|Preparing|Unpacking|Setting|Processing|Triggers|Get)"
echo "==> Installing websocket-client..."
pip3 install --break-system-packages websocket-client 2>&1 | tail -2
# ── Kiosk repo ─────────────────────────────────────────────────────
echo "==> Cloning kiosk repo..."
if [ ! -d "$REPO_DIR" ]; then
git clone https://gitea.jgitta.com/jgitta/senior-kiosk.git "$REPO_DIR"
fi
# ── Home screen ────────────────────────────────────────────────────
echo "==> Deploying home screen..."
mkdir -p "$HOME_DIR"
config_json=$(cat "$REPO_DIR/config.json" | tr '\n' ' ')
sed "s|const config = {};|const config = $config_json;|" \
"$REPO_DIR/home-screen-index.html" > "$HOME_DIR/index.html"
# ── Chromium profile ───────────────────────────────────────────────
mkdir -p "$CHROMIUM_PROFILE"
# ── LightDM auto-login ─────────────────────────────────────────────
echo "==> Configuring LightDM auto-login..."
mkdir -p /etc/lightdm/lightdm.conf.d
cat > /etc/lightdm/lightdm.conf.d/50-kiosk.conf << EOF
[Seat:*]
autologin-user=$KIOSK_USER
autologin-user-timeout=0
user-session=openbox
EOF
# ── Openbox ────────────────────────────────────────────────────────
echo "==> Configuring Openbox..."
mkdir -p "$KIOSK_HOME/.config/openbox"
cat > "$KIOSK_HOME/.config/openbox/rc.xml" << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<openbox_config xmlns="http://openbox.org/3.4/rc">
<startup/>
</openbox_config>
EOF
cat > "$KIOSK_HOME/.config/openbox/autostart" << 'EOF'
(while true; do
python3 ~/kiosk-browser/browser.py
sleep 2
done) &
EOF
# ── kiosk-restart helper ───────────────────────────────────────────
cat > /usr/local/bin/kiosk-restart << 'EOF'
#!/bin/bash
pkill -f "remote-debugging-port=9222" || true
pkill -f "python3.*browser" || true
sleep 1
echo "Kiosk restarted — new code is live"
EOF
chmod +x /usr/local/bin/kiosk-restart
# ── X11 hardening ──────────────────────────────────────────────────
echo "==> Hardening X11..."
mkdir -p /etc/X11/xorg.conf.d
cat > /etc/X11/xorg.conf.d/50-kiosk.conf << 'EOF'
Section "ServerFlags"
Option "DontVTSwitch" "true"
Option "DontZap" "true"
Option "BlankTime" "0"
Option "StandbyTime" "0"
EndSection
EOF
# ── SSH: allow root login for admin ───────────────────────────────
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
# ── Permissions ────────────────────────────────────────────────────
echo "==> Setting permissions..."
chown -R "$KIOSK_USER:$KIOSK_USER" \
"$KIOSK_HOME/.config" \
"$REPO_DIR" \
"$HOME_DIR" \
"$CHROMIUM_PROFILE"
# ── Enable LightDM, remove first-boot setup ───────────────────────
systemctl enable lightdm
systemctl set-default graphical.target
# Remove auto-login and setup script so root doesn't auto-login after kiosk is running
rm -f /etc/systemd/system/getty@tty1.service.d/autologin.conf
rm -f /usr/local/bin/kiosk-setup
# Legacy cleanup (no-op if not present)
systemctl disable kiosk-firstboot 2>/dev/null || true
rm -f /etc/systemd/system/kiosk-firstboot.service
systemctl daemon-reload
echo
echo "============================================"
echo " Setup complete!"
echo " Kiosk will start after reboot as: $KIOSK_NAME ($KIOSK_USER)"
echo "============================================"
echo
read -rp "Press Enter to reboot..."
reboot