openwrt-iac / uapi / docs / 1.2.1 / Building the uapi APK
The version comes from a single source: the VERSION file at the repo root (semver, e.g. 1.0.0-rc1). The OpenWrt Makefile translates that to apk-style PKG_VERSION (hyphens become underscores), and make stage ships a copy to /usr/share/uapi/VERSION so main.uc and /healthz report the same string.
This document walks through producing uapi-<version>-r1.apk for OpenWrt 25.12.4 using the official OpenWrt SDK. Substitute the actual version from the VERSION file (or the release page) wherever you see <version> below.
/usr/share/uapi/main.uc uhttpd ucode-prefix entry point
/usr/share/uapi/raw.uc generic /raw/<package>/<id> handler
/usr/share/uapi/lib/*.uc shared modules
/usr/share/uapi/resources/*.uc curated resource modules
/usr/share/uapi/openapi.json generated OpenAPI 3.1 spec
/usr/bin/uapi-token token CLI
/etc/config/uapi conffile (mode 0600, conffile-marked)
/etc/uci-defaults/99-uapi one-shot install hook
/etc/config/uapi is marked as a conffile, so upgrades preserve operator-created tokens.
Dependencies (pulled in automatically):
uhttpd uhttpd-mod-ucode ucode
ucode-mod-ubus ucode-mod-uci ucode-mod-fs ucode-mod-digest ucode-mod-log
SDK_URL=https://downloads.openwrt.org/releases/25.12.4/targets/x86/64/openwrt-sdk-25.12.4-x86-64_gcc-14.3.0_musl.Linux-x86_64.tar.zst
mkdir -p build/sdk
curl -L "$SDK_URL" | tar --use-compress-program=unzstd -xvf - -C build/sdk --strip-components=1
Adjust targets/x86/64 for your target architecture if cross-compiling for something other than x86_64. uapi is pure ucode (PKGARCH:=all), so the resulting .apk is architecture-independent.
make openapi # regenerate build/openapi.json
make stage # populate build/openwrt/uapi/files/
cd build/sdk
./scripts/feeds update -a
./scripts/feeds install -a
# Add our package as a local feed entry. The Makefile expects to find
# ./files relative to itself, so symlink the package dir we just staged.
ln -s ../../openwrt/uapi package/uapi
make defconfig
make package/uapi/compile V=s
The output .apk lands at bin/packages/all/base/uapi-<version>-r1.apk (or whatever the SDK reports at the end of the build).
scp bin/packages/all/base/uapi-*.apk root@<router>:/tmp/
ssh root@<router> 'apk add /tmp/uapi-<version>-r1.apk'
ssh root@<router> 'uapi-token create --name first --scope "*:rw"'
The CLI prints the cleartext bearer to stdout exactly once. Save it.
The postinst script runs /etc/uci-defaults/99-uapi immediately on live installs (not chroots/INSTROOT builds) and then deletes the script. That single run:
uhttpd.main.ucode_prefix already lists /api/v1=/usr/share/uapi/main.uc. If so, exits cleanly.After that, https://<router>/api/v1/healthz is reachable.
apk remove uapi triggers the prerm hook, which:
ucode_prefix entry from uhttpd.main.The token store at /etc/config/uapi is preserved (conffile semantics). To wipe it: rm /etc/config/uapi after removal.