Boards now boot LAN-open (host 0.0.0.0, allow_public_bind, require_pairing=false) so a team reaches its node's embedded ZeroClaw dashboard + web chat directly by IP with no token — the 'Open your node' path. Two more modalities ride the same default (cloud-first) agent: - Telegram: config seeds [channels.telegram.default] disabled + pre-bound to the default agent; a team enables it from the dashboard by pasting a @BotFather token. Dashboard writes only set pending_reload, and /admin/reload is loopback-only, so a new zeroclaw-reload-watcher.sh (loopback) applies dashboard config edits within seconds — no shell. provision-fleet pushes + launches it. - Lockdown: zeroclaw-lockdown.sh flips require_pairing=true, reloads, and mints a pair code (open -> locked harden step); documented as a board/adb action since minting + reload are loopback-only. - Voice: seeds a commented [channels.voice_duplex.default] + documents the aarch64 build (embedded-web + gateway-voice-duplex); build/hardware work is separate. Onboarding scripts (apess-selfregister.sh, provision-uno-q.sh) now tolerate open-boot: when the gateway mints no pair code, they announce with a placeholder token (the open board ignores auth) instead of hard-failing. Co-Authored-By: Claude Opus 4.8 <[email protected]>
63 lines
3.0 KiB
Bash
Executable File
63 lines
3.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# The "harden" step — flip a node from open (setup) to paired (locked). Boards
|
|
# boot LAN-open so a team can set up tokenless; once they're done, this locks the
|
|
# node so only their group can reach it.
|
|
#
|
|
# Runs ON the board (loopback): pair-code minting + /admin/reload are localhost-
|
|
# only, so this can't be a LAN-browser button. Trigger it over adb, from a board
|
|
# shell, or wire it to a physical button — then hand the team the pair code it
|
|
# prints (they enter it once in the dashboard's pairing screen).
|
|
#
|
|
# ./zeroclaw-lockdown.sh # on the board
|
|
# adb -s <serial> shell '/home/arduino/zeroclaw-lockdown.sh' # from the host
|
|
#
|
|
# Env:
|
|
# ZC_CONFIG config file (default /home/arduino/.zeroclaw/config.toml)
|
|
# GATEWAY_PORT loopback gateway port (default 8080)
|
|
# ZC_BIN zeroclaw binary (default /home/arduino/zeroclaw)
|
|
set -uo pipefail
|
|
|
|
CONFIG="${ZC_CONFIG:-/home/arduino/.zeroclaw/config.toml}"
|
|
PORT="${GATEWAY_PORT:-8080}"
|
|
ZC_BIN="${ZC_BIN:-/home/arduino/zeroclaw}"
|
|
BASE="http://127.0.0.1:${PORT}"
|
|
|
|
echo "==> locking down this node (require pairing)"
|
|
|
|
# 1) Persist require_pairing=true. Prefer the running gateway's config API
|
|
# (loopback → allowed even while pairing is off); fall back to editing the
|
|
# toml directly if the endpoint isn't reachable.
|
|
if ! curl -sf --max-time 5 -X PUT "${BASE}/api/config/prop?path=gateway.require_pairing" \
|
|
-H 'content-type: application/json' -d 'true' >/dev/null 2>&1; then
|
|
echo " (config API unreachable — editing $CONFIG directly)"
|
|
if grep -qE '^\s*require_pairing\s*=' "$CONFIG"; then
|
|
sed -i 's/^\(\s*require_pairing\s*=\).*/\1 true/' "$CONFIG"
|
|
else
|
|
# insert under [gateway]
|
|
sed -i '/^\[gateway\]/a require_pairing = true' "$CONFIG"
|
|
fi
|
|
fi
|
|
|
|
# 2) Reload so the live PairingGuard picks up require_pairing=true.
|
|
curl -sf --max-time 8 -X POST "${BASE}/admin/reload" >/dev/null 2>&1 || true
|
|
# give the daemon a moment to come back paired
|
|
for _ in $(seq 1 15); do
|
|
curl -sf --max-time 2 "${BASE}/health" >/dev/null 2>&1 && break
|
|
sleep 1
|
|
done
|
|
|
|
# 3) Mint a fresh pair code (localhost-only). Try the admin endpoint, then the CLI.
|
|
CODE="$(curl -sf --max-time 5 -X POST "${BASE}/admin/paircode/new" 2>/dev/null | grep -oE '[0-9]{6}' | head -1)"
|
|
[ -n "$CODE" ] || CODE="$("$ZC_BIN" gateway get-paircode --new --port "$PORT" 2>/dev/null | grep -oE '[0-9]{6}' | head -1)"
|
|
|
|
echo
|
|
if [ -n "$CODE" ]; then
|
|
echo " ┌───────────────────────────────────────────┐"
|
|
echo " │ Node locked. Pairing code: ${CODE} │"
|
|
echo " └───────────────────────────────────────────┘"
|
|
echo " Enter it once in the dashboard's pairing screen (http://<board-ip>:${PORT}/pairing)."
|
|
else
|
|
echo " ! Node lockdown persisted, but couldn't mint a pair code automatically."
|
|
echo " Run on the board: ${ZC_BIN} gateway get-paircode --new --port ${PORT}"
|
|
fi
|