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.