A complete standalone web interface for OpenWrt routers. Not a LuCI theme—pure vanilla JavaScript SPA using OpenWrt's native ubus API.
|
|
opkg update or apk update
opkg install / apk add git git-http ca-bundle nano
git clone https://github.com/benisai/codex-moci.git
cd codex-moci
# Default (no Netify install)
sh scripts/setup-openwrt-router.sh
# Optional: include Netify packages + collector
sh scripts/setup-openwrt-router.sh --with-netify
cp rpcd-acl.json /usr/share/rpcd/acl.d/moci.json
/etc/init.d/rpcd restart
uci set uhttpd.main.home='/www'
uci commit uhttpd
/etc/init.d/uhttpd restartWhat the ACL grants:
- WAN/LAN status display on dashboard
- Bandwidth monitoring
- Device count
- Package list viewing in Software tab
Access at http://192.168.1.1/moci/ and login with your root credentials.
What does the shell script do?:
- installs required packages (
vnstat,nlbwmon,speedtestcpp, etc.) - optionally installs Netify (
netifyd,netcat, Netify collector) when run with--with-netify - deploys web UI to
/www/moci - installs/updates
rpcdACL (/usr/share/rpcd/acl.d/moci.json) - installs backend workers + init scripts:
/usr/bin/moci-netify-collector/usr/bin/moci-ping-monitor/usr/bin/moci-speedtest-monitor/usr/bin/moci-state-sync/usr/bin/moci-device-quarantine/etc/init.d/netify-collector/etc/init.d/ping-monitor/etc/init.d/moci-state-sync/etc/init.d/moci-device-quarantine
- installs
/etc/config/mocidefaults for Monitoring + Netify - enables/restarts
rpcd,uhttpd,netify-collector,ping-monitor,moci-state-sync,vnstat,nlbwmon,netifyd - seeds dashboard traffic settings in UCI (
moci.dashboard.*) with:provider='auto'(prefer Bandix when available, fallback to interface counters)window_seconds='900'(15-minute realtime window)
After running script, open:
http://<router-lan-ip>/moci/
If ACLs changed, log out/in once to refresh your ubus session permissions.
MoCI’s Monitoring and Netify tabs are backed by local services running on the router.
The frontend reads data via ubus (file.read, file.exec, uci.get) and does not do in-browser probing.
Service and scripts
- Init script:
files/ping-monitor.init - Worker:
files/moci-ping-monitor.sh - Runtime command:
/usr/bin/moci-ping-monitor
Data flow
- Procd starts
moci-ping-monitor(ifmoci.ping_monitor.enabled=1). - Script loads config from UCI (
moci.ping_monitor.*). - It pings target (default
1.1.1.1) on interval and appends rows to flat file. - Rows are stored in
output_file(default/tmp/moci-ping-monitor.txt) as:timestamp|target|status|latency|message
- Monitoring UI reads
/tmp/moci-ping-monitor.txtand renders:- status cards
- timeline
- recent samples table
Config keys (/etc/config/moci)
config ping 'ping_monitor'option enabled '1'option target '1.1.1.1'option interval '60'option threshold '100'option timeout '2'option output_file '/tmp/moci-ping-monitor.txt'option max_lines '2000'
Service control
/etc/init.d/ping-monitor enable
/etc/init.d/ping-monitor start
/etc/init.d/ping-monitor restartWorker script
- Worker:
files/moci-speedtest-monitor.sh - Runtime command:
/usr/bin/moci-speedtest-monitor
Data flow
- UI stores daily schedule in UCI (
moci.speedtest_monitor.*). - UI applies/removes a managed root cron entry (
# MOCI_SPEEDTEST_MONITOR). - Cron runs
/usr/bin/moci-speedtest-monitor --onceonce per day. - Script runs configured speedtest binary (
moci.speedtest_monitor.bin, default/usr/bin/speedtest) with fallback auto-detection, parses download/upload, and appends rows to:/tmp/moci-speedtest-monitor.txt
- Monitoring UI reads this file and renders:
- last download/upload cards
- daily up/down line graph
- recent speedtest sample table
Row format
timestamp|status|download_mbps|upload_mbps|server|message
Config keys (/etc/config/moci)
config speedtest 'speedtest_monitor'option enabled '1'option run_hour '3'option run_minute '15'option bin '/usr/bin/speedtest'option output_file '/tmp/moci-speedtest-monitor.txt'option max_lines '365'
Service and scripts
- Init script:
files/netify-collector.init - Worker:
files/moci-netify-collector.sh - Runtime command:
/usr/bin/moci-netify-collector
Data flow
- Procd starts
moci-netify-collector(ifmoci.collector.enabled=1). - Collector reads UCI config (
moci.collector.*). - It connects to Netify stream via netcat (
nc host port) with inactivity timeout (stream_timeout) so stale sockets are reconnected automatically. type:"flow"events are inserted into a local SQLite database (flow_rawtable).- Netify UI reads recent rows via
sqlite3and renders:- flow/app/device counters
- top applications
- recent flows
- collector and file status
Default database file
/tmp/moci-netify.sqlite
Config keys (/etc/config/moci)
config netify 'collector'option enabled '1'option host '127.0.0.1'option port '7150'option db_path '/tmp/moci-netify.sqlite'option retention_rows '500000'option stream_timeout '45'
Service control
/etc/init.d/netify-collector enable
/etc/init.d/netify-collector start
/etc/init.d/netify-collector restartService and scripts
- Init script:
files/device-quarantine.init - Worker:
files/moci-device-quarantine.sh - Runtime command:
/usr/bin/moci-device-quarantine
Behavior
- Service checks both:
moci.features.quarantinemoci.quarantine.enabled
- If enabled, it scans DHCP leases on interval.
- New (previously unseen) MACs are quarantined by adding firewall reject rules for:
lan -> lanlan -> wan
- Quarantine matching is MAC-based (
src_mac). - Rules use prefix
moci_quarantine_and appear in MoCI Network -> Quarantine.
Config keys (/etc/config/moci)
config quarantine 'quarantine'option enabled '0'(default disabled)option interval '15'option leases_file '/tmp/dhcp.leases'option state_file '/tmp/moci-quarantine-known.txt'option rule_prefix 'moci_quarantine_'
MoCI keeps high-write data in /tmp to reduce flash wear, and checkpoints to persistent storage on a timer.
Service and scripts
- Init script:
files/moci-state-sync.init - Worker:
files/moci-state-sync.sh - Runtime command:
/usr/bin/moci-state-sync
What is checkpointed
- Netify SQLite DB (
moci.collector.db_path, default/tmp/moci-netify.sqlite) - Ping monitor file (
moci.ping_monitor.output_file, default/tmp/moci-ping-monitor.txt) - Speedtest file (
moci.speedtest_monitor.output_file, default/tmp/moci-speedtest-monitor.txt) - MoCI UCI config (
/etc/config/moci) vnstatruntime directory (/var/lib/vnstat) when present
Flow
- On boot, service restores previous checkpoint back into runtime locations.
- It installs a managed cron entry (
# MOCI_STATE_SYNC). - Cron runs
moci-state-sync saveat interval from UCI. - On service stop, it performs a final save.
Config keys (/etc/config/moci)
config state_backup 'state_backup'option backup_time '720'(minutes; 12 hours default)option state_dir '/overlay/moci-state'
Manual control
/etc/init.d/moci-state-sync enable
/etc/init.d/moci-state-sync start
/usr/bin/moci-state-sync save
/usr/bin/moci-state-sync restore
/usr/bin/moci-state-sync sync-cronWhen using the root index.html demo wrapper (/index.html), Monitoring and Netify data are mocked in-browser:
- ping history/service responses are simulated
- Netify flow data is simulated
This lets you test UI behavior locally without running router services.
The dashboard card TRAFFIC HISTORY (VNSTAT) is powered by vnstat JSON output.
- Dashboard module runs
file.execon:/usr/bin/vnstat --json(primary)/usr/sbin/vnstat --json(fallback)
- It parses
interfaces[].trafficarrays from JSON. - User chooses period from the card:
HOURLY->traffic.hour/traffic.hoursDAILY->traffic.day/traffic.daysMONTHLY->traffic.month/traffic.months
- UI keeps the last 12 points for the selected period.
- It renders grouped bars on canvas:
- Download (
rx) - Upload (
tx)
- Download (
- Data refresh is throttled to about once per minute while on dashboard.
- Default period is HOURLY.
- Period buttons switch the chart immediately.
- If
vnstatis unavailable or no data exists, the chart shows a fallback message. - Card visibility is controlled by feature flag:
moci.features.traffic_history
vnstatinstalled and collecting traffic.- Optional LuCI integration package:
luci-app-vnstat(orluci-app-vnstat2depending on repo).
uci set moci.features.traffic_history='1' # show
uci set moci.features.traffic_history='0' # hide
uci commit mociThe dashboard card NETWORK ACTIVITY keeps an in-memory rolling window (default 15 minutes).
- Default source behavior is
moci.dashboard.provider='auto':- tries
luci.bandix(getMetrics/getStatus) when Bandix is installed - falls back to local interface counters from
/proc/net/dev
- tries
- Top hero DOWNLOAD/UPLOAD values show:
- current rate
- cumulative total
config traffic 'dashboard'
option provider 'auto' # auto | interface | bandix
option window_seconds '900' # 60..3600uci set moci.dashboard.provider='bandix'
uci set moci.dashboard.window_seconds='900'
uci commit mociIf you use Bandix data in MoCI, ensure luci-app-bandix and backend bandix versions match (0.12.x with 0.12.x).
Uses OpenWrt's native authentication system. Same security model as LuCI:
| Feature | MoCI | LuCI |
|---|---|---|
| Authentication | ubus sessions | ubus sessions |
| Authorization | rpcd ACLs | rpcd ACLs |
All operations validated server-side. No privilege escalation paths.
Auto-deploy on save:
# QEMU VM
pnpm dev
# Physical router
pnpm dev:physical 192.168.1.1Project structure:
moci/
├── index.html - Application shell
├── app.css - Styling
└── js/
├── core.js - Core functionality
└── modules/ - Feature modules (dashboard, network, system, vpn, services)
Adding features:
const [status, result] = await this.ubusCall('system', 'info', {});Chrome 90+ • Firefox 88+ • Safari 14+ • Any modern browser
MIT




