# MynetworK - Multi-Source Network Dashboard
MynetworK ![MynetworK](https://img.shields.io/badge/MynetworK-0.13.12-111827?style=for-the-badge) ![Status](https://img.shields.io/badge/Status-PRODUCTION-374151?style=for-the-badge) [![GHCR](https://img.shields.io/badge/GHCR-mynetwork-0ea5e9?style=for-the-badge&logo=docker&logoColor=white)](https://github.com/Erreur32/MynetworK/pkgs/container/mynetwork) ![React](https://img.shields.io/badge/React-19-111827?style=for-the-badge&logo=react&logoColor=38bdf8) ![TypeScript](https://img.shields.io/badge/TypeScript-5.8-111827?style=for-the-badge&logo=typescript&logoColor=60a5fa) ![Docker](https://img.shields.io/badge/Docker-Ready-1f2937?style=for-the-badge&logo=docker&logoColor=38bdf8) [![OSSF Scorecard](https://img.shields.io/ossf-scorecard/github.com/Erreur32/MynetworK?style=for-the-badge&label=Scorecard)](https://scorecard.dev/viewer/?uri=github.com/Erreur32/MynetworK) [![CodeQL](https://img.shields.io/badge/CodeQL-active-brightgreen?style=for-the-badge&logo=github)](https://github.com/Erreur32/MynetworK/security/code-scanning) [![SonarCloud](https://img.shields.io/sonar/quality_gate/Erreur32_MynetworK?server=https%3A%2F%2Fsonarcloud.io&style=for-the-badge&logo=sonarcloud&logoColor=white&label=Sonar)](https://sonarcloud.io/summary/overall?id=Erreur32_MynetworK) ![License](https://img.shields.io/badge/License-MIT-111827?style=for-the-badge&color=111827&logoColor=white)

MynetworK

Unified Freebox + UniFi management + Network Scanner.

**πŸ“– [Read in French (Lire en franΓ§ais)](README.fr.md)**

Powered by
Freebox    Ubiquiti Unifi

**A multi-source network dashboard to manage Freebox, UniFi and Network Scanner** [Installation](#installation) | [Features](#features) | [Configuration](#configuration) | [MCP](#mcp-model-context-protocol) | [Home Assistant](#home-assistant)
--- ## Overview **MynetworK** is a unified dashboard to manage and monitor multiple local network data sources: ![Capture Dashboard](https://github.com/Erreur32/MynetworK/blob/main/img-capture/dashboard.png?raw=true) - **Freebox** - Full management of your Freebox (Ultra, Delta, Pop) - **UniFi Controller** - Monitor and manage your UniFi infrastructure - **Network Scan** - Device discovery and analysis with automatic vendor detection ## Features - πŸ” **User authentication** - JWT system with role management (admin, user, viewer) - πŸ”Œ **Plugin system** - Modular architecture to easily add new data sources - πŸ“Š **Unified dashboard** - Centralized view of all plugin data - πŸ“ **Full logging** - Traceability of all actions with advanced filters - πŸ‘₯ **User management** - Administration interface to manage access - 🐳 **Docker ready** - Simplified deployment with Docker Compose - 🌐 **Internationalization (i18n)** - English (default) and French; language switcher in header. See [Docs/INTERNATIONALIZATION.md](Docs/INTERNATIONALIZATION.md). - πŸ€– **MCP server** - Native [Model Context Protocol](https://modelcontextprotocol.io) server for Freebox, UniFi and the network scanner, LAN-only. See [MCP](#mcp-model-context-protocol) below. > [!TIP] > >
> πŸ–ΌοΈ Click to view other screenshots > > ![Search Ip](https://github.com/Erreur32/MynetworK/blob/main/img-capture/search_ip.png?raw=true) > > ![MyNetwork Scan](https://github.com/Erreur32/MynetworK/blob/main/img-capture/Scan_network.png?raw=true) > > ![Unifi Tab](https://github.com/Erreur32/MynetworK/blob/main/img-capture/unifi_tab.png?raw=true) > > ![Topology](https://github.com/Erreur32/MynetworK/blob/main/img-capture/mynetwork_topology.png?raw=true) > >
> [!NOTE] > A dedicated and **fully functional** version for **Home Assistant** is available here: [https://github.com/Erreur32/HA_mynetwork](https://github.com/Erreur32/HA_mynetwork) > ## Installation ### Prerequisites - Docker and Docker Compose - Local network access to Freebox/UniFi ### docker-compose.yml ```yaml services: mynetwork: image: ghcr.io/erreur32/mynetwork:latest restart: unless-stopped ports: # Dashboard external port (default: 7505) - "${DASHBOARD_PORT:-7505}:3000" environment: # Required secret (no fallback in production) JWT_SECRET: ${JWT_SECRET} # Configuration CONFIG_FILE_PATH: ${CONFIG_FILE_PATH:-/app/config/mynetwork.conf} FREEBOX_HOST: ${FREEBOX_HOST:-mafreebox.freebox.fr} FREEBOX_TOKEN_FILE: /app/data/freebox_token.json # Host metrics access HOST_ROOT_PATH: ${HOST_ROOT_PATH:-/host} # PUBLIC_URL (optional, only with reverse proxy) # PUBLIC_URL: https://dashboard.example.com volumes: # Persistent data (Freebox token, local DB, etc.) - ./data:/app/data # Host metrics (read-only) β€” CPU, RAM, network, ARP table, hostname - /proc:/host/proc:ro - /sys:/host/sys:ro - /etc/hostname:/host/etc/hostname:ro - /etc/hosts:/host/etc/hosts:ro # Network capabilities for scan (ping / ARP) cap_add: - NET_RAW - NET_ADMIN - SETUID - SETGID cap_drop: - ALL healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3000/api/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s ``` > [!IMPORTANT] > **v0.7.80 Breaking Change:** Docker volumes have changed. `/:/host:ro` and `docker.sock` mounts removed for security. See [CHANGELOG](CHANGELOG.md#0780---2026-04-15) for migration instructions. **Launch:** ```bash # Start with Docker Compose docker-compose up -d # View logs docker-compose logs -f # Stop docker-compose down # Update image docker-compose pull docker-compose up -d ``` **Recommendation:** Use the **[.env file](#secure-jwt_secret-configuration)** (`.env` at project root); Docker Compose reads it automatically and injects `JWT_SECRET` into the container. > For more details, see the [Secure JWT_SECRET configuration](#secure-jwt_secret-configuration) section for all configuration methods, security best practices and verification. The dashboard will be available at: - **http://localhost:7505** - from the host machine - **http://SERVER_IP:7505** - from another device on the network
Advanced configuration ### Optional: External configuration file (`.conf`) You can use an external `.conf` file for configuration: 1. **Create the config file:** ```bash cp config/mynetwork.conf.example config/mynetwork.conf # Edit config/mynetwork.conf to your needs ``` 2. **Mount the file in Docker:** Uncomment the line in `docker-compose.yml`: ```yaml volumes: - mynetwork_data:/app/data - ./config/mynetwork.conf:/app/config/mynetwork.conf:ro ``` 3. **Automatic sync:** - On startup, if the `.conf` file exists β†’ import into the database - If the file does not exist β†’ export current configuration 4. **API endpoints:** - `GET /api/config/export` - Export current configuration - `POST /api/config/import` - Import from file - `GET /api/config/file` - Check file status - `POST /api/config/sync` - Manual sync #### Nginx (reverse proxy) If you use **nginx** as a reverse proxy in front of MynetworK, set `PUBLIC_URL` to the public URL (via nginx), not the Docker container URL. **Case 1: Without nginx (direct access)** No `PUBLIC_URL` needed. The app works on the mapped port (e.g. `http://YOUR_IP:7505`). **Case 2: With nginx (reverse proxy)** 1. **Nginx config:** See `Docs/nginx.example.conf` for a full example. 2. **docker-compose.yml:** ```yaml environment: - PUBLIC_URL=http://mynetwork.example.com # Or with HTTPS: # - PUBLIC_URL=https://mynetwork.example.com ``` 3. **Minimal nginx example:** ```nginx server { listen 80; server_name mynetwork.example.com; location / { proxy_pass http://192.168.1.150:7505; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; } } ``` 4. **Benefits of nginx:** SSL/HTTPS (e.g. Let's Encrypt), multiple services on one server, caching, clean URLs. See `Docs/nginx.example.conf` for a complete HTTP/HTTPS setup.
Secure JWT_SECRET configuration **Critical – Security:** The default JWT secret (`change-me-in-production-please-use-strong-secret`) is for **development only**. In production you **must** set the `JWT_SECRET` environment variable to a unique, strong value. #### Why it matters `JWT_SECRET` is used to sign and verify JWT authentication tokens. A weak or default secret allows an attacker to: - Forge valid JWTs and impersonate any user - Access the system without authentication (full admin access) - Compromise all users and their data - Change permissions and access restricted features #### Where it is used `JWT_SECRET` is loaded at server startup in `server/services/authService.ts` from `process.env.JWT_SECRET`. If unset, the default value is used and a warning is logged. The secret is used to sign tokens on login and verify them on authenticated requests. ## Dependencies & supply-chain MynetworK runs entirely on your machine and only talks to the network equipment you configure (Freebox / UniFi / your LAN). It never phones home. The full list of npm packages it ships is in [`package.json`](./package.json); below is what's important to know. ### Runtime β€” backend (Node / Express) | Package | Used for | Notes | | --- | --- | --- | | `express` | HTTP server | Stable, widely audited | | `helmet` | Security headers (CSP, HSTS, X-Frame-Options…) | Defense-in-depth | | `express-rate-limit` | API and write-route throttling, IPv6-aware | | | `compression` | gzip responses | | | `cors` | CORS rules | Tight defaults | | `bcrypt` | Password hashing | | | `jsonwebtoken` | Issue / verify JWTs | See `JWT_SECRET` above | | `better-sqlite3` | Local DB (data, sessions, scans, topology snapshots, manual placements) | Database file lives in the mounted `./data` volume β€” back it up like any DB | | `node-cron` | Daily topology refresh + scheduled scans | Local only, no internet | | `ws` | WebSockets for live UI updates | Listens on the same port as the HTTP server | ### Runtime β€” frontend (React / Vite) | Package | Used for | Notes | | --- | --- | --- | | `react` / `react-dom` | UI framework | | | `react-router-dom` | Client-side routing | | | `zustand` | State management | | | `i18next` / `react-i18next` | English / French translations | | | `recharts` | Bar / line charts on the dashboard | Brings `d3-shape`, `d3-scale`, `d3-array`, etc. as transitive deps | | `@xyflow/react` (React Flow) | Interactive topology graph (`/topology`) | Brings `d3-zoom`, `d3-drag`, `d3-selection`, `d3-interpolate` | | `dagre` | Tree / hierarchical layout for the topology | | | `html-to-image` | PNG / SVG export of the topology | Runs entirely in the browser, no upload | | `jspdf` | PDF export of the topology (A4, raster) | Browser-only | | `lucide-react` | Icon set | | | `react-markdown` + `remark-gfm` | Render the in-app changelog | Sanitised | | `leaflet` + `leaflet.markercluster` | Map view | | | `sonner` | Toast notifications | | ### Security considerations - **No telemetry.** None of these packages call out to a third-party server when the app runs. The Docker container does not need outbound internet to function β€” it only reaches the LAN equipment you configure. - **Export libraries (`html-to-image`, `jspdf`)** are 100 % client-side. Generated PNG / PDF / SVG files stay in your browser; nothing is uploaded. - **Topology stack (`@xyflow/react`, `dagre`)** runs in the browser and on a SQLite-backed snapshot. The snapshot only contains data your active plugins already have access to (Freebox / UniFi devices on your LAN). - **Charts stack (`recharts`)** renders local data only. - **Supply chain.** Dependabot is enabled on this repo and proposes weekly updates. Snyk runs on every push (`Snyk Security` in CI). SonarCloud runs on every push to flag suspicious changes. - **Reproducible builds.** `package-lock.json` is committed. The published Docker image is built from a tagged commit by GitHub Actions (`Build & Push Docker Image` workflow) and pushed to GHCR, so you can verify what's running. - **Updating.** Pull the new image from GHCR (`docker compose pull && docker compose up -d`). The version that's running is shown in the UI footer and at startup in the container logs. If you spot a security issue, please open a private GitHub security advisory rather than a public issue. ## Configuration #### Configuration methods (recommended order) ##### 1. **`.env` file (recommended for production)** Docker Compose automatically reads `.env` at project root. 1. **Generate a strong secret** (at least 32 characters): ```bash # Linux/macOS: openssl rand -base64 32 # Windows PowerShell: [Convert]::ToBase64String((1..32 | ForEach-Object { Get-Random -Maximum 256 })) ``` 2. **Create a `.env` file** at project root: ```bash # .env JWT_SECRET=your_generated_secret_here_minimum_32_chars DASHBOARD_PORT=7505 FREEBOX_HOST=mafreebox.freebox.fr PUBLIC_URL=https://mynetwork.example.com ``` 3. **Restrict permissions:** ```bash chmod 600 .env ``` 4. **Start with Docker Compose:** ```bash docker-compose up -d ``` ##### 2. **`.env` with `--env-file`** ```bash echo "JWT_SECRET=$(openssl rand -base64 32)" > .env.production docker-compose --env-file .env.production up -d ``` #### Verification After startup, check that a custom secret is in use: ```bash docker-compose logs | grep -i "jwt\|secret" ``` If you see a warning like: *"Using default JWT secret. Please set JWT_SECRET..."*, then `JWT_SECRET` was not set correctly. **In the web UI:** Administration β†’ Security β†’ JWT configuration section shows whether the default secret is used. #### Security best practices 1. **Length:** At least **32 characters** (64 recommended) 2. **Random:** Use random data, not predictable passwords 3. **Unique:** Each production instance should have its own secret 4. **Storage:** Restrict `.env` permissions (`chmod 600`), add `.env` to `.gitignore`, use a secrets manager for critical deployments 5. **Rotation:** Change the secret periodically (e.g. every 6–12 months) or if compromise is suspected 6. **Dev vs prod:** Use different secrets for development and production #### JWT secret rotation 1. Generate a new secret: `openssl rand -base64 32` 2. Update `.env`: `JWT_SECRET=new_secret` 3. Restart: `docker-compose restart` 4. All users will need to log in again (existing tokens are invalidated). #### Example `.env` ```bash # .env – Production JWT_SECRET=your_openssl_generated_secret_here DASHBOARD_PORT=7505 FREEBOX_HOST=mafreebox.freebox.fr PUBLIC_URL=https://mynetwork.example.com ```
## First login 1. Open the dashboard (http://localhost:7505 or your server IP). 2. Log in with default credentials: - **Username:** `admin` - **Password:** `admin123` 3. **Change the password immediately after first login.** 4. Configure your plugins in the **Plugins** page.
Features ### Main dashboard - **Multi-source statistics** - Unified view of all plugin data - **Real-time charts** - Throughput, connections, stats - **Network overview** - Global state of your infrastructure ### Plugin management - **Centralized configuration** - UI to configure each plugin - **Enable/disable** - Fine-grained control of each data source - **Connection status** - Check each plugin’s state ### Freebox (plugin) - **Full dashboard** - All Freebox features (WiFi, LAN, Downloads, VMs, TV, Phone) - **Compatibility** - Ultra, Delta, Pop - **Native API** - Official Freebox OS API ### UniFi Controller (plugin) - **Network monitoring** - AP stats, clients, traffic - **Multi-site** - Multiple UniFi sites - **Real-time data** - Automatic stats updates - **Dual API** - Local Controller (node-unifi) and Site Manager API (cloud) - **Stats badges** - System stats in header (throughput, uptime, devices) ### Network Scan (plugin) - **Auto discovery** - Full local network scan (IPs, MAC, hostnames) - **Vendor detection** - Automatic manufacturer identification (Wireshark DB, Freebox/UniFi, or external API) - **Scheduled scans** - Periodic full scan and refresh - **History** - Device evolution over time with charts - **Wireshark vendor DB** - Full integration with Wireshark `manuf` and auto-update - **Priority system** - Hostname/vendor detection order (Freebox, UniFi, Scanner) - **Modern UI** - Interactive table with sort, filters, search and inline hostname editing ### User management (admin) - **Full CRUD** - Create, edit, delete users - **Roles** - Permissions (admin, user, viewer) - **Security** - Passwords hashed with bcrypt ### Activity logs (admin) - **Full traceability** - All actions logged - **Advanced filters** - By user, plugin, action, level, period - **Export** - Log export (planned)
Architecture MynetworK uses a modular architecture: - **React frontend** (TypeScript) - Modern UI - **Express backend** (TypeScript) - REST API and WebSocket - **SQLite database** - Configuration and data storage - **Plugin system** - Extensible architecture for new data sources See [DEV/ARCHITECTURE_PLUGINS.md](DEV/ARCHITECTURE_PLUGINS.md) for details.
Documentation ### For users - **[CHANGELOG.md](CHANGELOG.md)** - Change log and new features ### For developers See **[DEV/README-DEV.md](DEV/README-DEV.md)** for development documentation. **Main docs:** - **[DEV/DOCUMENTATION.md](DEV/DOCUMENTATION.md)** - Documentation index - **[DEV/GUIDE_DEVELOPPEMENT.md](DEV/GUIDE_DEVELOPPEMENT.md)** - Developer guide - **[DEV/ARCHITECTURE_PLUGINS.md](DEV/ARCHITECTURE_PLUGINS.md)** - Plugin architecture **Docs folder ([Docs/](Docs/)):** Setup and production guides (UniFi, Freebox, env vars, Nginx, troubleshooting, reset). Key docs have **English** and **French** versions (see [Docs/README.md](Docs/README.md)).
## Home Assistant > [!IMPORTANT] > A dedicated **fully functional** version for **Home Assistant** is available: > [![HA Repo](https://img.shields.io/badge/Home%20Assistant-Dedicated%20Version-41C483?style=for-the-badge&logo=homeassistant&logoColor=white)](https://github.com/Erreur32/HA_mynetwork) > > - **HACS integration** ready > - **Add-on** support > - **Optimized** for HA Supervisor/Docker > - **Auto-discovery** of Freebox/UniFi networks See [HA Repo](https://github.com/Erreur32/HA_mynetwork) for installation. ## MCP (Model Context Protocol) MynetworK ships a native [MCP](https://modelcontextprotocol.io) server, so an MCP client (e.g. Claude Desktop, Claude Code) can query and control your Freebox, UniFi controller and network scanner directly, no need to go through the web UI. - **LAN-only** - not exposed through the reverse proxy; gated by an IP allowlist (RFC1918 + loopback + Tailscale 100.64.0.0/10) in addition to a dedicated bearer token - **Behind a reverse proxy** - the allowlist checks the TCP peer address and ignores `X-Forwarded-For` by default. If a proxy is the only path to the app and you want the real client checked, list it in `MCP_TRUSTED_PROXIES` (IPv4/CIDR, comma-separated); the same setting covers API tokens and the Prometheus export - **Named, multi-token auth** - separate from the JWT web session; create as many named tokens as you need (one per client/device), each with its own optional expiry, from the admin panel - **Managed from the admin UI** - the "MCP" tab lets you create tokens (shown once), revoke them individually, and shows whether MCP is enabled, the endpoint, active sessions and each token's status/last-used time ### 1. Generate an access token From the admin panel: Settings > MCP > General tab > "New token". Name it, pick a duration (or unlimited), and copy the token shown: it is never displayed again. A CLI fallback also exists, for when the admin panel is unreachable (see [Docs/MCP_DEV_SETUP.md](Docs/MCP_DEV_SETUP.md) for the full explanation): ```bash # Docker (production, default deployment, container name is "mynetwork") docker exec -it -u node mynetwork node_modules/.bin/tsx scripts/mcp-token.ts # Local / dev (bare npm run dev, no container) npm run mcp:token ``` Each CLI run creates a new token named "CLI" with no expiry, without touching tokens created from the admin UI. ### 2. Connect a client The server speaks the standard MCP **Streamable HTTP** transport at `http://:/api/mcp`: swap in the LAN IP and port printed above, and the token, for any client below. **Claude Code (CLI)** ```bash claude mcp add --transport http mynetwork http://:/api/mcp \ --header "Authorization: Bearer " ``` Or add it to a project's `.mcp.json`: ```json { "mcpServers": { "mynetwork": { "type": "http", "url": "http://:/api/mcp", "headers": { "Authorization": "Bearer " } } } } ``` **Claude Desktop** Paid plans (Pro/Max/Team/Enterprise) can add it directly under Settings β†’ Connectors, which speaks Streamable HTTP natively. On the free plan, or for any stdio-only client, bridge it with [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) in `claude_desktop_config.json`: ```json { "mcpServers": { "mynetwork": { "command": "npx", "args": [ "mcp-remote@latest", "http://:/api/mcp", "--header", "Authorization: Bearer " ] } } } ``` **Other agents / clients** Any MCP client with Streamable HTTP support (Cursor, Continue, custom agents built on the MCP SDK, ...) only needs the URL and the bearer header above. For a stdio-only client, the same `mcp-remote` bridge shown for Claude Desktop applies. ### Available tools | Source | Read | Write | |---|---|---| | **Freebox** | system info, connection status, WiFi status/stations, LAN hosts, DHCP config/leases, switch ports, call log, contacts | reboot, toggle WiFi/BSS, add a DHCP static lease | | **UniFi** | devices, clients, WLANs, network config, port forwarding rules, bandwidth report, system info, sites | block/unblock a client, enable/disable a WLAN, restart a device | | **Network scanner** | stats, devices, device by IP, blacklist | trigger/rescan a scan, add a manual IP, rename a host, blacklist add/remove | Write actions are limited to non-destructive operations (nothing deletes data), though some are disruptive by nature (a reboot or a device restart briefly interrupts connectivity β€” tool descriptions flag this explicitly). ### Examples What a tool call looks like from an MCP client, and the kind of response it gets back (values below are illustrative, not real data). **Freebox β€” read: which devices are currently on WiFi** ``` > freebox_get_wifi_stations ``` ```json { "success": true, "result": [ { "mac": "AA:BB:CC:11:22:33", "hostname": "laptop-julien", "ip": "192.168.1.42", "band": "5G", "rssi": -52, "connected_since": 3841 }, { "mac": "AA:BB:CC:44:55:66", "hostname": "iphone-julien", "ip": "192.168.1.57", "band": "2G4", "rssi": -67, "connected_since": 120 } ] } ``` **UniFi β€” write: block a client from the network** ``` > unifi_block_client { "mac": "AA:BB:CC:77:88:99" } ``` ```json { "success": true, "result": { "mac": "AA:BB:CC:77:88:99", "blocked": true } } ``` ## Security - **JWT authentication** - Secure tokens with expiration - **Password hashing** - bcrypt with salt rounds - **Auth middleware** - Protection of sensitive routes - **Action logging** - Full traceability - **Role-based access** - Granular permissions ## Contributing Contributions are welcome. ### Guidelines - Follow existing code style (4 spaces, camelCase, comments in English) - Add TypeScript types for new code - Test changes before submitting - Document new features - Follow project rule files ## License This project is licensed under the MIT License. See [LICENSE](LICENSE) for details. ## Acknowledgments ### Original project This project is heavily inspired by **Freebox OS Ultra Dashboard** by [HGHugo](https://github.com/HGHugo/FreeboxOS-Ultra-Dashboard). Many thanks to the original author for the work that served as a base for MynetworK. **Original project:** [FreeboxOS-Ultra-Dashboard](https://github.com/HGHugo/FreeboxOS-Ultra-Dashboard) ### Others - [Free](https://www.free.fr) for the Freebox and its open API - [Freebox SDK](https://dev.freebox.fr) for API documentation - [Ubiquiti](https://www.ui.com) for UniFi - The open-source community for the libraries used ---
**Made with ❀️ for multi-source network management** **MynetworK - Multi-Source Network Dashboard**