feat: kit-busrouter v2.0 — complete Synology + GL fleet router platform
Includes: - package/ GL-XE3000 kit-busrouter (opkg) - scripts/provision.sh (GL) and provision-synology.sh (Synology) - syno-balance/ — new WAN balancer replacing aiwanbal (SmartWAN adapter) - kit-connect/ — unified connectivity SPK (Tailscale + reverse SSH) - docs/deployment/synology-rt2600ac-checklist.md — 62-point checklist - docs/provisioning/device-identity.md — fleet identity spec - docs/pilot/checklist.md — field pilot validation - x4078_20260721.dss — reference config backup Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Executable
+47
@@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
# wg-mgmt-diagnose.sh — READ-ONLY diagnosis of the WG mgmt tunnel on the bench router.
|
||||
# Run ON THE ROUTER over LAN: ssh root@192.168.8.1 (pw kitPLANE1!!), then: sh wg-mgmt-diagnose.sh
|
||||
# Safe: only reads state + captures packets. Mutates nothing.
|
||||
# Context: docs/handoff/2026-07-01-wg-mgmt-incident-and-resume.md
|
||||
set +e
|
||||
HUB_WG=10.88.0.1
|
||||
MGMT_SRC=10.88.0.2
|
||||
HUB_PUB=167.172.237.162
|
||||
|
||||
echo "===== A. FULL WG state (THE missing datapoint — check persistent-keepalive + allowed-ips) ====="
|
||||
wg show
|
||||
echo
|
||||
echo "===== routing / policy (should steer mgmt-sourced traffic into table 1001) ====="
|
||||
echo "-- ip rule --"; ip rule
|
||||
echo "-- table 1001 --"; ip route show table 1001
|
||||
echo "-- default routes --"; ip route show | grep -E '^default'
|
||||
echo "-- underlay path to hub --"; ip route get "$HUB_PUB"
|
||||
echo "-- mgmt-sourced return path --"; ip route get "$HUB_WG" from "$MGMT_SRC" 2>/dev/null
|
||||
echo "-- rp_filter (expect 0; NOT the cause) --"
|
||||
for f in /proc/sys/net/ipv4/conf/all/rp_filter /proc/sys/net/ipv4/conf/eth0/rp_filter \
|
||||
/proc/sys/net/ipv4/conf/rmnet_mhi0/rp_filter /proc/sys/net/ipv4/conf/wgclient1/rp_filter; do
|
||||
[ -f "$f" ] && echo " $f = $(cat "$f")"
|
||||
done
|
||||
echo "-- iface MTUs --"
|
||||
for i in eth0 rmnet_mhi0 wgclient1; do ip link show "$i" 2>/dev/null | sed -n 's/.*\(mtu [0-9]*\).*/ '"$i"': \1/p'; done
|
||||
|
||||
echo
|
||||
echo "===== B. Live capture: watch fiber(eth0) WG + decrypted(wgclient1) while pinging the hub ====="
|
||||
echo " [eth0] = encrypted WG on the fiber underlay ; [wg] = decrypted inner packets"
|
||||
( timeout 12 tcpdump -ni eth0 udp port 51820 2>/dev/null | sed 's/^/[eth0] /' & )
|
||||
( timeout 12 tcpdump -ni wgclient1 2>/dev/null | sed 's/^/[wg] /' & )
|
||||
sleep 1
|
||||
ping -c 8 -W 2 -I "$MGMT_SRC" "$HUB_WG"
|
||||
echo "ping rc=$?"
|
||||
wait 2>/dev/null
|
||||
|
||||
echo
|
||||
echo "===== INTERPRET ====="
|
||||
cat <<'EOF'
|
||||
* wg show 'persistent keepalive: (none)' -> hypothesis #1 (NAT mapping expiry). Fix: keepalive.
|
||||
* hub-peer 'allowed ips' lacks 10.88.0.1 -> hypothesis #2. Replies get cryptokey-dropped.
|
||||
* [eth0] shows OUTBOUND + INBOUND :51820 -> hub replies DO arrive on fiber -> decrypt/inner issue.
|
||||
* [eth0] shows OUTBOUND only -> router pkts not leaving OR hub not returning -> coordinate hub capture.
|
||||
* [wg] shows echo-request but no echo-reply -> confirms replies not reaching inner iface.
|
||||
Next: apply scripts/diag/wg-mgmt-fix.sh (keepalive first). See the handoff doc.
|
||||
EOF
|
||||
Executable
+58
@@ -0,0 +1,58 @@
|
||||
#!/bin/sh
|
||||
# wg-mgmt-fix.sh — apply ONE mgmt-tunnel robustness fix at a time, then bounce wgclient1.
|
||||
# Run ON THE ROUTER over LAN: ssh root@192.168.8.1 (pw kitPLANE1!!)
|
||||
# sh wg-mgmt-fix.sh keepalive # set persistent_keepalive=25 (TRY FIRST)
|
||||
# sh wg-mgmt-fix.sh mtu # set wgclient1 mtu=1280 (fixes PMTU black-holes / SSH data)
|
||||
# sh wg-mgmt-fix.sh rpfilter # persist loose rp_filter (=2) + hotplug re-assert
|
||||
# sh wg-mgmt-fix.sh all # keepalive + mtu + rpfilter
|
||||
# MUTATING but reversible (each is a uci change). Bounces the tunnel ~5s; touches nothing else.
|
||||
# After each: re-test ping -c3 -W2 -I 10.88.0.2 10.88.0.1 (expect replies).
|
||||
# Rationale + goal (mgmt over EITHER WAN): docs/handoff/2026-07-01-wg-mgmt-incident-and-resume.md
|
||||
set -e
|
||||
IFACE=wgclient1
|
||||
|
||||
bounce() { echo ">> uci commit network; ifup $IFACE"; uci commit network; ifup "$IFACE"; sleep 5; }
|
||||
|
||||
do_keepalive() {
|
||||
echo "== persistent_keepalive=25 on $IFACE (hold NAT mapping open on whichever WAN) =="
|
||||
uci set network.$IFACE.persistent_keepalive='25'
|
||||
bounce
|
||||
}
|
||||
|
||||
do_mtu() {
|
||||
echo "== mtu=1280 on $IFACE (safe under cellular + ATT-fiber/PPPoE path MTUs) =="
|
||||
uci set network.$IFACE.mtu='1280'
|
||||
bounce
|
||||
}
|
||||
|
||||
do_rpfilter() {
|
||||
echo "== persist loose rp_filter (=2) so multi-WAN policy-routed mgmt isn't dropped =="
|
||||
grep -q 'busrouter: loose reverse-path' /etc/sysctl.conf 2>/dev/null || cat >> /etc/sysctl.conf <<'EOF'
|
||||
# busrouter: loose reverse-path filtering for multi-WAN WG mgmt failover
|
||||
net.ipv4.conf.all.rp_filter=2
|
||||
net.ipv4.conf.default.rp_filter=2
|
||||
EOF
|
||||
# apply now
|
||||
sysctl -w net.ipv4.conf.all.rp_filter=2 >/dev/null
|
||||
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 2 > "$f"; done
|
||||
# re-assert on WAN flaps (GL DHCP hooks may re-tighten per-iface)
|
||||
mkdir -p /etc/hotplug.d/iface
|
||||
cat > /etc/hotplug.d/iface/99-busrouter-rpfilter <<'EOF'
|
||||
#!/bin/sh
|
||||
[ "$ACTION" = ifup ] || exit 0
|
||||
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 2 > "$f" 2>/dev/null; done
|
||||
EOF
|
||||
chmod +x /etc/hotplug.d/iface/99-busrouter-rpfilter
|
||||
echo " rp_filter now: all=$(cat /proc/sys/net/ipv4/conf/all/rp_filter)"
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
keepalive) do_keepalive ;;
|
||||
mtu) do_mtu ;;
|
||||
rpfilter) do_rpfilter ;;
|
||||
all) do_keepalive; do_mtu; do_rpfilter ;;
|
||||
*) echo "usage: $0 {keepalive|mtu|rpfilter|all}"; exit 2 ;;
|
||||
esac
|
||||
|
||||
echo
|
||||
echo ">> Now verify: ping -c3 -W2 -I 10.88.0.2 10.88.0.1 (replies = mgmt tunnel healthy)"
|
||||
Executable
+298
@@ -0,0 +1,298 @@
|
||||
#!/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 <DEVICE_ID> [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 <DEVICE_ID> [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@<router>:/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} <AUTH_KEY>"
|
||||
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@<router>:/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=<your-eyenet-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@<router-lan-ip> 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
|
||||
Executable
+343
@@ -0,0 +1,343 @@
|
||||
#!/bin/sh
|
||||
# provision.sh — Bootstrap a GL-XE3000 Pioneer Bus Router
|
||||
#
|
||||
# Run once from router LAN (192.168.8.1) or console on a fresh/factory unit.
|
||||
#
|
||||
# Usage:
|
||||
# provision.sh <DEVICE_ID> <WG_PRIVKEY> <WG_TUNNEL_IP>
|
||||
#
|
||||
# DEVICE_ID : bus identifier, e.g. B0042
|
||||
# Becomes the WiFi SSID on both bands (plan spec "X0000" means
|
||||
# SSID = the device ID, not a literal string "X0000").
|
||||
# WG_PRIVKEY : base64 WireGuard private key for this unit (wg genkey)
|
||||
# WG_TUNNEL_IP : assigned tunnel IP, e.g. 10.88.0.42 (no DHCP; hub admin assigns)
|
||||
#
|
||||
# Prerequisites:
|
||||
# - Cellular SIM installed and rmnet_mhi0 online (for opkg)
|
||||
# - kit-busrouter .ipk at /tmp/kit-busrouter.ipk (or set BUSROUTER_IPK env)
|
||||
# - WG keypair generated; public key registered at hub before running this script
|
||||
# - Edit HUB_PUBKEY constant below before deploying
|
||||
#
|
||||
# Idempotent: safe to re-run after partial failure.
|
||||
|
||||
set -e
|
||||
|
||||
DEVICE_ID="${1:?Usage: provision.sh <DEVICE_ID> <WG_PRIVKEY> <WG_TUNNEL_IP>}"
|
||||
WG_PRIVKEY="${2:?Missing WG_PRIVKEY}"
|
||||
WG_TUNNEL_IP="${3:?Missing WG_TUNNEL_IP}"
|
||||
|
||||
BUSROUTER_IPK="${BUSROUTER_IPK:-/tmp/kit-busrouter.ipk}"
|
||||
|
||||
# ── Fleet-wide constants (edit before deploying) ──────────────────────────────
|
||||
HUB_PUBKEY="4QAauZ9gS/wZ/u0Wf66OcJFGo4erng3V5mwpYpARlmc="
|
||||
HUB_HOST="167.172.237.162"
|
||||
HUB_PORT="51820"
|
||||
WG_ALLOWED="10.88.0.0/24"
|
||||
WIFI_PASS="Pioneer123"
|
||||
ADMIN_PASS="Pioneer321!"
|
||||
TIMEZONE="UTC"
|
||||
TIMEZONE_NAME="UTC"
|
||||
|
||||
# Guard: catch forgotten placeholder before any changes are made
|
||||
case "$HUB_PUBKEY" in REPLACE_*)
|
||||
echo "[provision] ERROR: edit HUB_PUBKEY in provision.sh before running" >&2
|
||||
exit 1
|
||||
esac
|
||||
|
||||
echo "[provision] === Pioneer Bus Router Provisioning ==="
|
||||
echo "[provision] DEVICE_ID : $DEVICE_ID"
|
||||
echo "[provision] WG_TUNNEL_IP: $WG_TUNNEL_IP"
|
||||
|
||||
# ── 1. Identity files ─────────────────────────────────────────────────────────
|
||||
echo "[provision] 1/12 Device identity"
|
||||
mkdir -p /etc/busrouter
|
||||
printf '%s\n' "$DEVICE_ID" > /etc/busrouter/device-id
|
||||
[ -f /etc/busrouter/version ] || printf '0.0\n' > /etc/busrouter/version
|
||||
|
||||
# ── 2. Hostname + timezone ────────────────────────────────────────────────────
|
||||
echo "[provision] 2/12 Hostname + timezone"
|
||||
uci set system.@system[0].hostname="$DEVICE_ID"
|
||||
uci set system.@system[0].timezone="$TIMEZONE"
|
||||
uci set system.@system[0].zonename="$TIMEZONE_NAME"
|
||||
uci commit system
|
||||
|
||||
# ── 3. Admin accounts ─────────────────────────────────────────────────────────
|
||||
# GL-XE3000 SSH/WebUI authenticates as root. pioadmin is a uid=0 alias so that
|
||||
# "ssh pioadmin@..." works alongside "ssh root@..." with the same password.
|
||||
echo "[provision] 3/12 Admin accounts (root + pioadmin uid=0 alias)"
|
||||
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"
|
||||
|
||||
if ! grep -q '^pioadmin:' /etc/passwd 2>/dev/null; then
|
||||
echo "pioadmin:x:0:0:Fleet Admin:/root:/bin/ash" >> /etc/passwd
|
||||
fi
|
||||
# BusyBox shadow needs 9 colon-separated fields
|
||||
if ! grep -q '^pioadmin:' /etc/shadow 2>/dev/null; then
|
||||
echo "pioadmin:!:0:0:99999:7:::" >> /etc/shadow
|
||||
fi
|
||||
printf '%s\n%s\n' "$ADMIN_PASS" "$ADMIN_PASS" | passwd pioadmin 2>/dev/null || \
|
||||
echo "pioadmin:${ADMIN_PASS}" | chpasswd 2>/dev/null || \
|
||||
echo "[provision] WARNING: failed to set pioadmin password"
|
||||
|
||||
# ── 4. WiFi SSID (2.4 GHz + 5 GHz) ──────────────────────────────────────────
|
||||
echo "[provision] 4/12 SSID=${DEVICE_ID} / Pioneer123"
|
||||
ifaces=$(uci show wireless 2>/dev/null | grep '=wifi-iface' | cut -d. -f2 | cut -d= -f1)
|
||||
if [ -z "$ifaces" ]; then
|
||||
echo "[provision] WARNING: no wifi-iface sections found — check 'uci show wireless'"
|
||||
else
|
||||
for iface in $ifaces; do
|
||||
uci set "wireless.${iface}.ssid=${DEVICE_ID}"
|
||||
uci set "wireless.${iface}.key=${WIFI_PASS}"
|
||||
uci set "wireless.${iface}.encryption=psk2"
|
||||
done
|
||||
uci commit wireless
|
||||
wifi reload 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# ── 5. Stand down GL's kmwan ─────────────────────────────────────────────────
|
||||
echo "[provision] 5/13 Disabling GL kmwan"
|
||||
/etc/init.d/kmwan disable 2>/dev/null || true
|
||||
/etc/init.d/kmwan stop 2>/dev/null || true
|
||||
|
||||
# ── 5b. Disable GL route_policy VPN kill switch ───────────────────────────────
|
||||
# GL firmware treats the WireGuard client as a "Primary Tunnel" and enables a
|
||||
# kill switch that marks ALL LAN traffic for WG routing. Since our WG only
|
||||
# carries management traffic (AllowedIPs=10.88.0.0/24), this kills internet
|
||||
# for LAN clients. Disable the rule so GL does not interfere with mwan3.
|
||||
echo "[provision] 5b/13 Disabling GL route_policy kill switch"
|
||||
# The anonymous @rule[0] is the "Primary Tunnel" rule (wgclient1, killswitch=1)
|
||||
uci set route_policy.@rule[0].killswitch='0' 2>/dev/null || true
|
||||
uci set route_policy.@rule[0].enabled='0' 2>/dev/null || true
|
||||
uci commit route_policy 2>/dev/null || true
|
||||
|
||||
# ── 6. Install packages ───────────────────────────────────────────────────────
|
||||
echo "[provision] 6/12 opkg update + mwan3"
|
||||
opkg update
|
||||
opkg install mwan3
|
||||
if [ -f "$BUSROUTER_IPK" ]; then
|
||||
echo "[provision] Installing kit-busrouter"
|
||||
opkg install --force-reinstall "$BUSROUTER_IPK"
|
||||
else
|
||||
echo "[provision] WARNING: $BUSROUTER_IPK not found — install kit-busrouter manually"
|
||||
fi
|
||||
|
||||
# ── 7. wwan interface: enable DHCP default route for repeater ─────────────────
|
||||
# GL sets classlessroute=0 by default, which prevents the DHCP-obtained gateway
|
||||
# from being installed in the main routing table. Without a default via apcli0,
|
||||
# the repeater cannot forward internet traffic even when connected.
|
||||
echo "[provision] 7/13 wwan classlessroute fix (enable repeater gateway)"
|
||||
uci set network.wwan.classlessroute=1
|
||||
uci commit network
|
||||
|
||||
# ── 8. mwan3 base config ──────────────────────────────────────────────────────
|
||||
# Priority: wwan (repeater, metric 1) > modem_0001 (5G cellular, metric 2) > wan (Starlink, metric 3)
|
||||
# last_resort='default' — if all mwan3 members are offline, fall back to whatever
|
||||
# the main routing table has rather than returning unreachable to all clients.
|
||||
echo "[provision] 8/13 mwan3 (priority: wwan(1) > modem_0001(2) > wan(3))"
|
||||
uci batch << 'MWAN3_EOF'
|
||||
delete mwan3
|
||||
set mwan3.globals=globals
|
||||
set mwan3.globals.mmx_mask='0x3F00'
|
||||
set mwan3.globals.logging='0'
|
||||
set mwan3.wwan=interface
|
||||
set mwan3.wwan.enabled='1'
|
||||
set mwan3.wwan.initial_state='online'
|
||||
set mwan3.wwan.family='ipv4'
|
||||
set mwan3.wwan.track_ip='1.1.1.1'
|
||||
add_list mwan3.wwan.track_ip='8.8.8.8'
|
||||
set mwan3.wwan.track_method='ping'
|
||||
set mwan3.wwan.reliability='1'
|
||||
set mwan3.wwan.count='1'
|
||||
set mwan3.wwan.down='3'
|
||||
set mwan3.wwan.up='3'
|
||||
set mwan3.wwan.interval='5'
|
||||
set mwan3.modem_0001=interface
|
||||
set mwan3.modem_0001.enabled='1'
|
||||
set mwan3.modem_0001.initial_state='online'
|
||||
set mwan3.modem_0001.family='ipv4'
|
||||
set mwan3.modem_0001.track_ip='1.1.1.1'
|
||||
add_list mwan3.modem_0001.track_ip='8.8.8.8'
|
||||
set mwan3.modem_0001.track_method='ping'
|
||||
set mwan3.modem_0001.reliability='1'
|
||||
set mwan3.modem_0001.count='1'
|
||||
set mwan3.modem_0001.down='3'
|
||||
set mwan3.modem_0001.up='3'
|
||||
set mwan3.modem_0001.interval='5'
|
||||
set mwan3.wan=interface
|
||||
set mwan3.wan.enabled='1'
|
||||
set mwan3.wan.initial_state='online'
|
||||
set mwan3.wan.family='ipv4'
|
||||
set mwan3.wan.track_ip='1.1.1.1'
|
||||
add_list mwan3.wan.track_ip='8.8.8.8'
|
||||
set mwan3.wan.track_method='ping'
|
||||
set mwan3.wan.reliability='1'
|
||||
set mwan3.wan.count='1'
|
||||
set mwan3.wan.down='3'
|
||||
set mwan3.wan.up='3'
|
||||
set mwan3.wan.interval='5'
|
||||
set mwan3.wwan_mbr=member
|
||||
set mwan3.wwan_mbr.interface='wwan'
|
||||
set mwan3.wwan_mbr.metric='1'
|
||||
set mwan3.wwan_mbr.weight='100'
|
||||
set mwan3.cell_mbr=member
|
||||
set mwan3.cell_mbr.interface='modem_0001'
|
||||
set mwan3.cell_mbr.metric='2'
|
||||
set mwan3.cell_mbr.weight='100'
|
||||
set mwan3.wan_mbr=member
|
||||
set mwan3.wan_mbr.interface='wan'
|
||||
set mwan3.wan_mbr.metric='3'
|
||||
set mwan3.wan_mbr.weight='100'
|
||||
set mwan3.balanced=policy
|
||||
set mwan3.balanced.last_resort='default'
|
||||
add_list mwan3.balanced.use_member='wwan_mbr'
|
||||
add_list mwan3.balanced.use_member='cell_mbr'
|
||||
add_list mwan3.balanced.use_member='wan_mbr'
|
||||
set mwan3.default_rule=rule
|
||||
set mwan3.default_rule.dest='0.0.0.0/0'
|
||||
set mwan3.default_rule.proto='all'
|
||||
set mwan3.default_rule.use_policy='balanced'
|
||||
MWAN3_EOF
|
||||
uci commit mwan3
|
||||
/etc/init.d/mwan3 enable
|
||||
/etc/init.d/mwan3 restart 2>/dev/null || true
|
||||
|
||||
# ── 8. WireGuard mgmt tunnel ──────────────────────────────────────────────────
|
||||
# GL-XE3000 uses proto 'wgclient' (GL proprietary). The interface wgclient1 exists
|
||||
# in the factory image and references a peer config section (typically peer_2001).
|
||||
# Private key goes on the INTERFACE; public key + endpoint go on the PEER section.
|
||||
echo "[provision] 9/13 WireGuard (wgclient1)"
|
||||
|
||||
# Ensure interface section exists with correct type
|
||||
uci get network.wgclient1 >/dev/null 2>&1 || uci set network.wgclient1=wgclient
|
||||
uci set network.wgclient1.ip4table='1001'
|
||||
uci set network.wgclient1.mtu='1280'
|
||||
# Private key belongs on the interface (GL wgclient proto reads it here)
|
||||
uci set network.wgclient1.private_key="${WG_PRIVKEY}"
|
||||
uci set network.wgclient1.ip_address="${WG_TUNNEL_IP}/32"
|
||||
|
||||
# Update the peer section (hub endpoint + pubkey)
|
||||
peer_sec=""
|
||||
if uci get network.peer_2001 >/dev/null 2>&1; then
|
||||
peer_sec="peer_2001"
|
||||
else
|
||||
peer_sec=$(uci show network 2>/dev/null | grep '=wgclient_peer' | head -n1 \
|
||||
| cut -d. -f2 | cut -d= -f1)
|
||||
fi
|
||||
if [ -n "$peer_sec" ]; then
|
||||
uci set "network.${peer_sec}.public_key=${HUB_PUBKEY}"
|
||||
uci set "network.${peer_sec}.endpoint_host=${HUB_HOST}"
|
||||
uci set "network.${peer_sec}.endpoint_port=${HUB_PORT}"
|
||||
uci set "network.${peer_sec}.allowed_ips=${WG_ALLOWED}"
|
||||
uci set "network.${peer_sec}.persistent_keepalive=25"
|
||||
else
|
||||
echo "[provision] WARNING: no WG peer section found — configure hub peer manually"
|
||||
fi
|
||||
uci commit network
|
||||
|
||||
# ── 9b. Inbound mgmt SSH over the tunnel ──────────────────────────────────────
|
||||
# Bring up the path the hub/lab uses to reach this unit. Without BOTH of these
|
||||
# the tunnel comes up but SSH silently hits the wgclient1 zone DROP.
|
||||
# See docs/mgmt-tunnel-ssh.md for the full explanation.
|
||||
echo "[provision] 9b/13 Inbound mgmt SSH (firewall rule + hub jump key)"
|
||||
|
||||
# The WG client interface lives in its own firewall zone (defaults input=DROP).
|
||||
# Find the zone bound to wgclient1; fall back to the interface name.
|
||||
WG_ZONE=$(uci show firewall 2>/dev/null | awk -F"[.=]" '
|
||||
/\.name=/ {z=$2; name=$0}
|
||||
/\.network=/ && /wgclient1/ {print z; exit}')
|
||||
[ -n "$WG_ZONE" ] || WG_ZONE="wgclient1"
|
||||
|
||||
if ! uci show firewall 2>/dev/null | grep -q "name='Allow-WG-mgmt-SSH'"; then
|
||||
uci add firewall rule >/dev/null
|
||||
uci set firewall.@rule[-1].name='Allow-WG-mgmt-SSH'
|
||||
uci set firewall.@rule[-1].src="$WG_ZONE"
|
||||
uci set firewall.@rule[-1].proto='tcp'
|
||||
uci set firewall.@rule[-1].dest_port='22'
|
||||
uci set firewall.@rule[-1].family='ipv4'
|
||||
uci set firewall.@rule[-1].src_ip="$WG_ALLOWED"
|
||||
uci set firewall.@rule[-1].target='ACCEPT'
|
||||
uci commit firewall
|
||||
/etc/init.d/firewall restart 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Install the busfleet-hub jump key so the hub can SSH inbound over the tunnel.
|
||||
mkdir -p /etc/dropbear
|
||||
JUMP_KEY='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMS842ZbXPXHbVd9IjyVGubq7M/yQA/cn/vHgB5R0/ZE busfleet-hub-jump'
|
||||
if ! grep -qF 'busfleet-hub-jump' /etc/dropbear/authorized_keys 2>/dev/null; then
|
||||
printf '%s\n' "$JUMP_KEY" >> /etc/dropbear/authorized_keys
|
||||
fi
|
||||
chmod 600 /etc/dropbear/authorized_keys
|
||||
|
||||
# ── 9. ip rule: WG mgmt tunnel survives mwan3 ─────────────────────────────────
|
||||
# See device-identity.md §4 for root-cause explanation.
|
||||
echo "[provision] 10/13 WG mgmt ip rule (priority 99 -> table 1001)"
|
||||
ip rule del to "$WG_ALLOWED" priority 99 lookup 1001 2>/dev/null || true
|
||||
ip rule add to "$WG_ALLOWED" priority 99 lookup 1001 2>/dev/null || true
|
||||
|
||||
# Persist via UCI (uci show uses key='value' format, so this grep is correct)
|
||||
if ! uci show network 2>/dev/null | grep -q "\.dest='${WG_ALLOWED}'"; then
|
||||
uci add network rule
|
||||
uci set network.@rule[-1].lookup='1001'
|
||||
uci set network.@rule[-1].dest="${WG_ALLOWED}"
|
||||
uci set network.@rule[-1].priority='99'
|
||||
uci commit network
|
||||
fi
|
||||
|
||||
# ── 10. rp_filter=2 for wgclient1 ────────────────────────────────────────────
|
||||
echo "[provision] 11/13 rp_filter + hotplug"
|
||||
# GL-XE3000 may use /etc/sysctl.d/ drop-ins; write there for reliability
|
||||
mkdir -p /etc/sysctl.d
|
||||
printf 'net.ipv4.conf.wgclient1.rp_filter=2\n' > /etc/sysctl.d/10-busrouter.conf
|
||||
sysctl -w net.ipv4.conf.wgclient1.rp_filter=2 2>/dev/null || true
|
||||
# Also add to /etc/sysctl.conf if it exists and doesn't already have our setting
|
||||
if [ -f /etc/sysctl.conf ]; then
|
||||
grep -q 'wgclient1.rp_filter' /etc/sysctl.conf || \
|
||||
printf 'net.ipv4.conf.wgclient1.rp_filter=2\n' >> /etc/sysctl.conf
|
||||
fi
|
||||
|
||||
# Inline hotplug: re-assert rp_filter after any WAN state change
|
||||
cat > /etc/hotplug.d/iface/99-busrouter-rpfilter << 'HOTPLUG_EOF'
|
||||
#!/bin/sh
|
||||
[ "$ACTION" = "ifup" ] || exit 0
|
||||
sysctl -w net.ipv4.conf.wgclient1.rp_filter=2 2>/dev/null || true
|
||||
HOTPLUG_EOF
|
||||
chmod +x /etc/hotplug.d/iface/99-busrouter-rpfilter
|
||||
|
||||
# ── 11. GNSS enable on boot ───────────────────────────────────────────────────
|
||||
echo "[provision] 12/13 GNSS boot enable"
|
||||
if ! grep -q 'AT+QGPS=1' /etc/rc.local 2>/dev/null; then
|
||||
printf '# Enable Quectel GNSS engine on boot (OFF by default)\n' >> /etc/rc.local
|
||||
printf 'sleep 10; gl_modem -B 1-1.2 AT AT+QGPS=1 2>/dev/null\n' >> /etc/rc.local
|
||||
fi
|
||||
|
||||
# ── 12b. Apply GL route_policy change (restart gl-tertf daemon) ──────────────
|
||||
# gl-tertf reads /etc/config/route_policy and installs iptables tunnel marks.
|
||||
# Restart it now so the kill switch disable takes effect before the reboot.
|
||||
/etc/init.d/gl-tertf restart 2>/dev/null || true
|
||||
|
||||
# ── 13. Enable + start busrouter daemon ──────────────────────────────────────
|
||||
echo "[provision] 13/13 busrouter daemon"
|
||||
if [ -f /etc/init.d/busrouter ]; then
|
||||
/etc/init.d/busrouter enable
|
||||
/etc/init.d/busrouter start 2>/dev/null || true
|
||||
else
|
||||
echo "[provision] WARNING: busrouter init not found — install kit-busrouter first"
|
||||
fi
|
||||
|
||||
# ── Done ──────────────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "[provision] ============================================"
|
||||
echo "[provision] DONE: $DEVICE_ID provisioned."
|
||||
echo " WiFi SSID : $DEVICE_ID (2.4G + 5G) pw: Pioneer123"
|
||||
echo " Admin SSH : ssh root@192.168.8.1 pw: Pioneer321!"
|
||||
echo " ssh pioadmin@192.168.8.1 pw: Pioneer321!"
|
||||
echo " WG tunnel : $WG_TUNNEL_IP"
|
||||
echo " Verify : mwan3 status"
|
||||
echo " cat /etc/busrouter/device-id"
|
||||
echo " ps | grep daemon.sh"
|
||||
echo "[provision] ============================================"
|
||||
echo ""
|
||||
echo "[provision] Rebooting in 5 s ..."
|
||||
sleep 5
|
||||
reboot
|
||||
Reference in New Issue
Block a user