# Raspberry Pi Provisioning — Zero-Touch Player Setup ## Goal Customer unboxes Pi → plugs in power → content plays. That's it. No keyboard, no monitor, no SSH. ## Provisioning Flow ### Step 1: Image the SD Card (We Do This) Using Raspberry Pi Imager (CLI version for batch flashing): ```bash # One-time image prep cat << 'EOF' > /tmp/signage-firstboot.sh #!/bin/bash # Runs on first boot only — sets up the player # 1. Set hostname hostnamectl set-hostname signage-player # 2. Enable auto-login to console (required for kiosk mode) raspi-config nonint do_boot_behaviour B2 # 3. Install dependencies apt-get update && apt-get install -y chromium-browser unclutter x11-xserver-utils # 4. Create player service cat > /etc/systemd/system/signage-player.service << 'SRVEOF' [Unit] Description=Digital Signage Player After=network-online.target Wants=network-online.target [Service] User=pi Environment=DISPLAY=:0 ExecStartPre=/usr/bin/sleep 5 ExecStart=/usr/bin/bash /home/pi/player.sh Restart=always RestartSec=10 [Install] WantedBy=multi-user.target SRVEOF # 5. Create player script cat > /home/pi/player.sh << 'PLAYEOF' #!/bin/bash # Kiosk player — registers if new, plays if registered DEVICE_ID_FILE="/home/pi/.device-id" TOKEN_FILE="/home/pi/.device-token" API="https://signage.itpropartner.com/api" REG_CODE="${1:-}" # Hide mouse cursor unclutter -idle 0.1 & # Turn off screen blanking xset s off xset s noblank xset -dpms # Register if not yet registered if [ ! -f "$DEVICE_ID_FILE" ] && [ -n "$REG_CODE" ]; then SERIAL=$(cat /proc/cpuinfo | grep Serial | head -1 | awk '{print $3}') RESPONSE=$(curl -s -X POST "$API/devices/register" \ -H "Content-Type: application/json" \ -d "{\"code\":\"$REG_CODE\",\"serial\":\"$SERIAL\"}") echo "$RESPONSE" | python3 -c "import sys,json;d=json.load(sys.stdin);open('$DEVICE_ID_FILE','w').write(str(d['id']));open('$TOKEN_FILE','w').write(d['token'])" 2>/dev/null fi # Read device ID DEVICE_ID=$(cat "$DEVICE_ID_FILE" 2>/dev/null || echo "") # Launch kiosk browser if [ -n "$DEVICE_ID" ]; then chromium-browser --kiosk \ --no-sandbox \ --disable-infobars \ --disable-session-crashed-bubble \ --disable-features=Translate \ --noerrdialogs \ "$API/player/$DEVICE_ID" else # Show registration screen with QR code chromium-browser --kiosk \ --no-sandbox \ "$API/player/register?code=$REG_CODE" fi PLAYEOF chmod +x /home/pi/player.sh chown pi:pi /home/pi/player.sh # 6. Enable service systemctl enable signage-player.service # 7. Clean up (remove self) rm /boot/signage-firstboot.sh EOF ``` ### Step 2: Flash + Inject Registration (We Do) ```bash # Using Raspberry Pi Imager CLI on your machine rpi-imager-cli --write raspios-lite.img --device /dev/sdX # Mount boot partition and inject first-boot script mount /dev/sdX1 /mnt cp /tmp/signage-firstboot.sh /mnt/ umount /mnt ``` ### Step 3: Ship to Customer Pi arrives at customer location. They plug in: 1. Power (USB-C) 2. HDMI to TV 3. Ethernet (or WiFi pre-configured) **That's it.** No keyboard needed. No monitor for setup. ## What the Customer Sees ### First Boot (Unregistered) ``` ┌──────────────────────────────────────┐ │ │ │ DIGITAL SIGNAGE │ │ │ │ ┌────────────────────────────┐ │ │ │ This screen needs to be │ │ │ │ activated. │ │ │ │ │ │ │ │ Registration Code: │ │ │ │ SIGN-4K7P-M9X2 │ │ │ │ │ │ │ │ [████████████░░░░░░] │ │ │ │ Waiting for activation...│ │ │ └────────────────────────────┘ │ │ │ └──────────────────────────────────────┘ ``` ### After Registration (Normal Operation) ``` ┌──────────────────────────────────────┐ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └──────────────────────────────────────┘ ``` ## Recovery / Re-provisioning ### If Pi needs to be re-registered (different customer): ```bash # On Pi via SSH or USB keyboard: rm /home/pi/.device-id /home/pi/.device-token sudo reboot ``` Then register via the CMS with a new code. ### If customer wants to move Pi to a different TV: Just plug HDMI into the new TV. Pi auto-detects resolution via EDID. No config needed. ### If SD card dies: Flash a new one (same image) → insert → Pi boots → waiting for registration → activate from CMS. 5 minutes total. ## Startup Behavior Summary | Event | What Happens | |---|---| | Power on | Boot → auto-login → start player service | | Network connected | Register or poll for playlist | | Content fetched | Fullscreen Chromium kiosk | | Signal loss | Content cached locally, keeps playing | | Power loss | Auto-restart on power return | | Reboot | Same as power on | | SD card failure | Replace card, re-register | | TV resolution change | Auto-detected via HDMI EDID | ## Provisioning Checklist (For Us) - [ ] Prepare base Raspberry Pi OS lite image - [ ] Add first-boot script (auto-login, dependencies, service) - [ ] Create player kiosk launch script - [ ] Configure Chromium kiosk flags - [ ] Test: flash → boot → play → power loss → reboot → play again - [ ] Package for batch flashing (10+ Pis at once)