#!/bin/sh # provision-synology.sh — Bootstrap a Synology RT2600ac Pioneer Bus Router # # Run once from router LAN or console on a fresh/factory Synology SRM unit. # # Usage: # provision-synology.sh [TAILSCALE_AUTH_KEY] # # DEVICE_ID : bus identifier, e.g. B0042 # Becomes the WiFi SSID on both bands (plan spec). # TAILSCALE_AUTH_KEY : Tailscale pre-auth key (tskey-...). # Omit if Tailscale is already configured. # # Prerequisites: # - SRM 1.3.1+ with SSH enabled (Control Panel → Terminal & SNMP) # - SD card inserted (for persistent storage) # - aiwanbal SPK at /tmp/aiwanbal-latest.spk (or set AIWANBAL_SPK env) # - Tailscale SPK installed (or TAILSCALE_AUTH_KEY provided to configure) # - Eyeride Eyenet reachable at 192.168.10.1 (if GPS is used) # - Edit HUB_TAILSCALE_IP constant below before deploying # # Idempotent: safe to re-run after partial failure. set -e DEVICE_ID="${1:?Usage: provision-synology.sh [TAILSCALE_AUTH_KEY]}" TAILSCALE_AUTH_KEY="${2:-}" AIWANBAL_SPK="${AIWANBAL_SPK:-/tmp/aiwanbal-latest.spk}" # ── Fleet-wide constants (edit before deploying) ────────────────────────────────── HUB_TAILSCALE_IP="100.76.128.1" # hub's Tailscale IP HUB_TELEMETRY_PORT="8080" # telemetry API port on hub HUB_TELEMETRY_PATH="/api/telemetry" # telemetry endpoint path WIFI_PASS="Pioneer123" ADMIN_PASS="Pioneer321!" TIMEZONE="UTC" # Guard: catch forgotten placeholder before any changes are made case "$HUB_TAILSCALE_IP" in REPLACE_*|CHANGE_ME*|"") echo "[provision] ERROR: edit HUB_TAILSCALE_IP in provision-synology.sh before running" >&2 exit 1 ;; esac TELEMETRY_HUB="http://${HUB_TAILSCALE_IP}:${HUB_TELEMETRY_PORT}${HUB_TELEMETRY_PATH}" echo "[provision] === Pioneer Bus Router Provisioning (Synology SRM) ===" echo "[provision] DEVICE_ID : $DEVICE_ID" echo "[provision] HUB_TAILSCALE_IP : $HUB_TAILSCALE_IP" echo "[provision] TELEMETRY_HUB : $TELEMETRY_HUB" echo "" # ── 1. Device identity ─────────────────────────────────────────────────────────── echo "[provision] 1/11 Device identity" mkdir -p /etc/busrouter printf '%s\n' "$DEVICE_ID" > /etc/busrouter/device-id if [ ! -f /etc/busrouter/version ]; then printf '0.0\n' > /etc/busrouter/version fi echo "[provision] device-id: $(cat /etc/busrouter/device-id)" echo "[provision] version: $(cat /etc/busrouter/version)" # ── 2. Hostname ────────────────────────────────────────────────────────────────── # SRM stores hostname in /etc/synoinfo.conf and /etc/hostname echo "[provision] 2/11 Hostname → ${DEVICE_ID}" if command -v synosetkeyvalue >/dev/null 2>&1; then synosetkeyvalue /etc/synoinfo.conf system hostname "$DEVICE_ID" 2>/dev/null || true fi hostname "$DEVICE_ID" 2>/dev/null || true printf '%s\n' "$DEVICE_ID" > /etc/hostname 2>/dev/null || true # ── 3. Admin accounts ──────────────────────────────────────────────────────────── # Synology SRM: the web admin user is typically "admin" (created at setup). # SSH uses root (set via SRM Control Panel → Terminal & SNMP). # We set the root password for fleet SSH access. echo "[provision] 3/11 Admin account (root password)" printf '%s\n%s\n' "$ADMIN_PASS" "$ADMIN_PASS" | passwd root 2>/dev/null || \ echo "root:${ADMIN_PASS}" | chpasswd 2>/dev/null || \ echo "[provision] WARNING: failed to set root password" # ── 4. WiFi SSID ───────────────────────────────────────────────────────────────── # SRM WiFi is managed through the web UI (Wi-Fi Connect app). # We can configure it via synowifi if available, but the authoritative path # is the SRM Network Center. Log the expected values and attempt CLI config. echo "[provision] 4/11 WiFi SSID=${DEVICE_ID} (2.4G + 5G)" echo "[provision] Password: ${WIFI_PASS}" echo "[provision] NOTE: If WiFi doesn't change, configure manually in SRM:" echo "[provision] Wi-Fi Connect → Radio 1 (2.4G) → SSID: ${DEVICE_ID}" echo "[provision] Wi-Fi Connect → Radio 2 (5G) → SSID: ${DEVICE_ID}" # Try synowifi if present (may not exist on all SRM versions) if command -v synowifi >/dev/null 2>&1; then synowifi --set-ssid "$DEVICE_ID" --set-security wpa2-personal --set-passphrase "$WIFI_PASS" 2>/dev/null || \ echo "[provision] WARNING: synowifi command failed — configure WiFi via SRM web UI" elif command -v /usr/syno/bin/synowifi >/dev/null 2>&1; then /usr/syno/bin/synowifi --set-ssid "$DEVICE_ID" --set-security wpa2-personal --set-passphrase "$WIFI_PASS" 2>/dev/null || \ echo "[provision] WARNING: synowifi command failed — configure WiFi via SRM web UI" fi # ── 5. Install aiwanbal ────────────────────────────────────────────────────────── echo "[provision] 5/11 aiwanbal WAN balancer" if [ -f "$AIWANBAL_SPK" ]; then echo "[provision] Installing aiwanbal from $AIWANBAL_SPK" synopkg install "$AIWANBAL_SPK" 2>/dev/null || \ echo "[provision] WARNING: synopkg install failed — install manually" else echo "[provision] WARNING: $AIWANBAL_SPK not found" echo "[provision] Build aiwanbal SPK first, then copy to router:" echo "[provision] cd /home/node/workspace/aiwanbal && bash build.sh" echo "[provision] scp -O aiwanbal-*.spk kitadmin@:/tmp/aiwanbal-latest.spk" fi # Ensure aiwanbal is running if synopkg status aiwanbal >/dev/null 2>&1; then synopkg start aiwanbal 2>/dev/null || true echo "[provision] aiwanbal started" else echo "[provision] WARNING: aiwanbal package not found — install before continuing" fi # ── 6. Configure aiwanbal for busrouter (mobile environment) ───────────────────── echo "[provision] 6/11 aiwanbal busrouter tuning" AIWANBAL_CONF="/etc/aiwanbal/aiwanbal.conf" if [ -f "$AIWANBAL_CONF" ]; then # Set environment to mobile for faster scoring adaptations if grep -q '^ENVIRONMENT=' "$AIWANBAL_CONF" 2>/dev/null; then sed -i 's/^ENVIRONMENT=.*/ENVIRONMENT="mobile"/' "$AIWANBAL_CONF" else echo 'ENVIRONMENT="mobile"' >> "$AIWANBAL_CONF" fi # Set device name for fleet logging if grep -q '^DEVICE_NAME=' "$AIWANBAL_CONF" 2>/dev/null; then sed -i "s/^DEVICE_NAME=.*/DEVICE_NAME=\"$DEVICE_ID\"/" "$AIWANBAL_CONF" else echo "DEVICE_NAME=\"$DEVICE_ID\"" >> "$AIWANBAL_CONF" fi # Metered cellular: disable automatic speed tests to save data if grep -q '^SPEEDTEST_AUTO=' "$AIWANBAL_CONF" 2>/dev/null; then sed -i 's/^SPEEDTEST_AUTO=.*/SPEEDTEST_AUTO="0"/' "$AIWANBAL_CONF" else echo 'SPEEDTEST_AUTO="0"' >> "$AIWANBAL_CONF" fi # Log the config update logger -t provision "aiwanbal tuned for busrouter: mobile mode, auto-speedtest disabled" echo "[provision] ENVIRONMENT=mobile, SPEEDTEST_AUTO=0, DEVICE_NAME=${DEVICE_ID}" else echo "[provision] WARNING: aiwanbal.conf not found — tune manually" fi # ── 7. Tailscale ───────────────────────────────────────────────────────────────── echo "[provision] 7/11 Tailscale" if command -v tailscale >/dev/null 2>&1; then if [ -n "$TAILSCALE_AUTH_KEY" ]; then echo "[provision] Authenticating with pre-auth key..." tailscale up --authkey="$TAILSCALE_AUTH_KEY" --hostname="$DEVICE_ID" 2>/dev/null || \ echo "[provision] WARNING: tailscale up failed — check auth key" else ts_status=$(tailscale status --json 2>/dev/null || echo '{"BackendState":"NeedsLogin"}') ts_state=$(echo "$ts_status" | grep -o '"BackendState":"[^"]*"' | cut -d'"' -f4) if [ "$ts_state" = "Running" ]; then echo "[provision] Tailscale is running" else echo "[provision] WARNING: Tailscale not authenticated" echo "[provision] Run: tailscale up --hostname=${DEVICE_ID}" echo "[provision] Or re-run with: provision-synology.sh ${DEVICE_ID} " fi fi # Show Tailscale IP for fleet records ts_ip=$(tailscale ip -4 2>/dev/null || echo "unknown") echo "[provision] Tailscale IP: ${ts_ip}" else echo "[provision] WARNING: tailscale not found — install Tailscale SPK first" echo "[provision] Download from: https://pkgs.tailscale.com/stable/#synology" fi # ── 8. Telemetry script + cron ─────────────────────────────────────────────────── echo "[provision] 8/11 Telemetry agent" # Determine where to install the telemetry script TELEM_SRC="/usr/lib/busrouter/telemetry-synology.sh" TELEM_DEST="${TELEM_DEST:-/usr/lib/busrouter/telemetry-synology.sh}" # Check if this script is bundled with the repo (running from checkout) or # needs to be copied from a pre-staged location. if [ -f "$TELEM_SRC" ]; then echo "[provision] Using telemetry script from ${TELEM_SRC}" elif [ -f "/tmp/telemetry-synology.sh" ]; then TELEM_SRC="/tmp/telemetry-synology.sh" echo "[provision] Using telemetry script from /tmp/" else # The script should be copied alongside provision-synology.sh before running echo "[provision] WARNING: telemetry-synology.sh not found" echo "[provision] Copy it to /tmp/telemetry-synology.sh and re-run:" echo "[provision] scp package/kit-busrouter/files/usr/lib/busrouter/telemetry-synology.sh \\" echo "[provision] kitadmin@:/tmp/" fi if [ -f "$TELEM_SRC" ]; then mkdir -p "$(dirname "$TELEM_DEST")" cp "$TELEM_SRC" "$TELEM_DEST" chmod +x "$TELEM_DEST" # Configure the hub endpoint in the script sed -i "s|TELEMETRY_HUB:=http://10.88.0.1:8080/api/telemetry|TELEMETRY_HUB:=${TELEMETRY_HUB}|" "$TELEM_DEST" # Add cron job: run telemetry every 60 seconds # SRM uses /etc/crontab with user field (standard vixie-cron format) CRON_JOB="* * * * * root ${TELEM_DEST} 2>/dev/null" if [ -f /etc/crontab ]; then if ! grep -qF "$TELEM_DEST" /etc/crontab 2>/dev/null; then # Sleep offset to spread fleet load: use the last octet of device ID as stagger _stagger=0 _dev_suffix=$(echo "$DEVICE_ID" | grep -o '[0-9]*$' || echo "0") _stagger=$(( _dev_suffix % 60 )) printf '%s\n' "* * * * * root sleep ${_stagger}; ${TELEM_DEST} 2>/dev/null" >> /etc/crontab echo "[provision] Cron job added (${_stagger}s offset)" else echo "[provision] Cron job already present" fi else # Fallback: use crontab -e style (crontab -l 2>/dev/null || true; echo "* * * * * ${TELEM_DEST} 2>/dev/null") | crontab - 2>/dev/null || \ echo "[provision] WARNING: failed to add cron job — add manually" fi echo "[provision] Telemetry installed at ${TELEM_DEST}" fi # ── 9. Hub SSH jump key ────────────────────────────────────────────────────────── echo "[provision] 9/11 Hub SSH jump key" mkdir -p /root/.ssh JUMP_KEY='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMS842ZbXPXHbVd9IjyVGubq7M/yQA/cn/vHgB5R0/ZE busfleet-hub-jump' if ! grep -qF 'busfleet-hub-jump' /root/.ssh/authorized_keys 2>/dev/null; then printf '%s\n' "$JUMP_KEY" >> /root/.ssh/authorized_keys chmod 600 /root/.ssh/authorized_keys echo "[provision] Hub jump key installed" else echo "[provision] Hub jump key already present" fi # ── 10. Eyeride GPS config (optional) ──────────────────────────────────────────── echo "[provision] 10/11 Eyeride GPS" EYERIDE_IP="${EYERIDE_IP:-192.168.10.1}" EYERIDE_PORT="${EYERIDE_PORT:-8080}" echo "[provision] Eyeride target: ${EYERIDE_IP}:${EYERIDE_PORT}" echo "[provision] Set EYERIDE_PASSWORD env before running telemetry for GPS" echo "[provision] To configure permanently, add to aiwanbal.conf:" echo "[provision] EYERIDE_IP=${EYERIDE_IP}" echo "[provision] EYERIDE_PORT=${EYERIDE_PORT}" echo "[provision] EYERIDE_PASSWORD=" # ── 11. Verify + start services ────────────────────────────────────────────────── echo "[provision] 11/11 Final checks" # Ensure aiwanbal is running if synopkg status aiwanbal >/dev/null 2>&1; then synopkg start aiwanbal 2>/dev/null || true echo "[provision] aiwanbal is running" fi # Run one telemetry cycle to verify if [ -x "$TELEM_DEST" ]; then if "$TELEM_DEST" 2>/dev/null; then echo "[provision] Telemetry dry-run OK" else echo "[provision] Telemetry dry-run completed (check logs for POST result)" fi fi # ── Done ────────────────────────────────────────────────────────────────────────── echo "" echo "[provision] ============================================" echo "[provision] DONE: $DEVICE_ID provisioned (Synology SRM)." echo "" echo " Device ID : $DEVICE_ID" echo " Hostname : $DEVICE_ID" echo " WiFi SSID : $DEVICE_ID (2.4G + 5G) pw: Pioneer123" echo " Admin SSH : ssh root@ pw: Pioneer321!" if command -v tailscale >/dev/null 2>&1; then echo " Tailscale IP : $(tailscale ip -4 2>/dev/null || echo 'check `tailscale status`')" fi echo " Telemetry : ${TELEMETRY_HUB} (every 60s via cron)" echo "" echo " Verify:" echo " cat /etc/busrouter/device-id" echo " synopkg status aiwanbal" echo " tailscale status" echo " grep telemetry /etc/crontab" echo " tail -f /var/log/messages | grep busrouter" echo "[provision] ============================================" echo "" # ── Reboot ─────────────────────────────────────────────────────────────────────── echo "[provision] Rebooting in 5 s ..." sleep 5 reboot