The client_id is the harmony-cli app's plain numeric Client ID — not <num>@fleet, not the app name, not the app Resource ID. Fix the enroll README example and the dev-enroll-device.sh comment accordingly.
97 lines
4.7 KiB
Bash
Executable File
97 lines
4.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Build the aarch64 agent + enroll one device into staging in one shot —
|
|
# the fast inner loop for iterating on the agent against a real Pi (or a
|
|
# Pi-equivalent VM), skipping the manual cross-build + long enroll command.
|
|
#
|
|
# It runs the SAME path the procedure documents, just wrapped:
|
|
# 1. cross-compile harmony-fleet-agent for $AGENT_TARGET (the binary
|
|
# that gets uploaded to /usr/local/bin/fleet-agent).
|
|
# 2. example_fleet_device_enroll — mints the device's Zitadel machine
|
|
# user + key, then runs FleetDeviceSetupScore over SSH to install
|
|
# podman, drop the config, upload the agent, and bring up
|
|
# fleet-agent.service (enabled --now → autostarts on boot).
|
|
#
|
|
# Full procedure + failure modes: examples/fleet_device_enroll/README.md
|
|
# Systemd unit / autostart: harmony/src/modules/fleet/setup_score.rs
|
|
#
|
|
# Usage (per-device + secret values come from env / a local .envrc, never
|
|
# committed — keep your Pi host, device id, and ids there):
|
|
# DEVICE_ID=pi-lab-01 PI_HOST=192.168.2.19 \
|
|
# AUDIENCE=<fleet-project-id> ADMIN_OIDC_CLIENT_ID=<numeric-client-id> \
|
|
# ./fleet/scripts/dev-enroll-device.sh
|
|
#
|
|
# SKIP_BUILD=1 ./fleet/scripts/dev-enroll-device.sh # reuse last agent build
|
|
# DEV_ON_DEVICE=1 ./fleet/scripts/dev-enroll-device.sh # run it ON the Pi (no SSH)
|
|
#
|
|
# Prerequisites:
|
|
# - A running staging install (Zitadel + NATS + callout + operator).
|
|
# - aarch64 cross toolchain for $AGENT_TARGET. gnu (default) uses the
|
|
# system aarch64-linux-gnu-gcc; for an older Pi OS prefer musl via
|
|
# `cross` (see the README's "Why musl, not gnu").
|
|
# - SSH access to $PI_HOST as $SSH_USER (unless DEV_ON_DEVICE=1).
|
|
# - A Zitadel SSO account with machine-user / role-grant / key perms
|
|
# (browser device-code), or HARMONY_ZITADEL_ADMIN_TOKEN set to skip it.
|
|
|
|
set -euo pipefail
|
|
|
|
# ── Required (no sane default — must identify the device + Zitadel app) ──
|
|
: "${DEVICE_ID:?set DEVICE_ID (RFC1123 subdomain, e.g. pi-lab-01)}"
|
|
: "${AUDIENCE:?set AUDIENCE (the fleet Zitadel project id)}"
|
|
: "${ADMIN_OIDC_CLIENT_ID:?set ADMIN_OIDC_CLIENT_ID (the harmony-cli app\'s numeric Client ID, e.g. 371683318111994677 — just the number, no suffix; NOT the app name 'harmony-cli', NOT the app Resource ID)}"
|
|
|
|
# ── Tunable (staging defaults) ──────────────────────────────────────────
|
|
SSH_USER="${SSH_USER:-pi}"
|
|
ISSUER_URL="${ISSUER_URL:-https://sso-staging.cb1.nationtech.io}"
|
|
NATS_URL="${NATS_URL:-wss://nats-fleet-staging.cb1.nationtech.io}"
|
|
LABELS="${LABELS:-group=lab,arch=aarch64}"
|
|
AGENT_TARGET="${AGENT_TARGET:-aarch64-unknown-linux-gnu}"
|
|
SKIP_BUILD="${SKIP_BUILD:-0}"
|
|
DEV_ON_DEVICE="${DEV_ON_DEVICE:-0}"
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
cd "$REPO_ROOT"
|
|
|
|
# Pick up a local .envrc (PI_HOST, ids, admin token, …) if present.
|
|
if [[ -f "$REPO_ROOT/.envrc" ]]; then
|
|
# shellcheck disable=SC1091
|
|
source "$REPO_ROOT/.envrc"
|
|
fi
|
|
|
|
AGENT_BIN="target/${AGENT_TARGET}/release/harmony-fleet-agent"
|
|
|
|
if [[ "$SKIP_BUILD" != "1" ]]; then
|
|
echo "==> [1/2] cross-compile agent for ${AGENT_TARGET}"
|
|
# The gnu target needs the system aarch64 cross-gcc as linker (no
|
|
# ~/.cargo/config.toml target stanza in this repo). Harmless for other
|
|
# targets — cargo only reads the matching var.
|
|
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER="${CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER:-aarch64-linux-gnu-gcc}"
|
|
export CC_aarch64_unknown_linux_gnu="${CC_aarch64_unknown_linux_gnu:-aarch64-linux-gnu-gcc}"
|
|
export CXX_aarch64_unknown_linux_gnu="${CXX_aarch64_unknown_linux_gnu:-aarch64-linux-gnu-g++}"
|
|
export AR_aarch64_unknown_linux_gnu="${AR_aarch64_unknown_linux_gnu:-aarch64-linux-gnu-ar}"
|
|
cargo build --release --target "$AGENT_TARGET" -p harmony-fleet-agent
|
|
else
|
|
echo "==> [1/2] SKIP_BUILD=1, reusing ${AGENT_BIN}"
|
|
fi
|
|
[[ -f "$AGENT_BIN" ]] || { echo "agent binary not found: $AGENT_BIN (unset SKIP_BUILD?)"; exit 1; }
|
|
|
|
echo "==> [2/2] enroll ${DEVICE_ID}"
|
|
# DEV_ON_DEVICE: run ON the Pi (ansible local connection); otherwise SSH.
|
|
target_args=(--target "ssh://${SSH_USER}@${PI_HOST:?set PI_HOST or DEV_ON_DEVICE=1}")
|
|
[[ "$DEV_ON_DEVICE" == "1" ]] && target_args=()
|
|
|
|
cargo run -q -p example_fleet_device_enroll -- \
|
|
"${target_args[@]}" \
|
|
--device-id "$DEVICE_ID" \
|
|
--issuer-url "$ISSUER_URL" \
|
|
--audience "$AUDIENCE" \
|
|
--nats-url "$NATS_URL" \
|
|
--admin-oidc-client-id "$ADMIN_OIDC_CLIENT_ID" \
|
|
--agent-binary "$AGENT_BIN" \
|
|
--labels "$LABELS"
|
|
|
|
echo
|
|
echo "Enrolled ${DEVICE_ID}. Verify the heartbeat:"
|
|
echo " kubectl get fleetdev ${DEVICE_ID} # Device CR"
|
|
echo " nats kv get fleet-device-info ${DEVICE_ID}"
|