Skip to content

Repository files navigation

NetGrip

English | Español

Website Live demo Release License

Every service on your OpenWrt router, behind a switch your family can press.
NetGrip is a companion panel that runs on the router itself, next to LuCI: WireGuard, guest Wi-Fi, QoS, DNS and more, one click each, with a snapshot, a health check and an automatic rollback if anything goes wrong.

Try the live demo · Visit the website

NetGrip overview: system and WAN cards, a live traffic chart and the ethernet port panel, in light theme

See it before you install it

Why NetGrip?

I kept handing OpenWrt routers to people who only want working Wi-Fi and a VPN. LuCI is a tool for engineers: every toggle asks for a section name, an interface and an option. Vendor portals are friendlier, but they are closed apps that only work on that vendor's firmware. I wanted the machine in between: the real router, behind buttons a relative can press. NetGrip takes the services LuCI already exposes through rpcd and puts a switch in front of each one. Flip it, and NetGrip snapshots the config, applies the change, waits, checks the service came up, and undoes itself if it did not.

Three rules shape it:

  • It lives on the router. One static Go binary with the UI embedded (about 10 MB on disk and ~15 MB of RAM in use, measured on an ARM64 router; ~11.4 MB on mipsle), packaged as a real OpenWrt .apk/.ipk that survives sysupgrade. No container, no extra box, no Node on a router.
  • Safe by construction. Every change goes through an allowlisted executor with a config snapshot and automatic rollback. The panel cannot wander off the beaten path.
  • No new accounts. Login validates against rpcd, the same session LuCI uses; one admin per router, nothing extra to administer. AGPL-3.0, no premium anything.

What you get

An overview that answers "is everything fine?" System health, WAN state and a live traffic chart on one screen, plus an ethernet chassis with per-port state, device names and unmanaged-switch detection. That is the screenshot above.

Clients you can actually manage. Every station with speed and signal, one-click reserved IPs, block actions and per-device bandwidth limits.

Clients page: sortable table with device names, connection type, signal and usage per client

One card per service, each with a real switch. WireGuard (peers with QR codes) and OpenVPN (ready .ovpn downloads), DNS with rebind protection, cake-based SQM with a bufferbloat grade, DDNS, guest and IoT Wi-Fi on their own isolated subnets, port forwarding, and a router/AP mode switch that moves the WAN role without editing network and firewall by hand.

Services page with cards for WireGuard, DDNS, SQM and the visual firewall

System care without the ceremony. Access and session settings, security cards, a first-run wizard, firmware updates through owut/ASU that rebuild the image with your packages inside, and the roaming mesh rendered as a radial graph via usteer.

System page with access settings, security, Router/AP mode and update cards

And more: advanced traffic analysis by application (netifyd) with a 24 h timeline, an optional luci-app-netgrip entry under LuCI > Services, and an ES/EN interface that switches in one click. That is still not the whole list: the website shows every feature, each one with its screenshots at full size.

A NetPulse agent built in. The same binary also reports metrics, WiFi events and clients to NetPulse, so the router shows up labeled as NetGrip in its fleet with no extra install. It is a capability, not a requirement: if you do not use NetPulse, nothing changes.

Get it on your router

Requirements: a 64-bit ARM router (aarch64_cortex-a53, covers MediaTek filogic and Qualcomm ipq807x) or x86_64, running OpenWrt 24.10 or 25.12. The panel listens on port 8090 and logs in with your LuCI credentials.

SSH into the router and run:

wget -qO- https://raw.githubusercontent.com/gnacho/netgrip/main/install.sh | sh

The script picks the right package for the router's architecture and package manager (apk on OpenWrt 25.12+, opkg on 24.10), installs the latest release, enables and starts the service, and prints the panel URL. Prefer to review it first? Read install.sh. To pin a version: NETGRIP_VERSION=vX.Y.Z sh install.sh.

Open http://<router-ip>:8090 and log in with the same username and password you use for LuCI.

Manual install (packages)

Download the right package from the releases page and, on the router:

# OpenWrt 25.12 (apk)
apk add netgrip-<version>-r1-arm64.apk

# OpenWrt 24.10 (ipk)
opkg install netgrip_<version>-1_aarch64_cortex-a53.ipk

/etc/init.d/netgrip enable && /etc/init.d/netgrip start

The postinst adds the binary, the init script and the rc.d link to /etc/sysupgrade.conf, so the panel comes back after a firmware update. The optional luci-app-netgrip package embeds the panel under LuCI > Services in the same way.

Manual install (bare binary) and build from source

A bare binary works but dies on every firmware update; the package is the recommended path.

# Busybox dropbear has no scp; pipe the file instead:
cat netgrip-linux-arm64 | ssh root@<router-ip> "cat > /usr/sbin/netgrip && chmod 755 /usr/sbin/netgrip"
/usr/sbin/netgrip -listen 0.0.0.0 -port 8090

Building from source requires Go 1.24+ and Node 22+:

git clone https://github.com/gnacho/netgrip.git
cd netgrip
cd app && npm ci && cd ..
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o netgrip ./cmd/netgrip
Power-user reference: flags, service and JSON API

Flags (defaults are what most routers want):

Flag Default Description
-listen 0.0.0.0 Address to bind.
-port 8090 Port to listen on. GL.iNet firmware serves its own web UI on 8080, hence the default.
-rpcd-url http://127.0.0.1/ubus rpcd JSON-RPC endpoint for login validation.

The session timeout changes from the UI's Access card (options.main.session_timeout in UCI). The service runs from procd:

/etc/init.d/netgrip status
logread -e netgrip -f
/etc/init.d/netgrip restart

There is a JSON API behind every card, used by the frontend: reads via GET /api/board, /api/system, /api/wan, /api/wifi, /api/lan, /api/dns, /api/usteer, /api/clients, /api/netifyd, /api/dpi/apps, /api/dpi/timeline and /api/nftqos; writes via the matching POST endpoints (/api/wireguard, /api/openvpn, /api/sqm, /api/guestwifi, /api/iotwifi, /api/portforward, /api/netifyd, /api/nftqos) with a { "state": ..., "rolled_back": ..., "status": "applied|rolled_back|failed" } shape. Every write requires a session cookie.

What's next

Done recently: application-level traffic analysis with a per-app timeline, per-device bandwidth limits over nftables, and mipsle support for older hardware. Coming next: a custom packages feed so owut/ASU can keep NetGrip inside your firmware image (#63), and keeping the public demo in step with the panel. Ideas and reports in the issues steer what gets built.

Development

Stack: Go (single static binary) + React 19 + TypeScript + Vite + Tailwind, embedded with go:embed. No external database.

cd app && npm ci
npm run dev      # frontend dev server (see vite.config.ts for the /api proxy)
go build -o netgrip ./cmd/netgrip
go test ./...

The CI builds the frontend, cross-compiles and packages .apk/.ipk with the OpenWrt SDK on every release tag.

License

AGPL-3.0-only. See LICENSE.

Built by gnacho as a personal self-hosted project. If NetGrip is useful to you, a star on GitHub is the way to say thanks; issues and PRs are welcome.

About

Lightweight companion panel for OpenWrt routers - service toggles, WiFi, VPN, and network management with a clean UI

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages