HALO/v0.1.0/OPERATIONS

Configuration and operations

This page covers building HALO, deploying binaries to devices, and managing services in the field.

Build

HALO cross-compiles from a workstation to aarch64-unknown-linux-musl using Zig as the linker. Always use cargo zigbuild, never cargo build.

bash
# Cross-compile all binaries
cargo zigbuild --release --target aarch64-unknown-linux-musl \
  --bin halo --bin halo_agent --bin halo-mesh --bin halo-field --bin haloctl

# Single binary
cargo zigbuild --release --target aarch64-unknown-linux-musl --bin halo

# Fast type/borrow check on the workstation
cargo check

# Build the frontend for device use
cd frontend && VITE_USE_DEVICE=true npm run build

SQLite is statically linked. Binaries are version-stamped with the git commit hash and build timestamp via build.rs, exposed at /health and through --version.

Deploy

Deploy is a binary push followed by a service restart. Serve the artifact over HTTP from the workstation and pull it onto the device with wget — do not use SCP.

bash
# 1. Serve the release artifact from the build output directory
python -m http.server 9001

# 2. Stop, replace, restart, and check on the gateway
ssh halo-gw "sudo systemctl stop gateway-api \
  && sudo wget -q -O /usr/local/bin/gateway-api http://<workstation-ip>:9001/halo \
  && sudo chmod +x /usr/local/bin/gateway-api \
  && sudo systemctl start gateway-api \
  && sleep 3 && sudo systemctl status gateway-api"

# 3. Verify a clean startup before confirming
ssh halo-gw "journalctl -u gateway-api -n 30 --no-pager"

Always read the logs before declaring a deploy good.

Services

Services are managed with systemd. The dependency chain is halo-meshgateway-api + halo-agent; mesh is the root dependency.

bash
ssh halo-gw "sudo systemctl restart gateway-api"
ssh halo-gw "sudo systemctl status gateway-api"
ssh halo-gw "journalctl -u gateway-api -f"            # live logs
ssh halo-gw "journalctl -u gateway-api -n 50 --no-pager"

If systemctl is-enabled halo-mesh returns disabled, no HALO services start on boot. Always verify the enabled state after any hardware change.

Binary paths on device

PathBinary
/usr/local/bin/gateway-apiMain API server (gateway only)
/usr/local/bin/halo-agentNode agent (all nodes)
/usr/local/bin/halo-meshMesh manager (all nodes)
/usr/local/bin/halo-fieldField diagnostics UI (remote nodes, port 80)
/usr/local/bin/haloctlCLI tool

Configuration and data locations

PathHolds
/etc/halo/config.yamlNode configuration written by haloctl setup
/etc/halo/agent-envAPI credentials for agent and CLI
/etc/halo/i2c-templates/User I2C sensor templates (TOML)
/etc/halo/boards/Custom board definitions (TOML)
/var/lib/halo/rf-config.jsonAuthoritative RF bandwidth configuration
/var/lib/halo/field-tests/Persistent field test CSV recordings
/usr/local/sbin/wpa_supplicantCustom build with mesh support

Do not modify without explicit instruction

Several files carry fragile, load-bearing configuration. Leave them alone unless a task explicitly requires a change:

  • migrations/ — schema; never auto-generate.
  • Cargo.toml — no dependency changes without approval.
  • .cargo/config.toml — cross-compile linker.
  • .github/workflows/ — CI pipeline.
  • build.rs — version stamping.
  • deploy/mesh/mesh-setup-*.sh — the Morse peering fix lives here.
  • Public API route signatures and any *_schema / *_config structs — wire-format implications.

Where to go next