<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>OTA Updater</title><link>https://carlosprados.github.io/ota-updater/index.html</link><description>A Go library and server for over-the-air updates on constrained networks — built for NB-IoT links at 20–60 kbps with high latency and frequent disconnects, where a naive “download the new binary” strategy is not viable.
go get github.com/carlosprados/ota-updater Apache-2.0. Both halves are importable Go packages, not just binaries.
What it actually gives you Binary deltas bsdiff + zstd. Ship a patch instead of the whole binary — usually one to two orders of magnitude less downlink. Signed everything Ed25519 over (target hash, transferred bytes hash). The agent rejects a corrupt payload after downloading it but before patching, which on NB-IoT is the save that matters. A/B slots + rollback The new binary is staged in the inactive slot. A watchdog confirms health after the swap; a version that fails to come up twice is marked bad permanently. Multi-artifact One server, N components × M versions × K architectures. Content-addressed storage means two tracks shipping identical bytes share one file. Never strands a device If the server cannot build a patch — factory-flashed unit, sideloaded build, corrupt slot — it ships the whole compressed target instead. Bounded resources RAM is capped by explicit byte budgets regardless of history size or artifact count. Disk is reclaimed by a retention sweeper. Two transports HTTP/JSON and CoAP/CBOR, mirroring the same resource paths. The agent falls back between them once per cycle. The shape of the system flowchart TB subgraph OPS["Operator / CI"] BUILD["build artifact"] end subgraph SERVER["update-server"] REG["Registry&lt;br/&gt;&lt;i&gt;which hash is current&lt;br/&gt;per artifact&lt;/i&gt;"] STORE["Store&lt;br/&gt;&lt;i&gt;content-addressed:&lt;br/&gt;hash.bin, from_to.delta.zst&lt;/i&gt;"] MAN["Manifester&lt;br/&gt;&lt;i&gt;signs manifests&lt;/i&gt;"] RET["Retention&lt;br/&gt;&lt;i&gt;reclaims disk&lt;/i&gt;"] end subgraph DEVICE["Device (edge-agent)"] UPD["Updater"] SLOTS["A/B slots&lt;br/&gt;+ watchdog"] end BUILD --&gt;|"publish"| REG REG --&gt;|"target hash"| MAN STORE &lt;--&gt;|"bytes"| MAN REG -.-&gt;|"live set"| RET RET -.-&gt;|"deletes stale"| STORE UPD --&gt;|"1 · heartbeat"| MAN MAN --&gt;|"2 · signed manifest"| UPD UPD --&gt;|"3 · GET delta"| STORE STORE --&gt;|"4 · bytes"| UPD UPD --&gt; SLOTS SLOTS --&gt;|"5 · report"| SERVER classDef srv fill:#38bdf82e,stroke:#38bdf8,stroke-width:1px classDef dev fill:#4ade802e,stroke:#4ade80,stroke-width:1px class REG,STORE,MAN,RET srv class UPD,SLOTS dev The division of labour is worth stating plainly, because it is the design decision everything else follows from:</description><generator>Hugo</generator><language>en-US</language><atom:link href="https://carlosprados.github.io/ota-updater/index.xml" rel="self" type="application/rss+xml"/><item><title>Architecture</title><link>https://carlosprados.github.io/ota-updater/architecture/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://carlosprados.github.io/ota-updater/architecture/index.html</guid><description>Components, the content-addressed store, and why the split between bytes and bookkeeping matters.</description></item><item><title>Protocol</title><link>https://carlosprados.github.io/ota-updater/protocol/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://carlosprados.github.io/ota-updater/protocol/index.html</guid><description>Wire messages, the two transfer modes, and the exact sequence of an update cycle.</description></item><item><title>Server</title><link>https://carlosprados.github.io/ota-updater/server/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://carlosprados.github.io/ota-updater/server/index.html</guid><description>Artifacts, the admin control plane, retention, and how RAM stays bounded.</description></item><item><title>Agent</title><link>https://carlosprados.github.io/ota-updater/agent/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://carlosprados.github.io/ota-updater/agent/index.html</guid><description>A/B slots, the watchdog, rollback, and embedding the agent as a library.</description></item><item><title>Operations</title><link>https://carlosprados.github.io/ota-updater/operations/index.html</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://carlosprados.github.io/ota-updater/operations/index.html</guid><description>Running it: deployment, observability, resource limits.</description></item></channel></rss>