openwrt-iac

OpenWrt, but ready for your IaC tool

uci already gave OpenWrt the rarest thing in the embedded-Linux world: a single, stable config interface every daemon speaks. What it doesn't give you is a way to drive it from outside the box. This org closes the gap, without forking OpenWrt.

All projects MIT-licensed - signed APK feed - signed tags - OpenWrt 25.12 +

Where we start: uci is the right base

OpenWrt has a property few other systems have. Every long-lived daemon (network, firewall, dhcp, wireless, dropbear, uhttpd, unbound, sqm, snmpd, lldpd, ...) reads its config from the same place (/etc/config/) through the same library (libuci), reloads via the same procd triggers, and exposes the same shape (typed sections, named or anonymous, with options and lists). LuCI, command-line operators, and on-box scripts all share one ABI. That's the foundation we build on.

What that foundation is missing, for any IaC tool that wants to drive the box from somewhere else:

Each of those gaps is solvable without changing the daemon, the kernel, or upstream uci itself. The work is to land precise pieces that close one gap each, ship them as standard OpenWrt apk packages, and keep them inside the existing system's grain.

The projects

uapi - the HTTP control plane

Native, zero-footprint REST API. Runs inside the existing uhttpd process via ucode (no daemon to supervise). Translates HTTP verbs into uci/ubus calls. Atomic transactions with snapshot-rollback, per-package locks, optimistic concurrency via ETags + If-Match, bearer tokens with hierarchical scopes, idempotency keys, signed releases with SPDX SBOM. 34 curated resources at 2.1 plus a generic raw passthrough for the long tail.

project page - install - OpenAPI reference - github

unbound-uci-ext - close a deliberate uci gap

unbound's interface:, outgoing-interface:, and friends are deliberately kept out of upstream's uci because users are expected to hand-edit /etc/unbound/unbound_srv.conf. This package exposes those (plus a verbatim passthrough for anything else) as uci so the rest of the toolchain (including uapi + Terraform) can drive them. Generator writes managed regions into the seam files and restarts unbound only when content actually changed.

github - apk add unbound-uci-ext

terraform-provider-uapi - the IaC consumer

Reference IaC client. Drives every uapi endpoint, honours ETags for drift detection, uses the same scope tree for least-privilege tokens. Lives in its own repo on Terraform Registry with its own version cadence; uapi's wire surface was shaped around what this provider needs.

registry - github

Design constraints (we keep these)

Stay on the grain

Use ucode, uhttpd, ubus, uci, procd, apk-tools the way OpenWrt intends. No parallel-universe daemon, no replacement init, no shadow config tree. If our project requires you to disable a standard OpenWrt piece to make ours work, the design is wrong.

Negligible footprint

Target hardware is 32MB-RAM SoHo routers. Runtime overhead, memory, and storage stay close to zero. uapi runs inside an existing process and adds no idle cost. Extension packages are shell + uci, no compiled code.

No forks of OpenWrt

We don't fork the unbound package because it doesn't surface a field we want; we ship an extension package alongside it. We don't fork netifd because a resource doesn't exist; we curate it through uapi. Upstream stays upstream.

Production-grade releases

GPG-signed git tags. Signed APK feed (RSA-4096, key rotated publicly when needed). Reproducible builds across target arches (PKGARCH:=all where possible). SPDX SBOM attached to each release. Multi-arch CI verifies the package works on every target SDK we ship for.

Get started

  1. Trust the feed signing key
    curl -fsSL https://openwrt-iac.github.io/feed/uapi-feed.pub.pem \
        | tee /etc/apk/keys/uapi-feed.pub.pem > /dev/null
  2. Add the feed
    echo 'https://openwrt-iac.github.io/feed/packages/all/uapi/packages.adb' \
        > /etc/apk/repositories.d/uapi.list
    apk update
  3. Install whichever pieces you need
    apk add uapi              # HTTP control plane
    apk add unbound-uci-ext   # if you run unbound

One feed line, every openwrt-iac package. See /uapi/install/ for the full install + first-token walkthrough.

Contributing

The bar for a new project under this org: it closes a real IaC gap for a real OpenWrt setup, stays inside the design constraints above, and is willing to live as a separate signed-and-released apk in this feed. New extension packages are particularly welcome where upstream OpenWrt has a deliberate uci gap that's costing operators hand-edits.

To get a package into the apk feed: open a PR against openwrt-iac/openwrt-iac.github.io's feed.yml with a one-line entry pointing at your source repo. Requirements + release expectations are in that repo's README.

About

openwrt-iac is not affiliated with the OpenWrt project or its maintainers. It started as the work of a single operator solving a specific problem on their own network, shared in the open in the hope it is useful to others with similar needs. OpenWrt is a trademark of its respective owners.