Cada servicio de tu router OpenWrt, detrás de un interruptor que
puede pulsar tu familia.
NetGrip es un panel companion que corre en el propio router, junto a LuCI:
WireGuard, WiFi de invitados, QoS, DNS y más, un clic cada uno, con
snapshot, comprobación de salud y rollback automático si algo sale mal.
Prueba la demo en vivo · Visita la web
- demo.netgrip.cloudless.club corre el panel real con datos de ejemplo: pulsa cada interruptor, abre cada tarjeta, no se aplica nada en ningún sitio.
- netgrip.cloudless.club lista todas y cada una de las funcionalidades, pantalla a pantalla, con el razonamiento detrás de cada una.
Seguía entregándoles routers OpenWrt a personas que solo quieren WiFi y una VPN que funcionen. LuCI es una herramienta para ingenieros: cada toggle te pide una sección, una interfaz y una opción. Los portales del fabricante son más amables, pero son apps cerradas que solo funcionan en su firmware. Yo quería la máquina intermedia: el router de verdad, detrás de botones que pueda pulsar un familiar. NetGrip toma los servicios que LuCI ya expone vía rpcd y les pone un interruptor delante. Lo pulsas, y NetGrip hace snapshot de la config, aplica el cambio, espera, comprueba que el servicio levantó, y se deshace solo si no fue así.
Tres reglas lo dan forma:
- Vive en el router. Un único binario Go estático con la UI embebida
(unos 10 MB en disco y ~15 MB de RAM en uso, medidos en un router ARM64;
~11,4 MB en mipsle), empaquetado como
.apk/.ipkreal de OpenWrt que sobrevive al sysupgrade. Sin contenedores, sin caja extra, sin Node en un router. - Seguro por construcción. Cada cambio pasa por un executor con allowlist, con snapshot de config y rollback automático. El panel no puede salirse del camino trazado.
- Sin cuentas nuevas. El login se valida contra rpcd, la misma sesión que usa LuCI; un admin por router, nada extra que administrar. AGPL-3.0, sin premium de ningún tipo.
Un resumen que responde a "¿está todo bien?" Salud del sistema, estado WAN y tráfico en vivo en una sola pantalla, más un chasis ethernet con estado por puerto, nombres de dispositivo y detección de switches no gestionados. Es la captura de arriba.
Clientes que se pueden gestionar de verdad. Cada estación con velocidad y señal, reservas de IP en un clic, bloqueo y límites de ancho de banda por dispositivo.
Una tarjeta por servicio, cada una con su interruptor real. WireGuard
(peers con código QR) y OpenVPN (.ovpn listo para descargar), DNS con
protección rebind, SQM basado en cake con nota de bufferbloat, DDNS, WiFi
de invitados e IoT en subredes aisladas, reenvío de puertos y un conmutador
router/AP que mueve el rol WAN sin editar network y firewall a mano.
Cuidado del sistema sin ceremonia. Acceso y sesión, tarjetas de seguridad, asistente de primer arranque, actualizaciones de firmware vía owut/ASU que reconstruyen la imagen con tus paquetes dentro, y la malla de roaming dibujada como grafo radial vía usteer.
Y más: análisis de tráfico avanzado por aplicación (netifyd) con
timeline de 24 h, la entrada opcional luci-app-netgrip bajo LuCI >
Servicios, e interfaz ES/EN que cambia en un clic. Y esto todavía no es
todo: en la web están todas las
funcionalidades, cada una con sus
capturas a tamaño real.
Agente de NetPulse integrado. El mismo binario reporta métricas, eventos WiFi y clientes a NetPulse: el router aparece etiquetado como NetGrip en su flota sin instalar nada más. Es una capacidad adicional, no un requisito: si no usas NetPulse, nada cambia.
MQTT y Home Assistant, si los quieres. Opcional y desactivado por defecto:
apúntalo a un broker MQTT y Home Assistant descubre el router solo. Publica el
estado en netgrip/<router>/state y crea 23 entidades: 17 sensores (CPU,
núcleo más cargado, temperatura, memoria, uptime, modo, versión, clientes
totales/WiFi/cable/débil, señal WiFi mínima y media, y tráfico de entrada y
salida de la red local), 4 interruptores (WiFi de invitados, banIP, IPv6 y SQM)
y 2 botones (recargar los feeds de banIP y reiniciar). Los interruptores y
botones actúan: Home Assistant manda la orden por netgrip/<router>/command/...
y el router contesta en netgrip/<router>/result.
Se configura desde la tarjeta MQTT de la página Sistema, o escribiendo
/etc/netgrip/mqtt.env (permisos 600). La tarjeta prueba la conexión antes
de guardar, y un servidor de NetPulse puede enviarle la configuración del
broker al router (aplicada con el mismo snapshot-y-rollback que cualquier
otro cambio). Sin TLS: pensado para un broker de tu red local. No se
publica nada hasta que lo actives.
Asistentes de IA (MCP), si los quieres. NetGrip puede exponer un endpoint local de MCP para que un asistente de IA consulte el estado del router en su propio vocabulario. Está desactivado por defecto y la primera tanda de tools es de solo lectura:
- Actívalo y pon un token:
uci set netgrip.mcp='mcp'; uci set netgrip.mcp.enabled=1; uci set netgrip.mcp.token=<aleatorio largo>; uci commit netgrip(el primer comando crea la sección; unuci set netgrip.mcp.enabled=1directo en una instalación nueva falla con "Invalid argument"). - Apunta tu cliente MCP a
http://<router>:8080/mcp(o el puerto que use el panel) y envía el token comoAuthorization: Bearer <token>.
El endpoint nunca acepta la cookie de sesión del navegador, responde 404
mientras está desactivado y tiene rate limit por IP (60 peticiones/minuto
por defecto, ajustable con uci set netgrip.mcp.rate_per_min=<n>). Los
tools (server_status, list_clients, wireless_status, wan_status,
multiwan_status, list_leases, list_devices) leen las mismas sondas y
cachés que el panel, y cada llamada queda en el log.
Requisitos: un target amd64, ARM64, ARMv5/6/7, MIPS little-endian o MIPS big-endian compatible, con OpenWrt 24.10 o 25.12. El instalador consulta al gestor de paquetes la arquitectura exacta del router y elige el paquete y ABI Go genérico correspondientes. El panel escucha en el puerto 8090 y entra con tus credenciales de LuCI.
SSH al router y ejecuta:
wget -qO- https://raw.githubusercontent.com/gnacho/netgrip/main/install.sh | shEl script elige el paquete correcto para la arquitectura y el gestor del
router (apk en OpenWrt 25.12+, opkg en 24.10), instala la última
release, habilita y arranca el servicio, e imprime la URL del panel.
¿Prefieres revisarlo antes? Lee install.sh. Para fijar
versión: NETGRIP_VERSION=vX.Y.Z sh install.sh.
Abre http://<ip-del-router>:8090 y entra con el mismo usuario y contraseña
que usas en LuCI.
Instalación manual (paquetes)
Descarga el paquete correcto desde la página de releases y, en el router:
# OpenWrt 25.12 (apk; el sufijo es la arquitectura genérica del binario)
apk add netgrip-<version>-r1-arm64.apk
# OpenWrt 24.10 (ipk; el sufijo es la arquitectura exacta del paquete)
opkg install netgrip_<version>-1_aarch64_cortex-a53.ipk
/etc/init.d/netgrip enable && /etc/init.d/netgrip startEl postinst añade el binario, el init y el enlace rc.d a
/etc/sysupgrade.conf, así que el panel vuelve tras una actualización de
firmware. El paquete opcional luci-app-netgrip incrusta el panel bajo LuCI
Servicios de la misma forma.
Instalación manual (binario suelto) y build desde fuente
Un binario suelto funciona, pero muere en cada actualización de firmware; el paquete es el camino recomendado.
# dropbear de busybox no tiene scp; mejor por pipe:
cat netgrip-linux-arm64 | ssh root@<ip-del-router> "cat > /usr/sbin/netgrip && chmod 755 /usr/sbin/netgrip"
/usr/sbin/netgrip -listen 0.0.0.0 -port 8090Compilar desde fuente requiere Go 1.24+ y Node 22+:
git clone https://github.com/gnacho/netgrip.git
cd netgrip
cd app && npm ci && npm run build && cd ..
VERSION=dev sh deploy/build-binaries.shEse comando compila el frontend una vez y genera binarios genéricos para amd64,
ARM64, ARMv5/6/7, mipsle y mips en dist/. Puedes pasar uno o más targets,
como linux-armv7 o linux-mipsle, para compilar solo esos binarios.
Referencia para curiosos: flags, servicio y API JSON
Flags (los defaults sirven para casi cualquier router):
| Flag | Default | Descripción |
|---|---|---|
-listen |
0.0.0.0 |
Dirección a la que bindear. |
-port |
8090 |
Puerto. El firmware GL.iNet sirve su propia web en el 8080, de ahí el default. |
-rpcd-url |
http://127.0.0.1/ubus |
Endpoint JSON-RPC de rpcd para validar el login. |
El timeout de sesión se cambia desde la tarjeta Acceso de la UI
(options.main.session_timeout en UCI). El servicio corre con procd:
/etc/init.d/netgrip status
logread -e netgrip -f
/etc/init.d/netgrip restartDetrás de cada tarjeta hay una API JSON, la misma que usa el frontend:
lecturas por 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 y /api/nftqos; escrituras por los
POST correspondientes (/api/wireguard, /api/openvpn, /api/sqm,
/api/guestwifi, /api/iotwifi, /api/portforward, /api/netifyd,
/api/nftqos) con forma
{ "state": ..., "rolled_back": ..., "status": "applied|rolled_back|failed" }.
Toda escritura exige cookie de sesión.
Reciente: integración con Home Assistant sobre MQTT (estado, sensores e interruptores/botones que actúan, descubiertos automáticamente), siete ABI Go genéricos por release de amd64 a MIPS, e interfaz bilingüe cuyo idioma del documento sigue al idioma activo. Lo siguiente: un feed de paquetes propio para que owut/ASU conserve NetGrip dentro de tu imagen de firmware (#63) y mantener la demo pública al día del panel. Las ideas y reportes en los issues dirigen qué se construye.
Stack: Go (binario estático único) + React 19 + TypeScript + Vite + Tailwind,
embebido con go:embed. Sin base de datos externa.
cd app && npm ci
npm run dev # dev server del frontend (el proxy /api está en vite.config.ts)
go build -o netgrip ./cmd/netgrip
go test ./...En cada tag de release, el CI compila y precomprime el frontend una sola vez,
cross-compila siete binarios para ABI Go genéricos y los distribuye en paquetes
.apk/.ipk específicos de cada target mediante el SDK de OpenWrt. El resumen
de la release muestra el tamaño de cada binario y del frontend comprimido.
AGPL-3.0-only. Ver LICENSE.
Construido por gnacho como proyecto personal self-hosted. Si NetGrip te sirve, una estrella en GitHub es la forma de dar las gracias; issues y PRs son bienvenidos.


