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.
# 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.
# 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-mesh → gateway-api + halo-agent; mesh is the root dependency.
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-meshreturnsdisabled, no HALO services start on boot. Always verify the enabled state after any hardware change.
Binary paths on device
| Path | Binary |
|---|---|
/usr/local/bin/gateway-api | Main API server (gateway only) |
/usr/local/bin/halo-agent | Node agent (all nodes) |
/usr/local/bin/halo-mesh | Mesh manager (all nodes) |
/usr/local/bin/halo-field | Field diagnostics UI (remote nodes, port 80) |
/usr/local/bin/haloctl | CLI tool |
Configuration and data locations
| Path | Holds |
|---|---|
/etc/halo/config.yaml | Node configuration written by haloctl setup |
/etc/halo/agent-env | API 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.json | Authoritative RF bandwidth configuration |
/var/lib/halo/field-tests/ | Persistent field test CSV recordings |
/usr/local/sbin/wpa_supplicant | Custom 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/*_configstructs — wire-format implications.
Where to go next
- Diagnose a deployed node with haloctl.
- Review the API surface in the gateway API reference.
