Requirements
Update tools
One per device, chosen in the config and compiled in as a feature. The agent does not write firmware itself — it hands the update to a tool that does, and those tools disagree about where the bytes come from, so the update tool owns the transfer.Configuration
The agent reads one TOML file —/etc/nerves-hub-link-agent.toml unless --config or $NERVES_HUB_AGENT_CONFIG points elsewhere. Nothing is read from the environment field by field, so a device’s configuration is one file you can read and diff.
host to your deployment’s device endpoint.
Decisions worth making before shipping
Identity. The device identifier can come from a literal, a file, or a command. On real hardware prefer the hardware’s own serial —{ file = "/sys/firmware/devicetree/base/serial-number" } — or a value on a data partition. A literal in a shipped image makes every device the same device, and an identifier baked into the rootfs is gone after the first update.
Update policy. apply installs whatever arrives, matching NervesHubLink out of the box. ask puts your application in the path.
Reboot policy. Separate from update policy on purpose. An application happy to download at any time may still be unable to reboot right now, and conflating the two forces it to refuse the download in order to protect the reboot.
A shared secret authenticates the product, not the device, so the agent sends a device identifier alongside it. NervesHub registers an identifier it has not seen before — which is what makes one factory image work for a whole fleet, and also means a wrong identifier quietly creates a second device rather than failing.
Bringing a device up
Start with thesandbox update tool. It downloads firmware, verifies its SHA-256, writes it to a file and stops — no block devices, no bootloader, and “reboot” is a log line. That exercises authentication, identity, deployment targeting, progress reporting and reconnects, which is everything except the part that writes to a disk.
RUST_LOG=nerves_hub_link_agent=debug to log the URL it dials and every frame in both directions.
Once it connects, swap the [update_tool] block for fwup or rauc.
Further reading
The agent’s repository carries the detail that only matters on hardware:docs/connecting.md— both endpoints, TLS, and what each authentication failure meansdocs/fwup.mdanddocs/rauc.md— what the image must provide, plus a QEMU rig that boots, rolls back and validatesdocs/deploying.md— cross-compiling, the service user, the systemd unit, and where the identifier has to live to survive a rootfs updatedocs/ipc.md— how your application answers the update and reboot questions

