#!/usr/bin/env bash ## # installs systemd files to keep toes running on your Raspberry Pi set -euo pipefail quiet() { "$@" > /dev/null 2>&1; } SYSTEMD_DIR="/etc/systemd/system" SERVICE_NAME="toes" SERVICE_FILE="$(dirname "$0")/${SERVICE_NAME}.service" SYSTEMD_PATH="${SYSTEMD_DIR}/${SERVICE_NAME}.service" BUN_SYMLINK="/usr/local/bin/bun" BUN_REAL="$HOME/.bun/bin/bun" echo ">> Updating system libraries" quiet sudo apt-get update quiet sudo apt-get install -y libcap2-bin quiet sudo apt-get install -y avahi-utils quiet sudo apt-get install -y fish echo ">> Setting fish as default shell for toes user" if [ "$(getent passwd toes | cut -d: -f7)" != "/usr/bin/fish" ]; then quiet sudo chsh -s /usr/bin/fish toes echo "Default shell changed to fish" else echo "fish already set as default shell" fi echo ">> Ensuring bun is available in /usr/local/bin" if [ ! -x "$BUN_SYMLINK" ]; then if [ -x "$BUN_REAL" ]; then quiet sudo ln -sf "$BUN_REAL" "$BUN_SYMLINK" echo "Symlinked $BUN_REAL -> $BUN_SYMLINK" else echo ">> Installing bun at $BUN_REAL" quiet sudo apt install unzip curl -fsSL https://bun.sh/install | bash > /dev/null 2>&1 if [ ! -x "$BUN_REAL" ]; then echo "ERROR: bun installation failed - $BUN_REAL not found" exit 1 fi quiet sudo ln -sf "$BUN_REAL" "$BUN_SYMLINK" echo "Symlinked $BUN_REAL -> $BUN_SYMLINK" fi else echo "bun already available at $BUN_SYMLINK" fi echo ">> Setting CAP_NET_BIND_SERVICE on $BUN_REAL" quiet sudo setcap 'cap_net_bind_service=+ep' "$BUN_REAL" quiet /usr/sbin/getcap "$BUN_REAL" || true echo ">> Creating data and apps directories" mkdir -p ~/data mkdir -p ~/apps echo ">> Installing bundled apps" BUNDLED_APPS="clock code cron env stats versions" for app in $BUNDLED_APPS; do if [ -d "apps/$app" ]; then echo " Installing $app..." # Copy app to ~/apps cp -r "apps/$app" ~/apps/ # Find the version directory and create current symlink version_dir=$(ls -1 ~/apps/$app | grep -E '^[0-9]{8}-[0-9]{6}$' | sort -r | head -1) if [ -n "$version_dir" ]; then ln -sfn "$version_dir" ~/apps/$app/current # Install dependencies (cd ~/apps/$app/current && bun install --frozen-lockfile) > /dev/null 2>&1 fi fi done echo ">> Installing dependencies" bun install echo ">> Building client bundle" bun run build echo ">> Installing toes service" quiet sudo install -m 644 -o root -g root "$SERVICE_FILE" "$SYSTEMD_PATH" echo ">> Reloading systemd daemon" quiet sudo systemctl daemon-reload echo ">> Enabling $SERVICE_NAME to start at boot" quiet sudo systemctl enable "$SERVICE_NAME" echo ">> Starting (or restarting) $SERVICE_NAME" quiet sudo systemctl restart "$SERVICE_NAME" echo ">> Enabling kiosk mode" sudo raspi-config nonint do_boot_behaviour B4 # labwc (older RPi OS / manual installs) mkdir -p ~/.config/labwc cat > ~/.config/labwc/autostart <<'EOF' chromium --noerrdialogs --disable-infobars --kiosk http://localhost EOF # Wayfire (RPi OS Bookworm default) WAYFIRE_CONFIG="$HOME/.config/wayfire.ini" if [ -f "$WAYFIRE_CONFIG" ]; then # Remove existing chromium autostart if present sed -i '/^chromium = /d' "$WAYFIRE_CONFIG" # Add to existing [autostart] section or create it if grep -q '^\[autostart\]' "$WAYFIRE_CONFIG"; then sed -i '/^\[autostart\]/a chromium = chromium --noerrdialogs --disable-infobars --kiosk http://localhost' "$WAYFIRE_CONFIG" else cat >> "$WAYFIRE_CONFIG" <<'EOF' [autostart] chromium = chromium --noerrdialogs --disable-infobars --kiosk http://localhost EOF fi fi echo ">> Done! Rebooting in 5 seconds..." quiet systemctl status "$SERVICE_NAME" --no-pager -l || true sleep 5 quiet sudo nohup reboot >/dev/null 2>&1 & exit 0