What the router sends
Dial-home, not a packet tap
luci-app-cpr-dialhome posts this JSON on an interval. A Cloudflare Worker can file it and answer with one command. The same command id is ignored after the first try, so a sticky reply does not upgrade-loop. The router never uploads pcaps, DNS history, or page titles. Sysupgrade runs owut upgrade --force only when owut is installed.
POST /v1/heartbeat
{
"hostname": "CPR-Sandton-Edge",
"release": "25.12.5",
"model": "Cudy WR3000 v1",
"uptime": 1558800,
"load": [0.42, 0.38, 0.31],
"mem_used_pct": 61,
"conntrack": { "count": 372, "max": 16384 },
"flows": [
{ "proto": "tcp", "src": "192.168.1.40", "dst": "102.132.10.8", "dport": 443, "packets": 2104 }
]
}Worker reply
{
"ok": true,
"commands": [
{ "id": "cmd_19", "op": "sysupgrade" }
]
}Packages to install on the router
- luci-theme-cpr — child of Bootstrap. Carbon ground, violet and steel actions, logo beside the hostname. Depends on luci-theme-bootstrap so the menu and login stay intact.
- luci-app-cpr-dialhome — Status → Republic menu, UCI config, procd loop, one-shot test.
Source for both packages is in the project under openwrt/. On a 16 MB WR3000 v1, install the theme and the dial-home script only. Do not add Suricata on that flash.