{"id":34658810,"url":"https://github.com/yeraze/meshmonitor","last_synced_at":"2026-05-10T05:02:53.867Z","repository":{"id":316843667,"uuid":"1064181786","full_name":"Yeraze/meshmonitor","owner":"Yeraze","description":"Web tool for monitoring a Meshtastic Node Deployment over TCP/HTTP","archived":false,"fork":false,"pushed_at":"2026-02-11T02:42:28.000Z","size":46310,"stargazers_count":301,"open_issues_count":8,"forks_count":31,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-02-11T06:54:41.355Z","etag":null,"topics":["meshtastic"],"latest_commit_sha":null,"homepage":"https://meshmonitor.org/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Yeraze.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY_AUDIT_REPORT.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":"yeraze","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":null}},"created_at":"2025-09-25T16:54:50.000Z","updated_at":"2026-02-11T02:41:37.000Z","dependencies_parsed_at":"2025-09-27T04:24:44.696Z","dependency_job_id":"07aabc9b-43bc-4188-ba71-5380ed8d4635","html_url":"https://github.com/Yeraze/meshmonitor","commit_stats":null,"previous_names":["yeraze/meshmonitor"],"tags_count":233,"template":false,"template_full_name":null,"purl":"pkg:github/Yeraze/meshmonitor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Yeraze%2Fmeshmonitor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Yeraze%2Fmeshmonitor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Yeraze%2Fmeshmonitor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Yeraze%2Fmeshmonitor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Yeraze","download_url":"https://codeload.github.com/Yeraze/meshmonitor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Yeraze%2Fmeshmonitor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29414343,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-13T06:24:03.484Z","status":"ssl_error","status_checked_at":"2026-02-13T06:23:12.830Z","response_time":78,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["meshtastic"],"created_at":"2025-12-24T18:38:01.289Z","updated_at":"2026-05-10T05:02:53.854Z","avatar_url":"https://github.com/Yeraze.png","language":"TypeScript","funding_links":["https://ko-fi.com/yeraze"],"categories":[],"sub_categories":[],"readme":"# MeshMonitor\n\n[![CI](https://github.com/Yeraze/meshmonitor/actions/workflows/ci.yml/badge.svg)](https://github.com/Yeraze/meshmonitor/actions/workflows/ci.yml)\n[![PR Tests](https://github.com/Yeraze/meshmonitor/actions/workflows/pr-tests.yml/badge.svg)](https://github.com/Yeraze/meshmonitor/actions/workflows/pr-tests.yml)\n[![Docker Image](https://ghcr-badge.egpl.dev/yeraze/meshmonitor/latest_tag?color=%235b4566\u0026ignore=latest,main,dev\u0026label=version\u0026trim=)](https://github.com/Yeraze/meshmonitor/pkgs/container/meshmonitor)\n[![Docker Pulls](https://ghcr-badge.egpl.dev/yeraze/meshmonitor/size?color=%235b4566\u0026tag=latest\u0026label=image%20size\u0026trim=)](https://github.com/Yeraze/meshmonitor/pkgs/container/meshmonitor)\n[![License](https://img.shields.io/github/license/Yeraze/meshmonitor)](https://github.com/Yeraze/meshmonitor/blob/main/LICENSE)\n[![Translation Status](https://hosted.weblate.org/widgets/meshmonitor/-/svg-badge.svg)](https://hosted.weblate.org/engage/meshmonitor/)\n\nA comprehensive web application for monitoring Meshtastic mesh networks over IP. Built with React, TypeScript, and Node.js, featuring a beautiful Catppuccin Mocha dark theme and multi-database support (SQLite, PostgreSQL, MySQL).\n\n![MeshMonitor Interface](docs/images/main.png)\n\n![MeshMonitor Interface](docs/images/channels.png)\n\n## Documentation\n\nFor complete documentation, visit **[meshmonitor.org](https://meshmonitor.org/)**\n\n- **[Getting Started Guide](https://meshmonitor.org/getting-started.html)** - Installation and quick start\n- **[FAQ](https://meshmonitor.org/faq.html)** - Frequently asked questions and troubleshooting\n- **[Configuration](https://meshmonitor.org/configuration/)** - Detailed configuration options\n- **[Development](https://meshmonitor.org/development/)** - Contributing and development setup\n\n## Quick Start\n\nGet MeshMonitor running in **60 seconds**:\n\n```bash\n# 1. Create docker-compose.yml\ncat \u003e docker-compose.yml \u003c\u003c 'EOF'\nservices:\n  meshmonitor:\n    image: ghcr.io/yeraze/meshmonitor:latest\n    ports:\n      - \"8080:3001\"\n    volumes:\n      - meshmonitor-data:/data\n    environment:\n      - MESHTASTIC_NODE_IP=192.168.1.100  # Seeds the first source on first boot; manage more from Dashboard → Sources\n    restart: unless-stopped\n\nvolumes:\n  meshmonitor-data:\nEOF\n\n# 2. Start MeshMonitor\ndocker compose up -d\n\n# 3. Open http://localhost:8080\n```\n\n**Default login:** `admin` / `changeme` (change after first login!)\n\nFor detailed installation instructions, configuration options, and deployment scenarios, see the **[Getting Started Guide](https://meshmonitor.org/getting-started.html)**.\n\n## Proxy Authentication\n\nMeshMonitor supports authentication via reverse proxy headers for seamless single sign-on (SSO) integration with Cloudflare Access, oauth2-proxy, Authelia, Traefik ForwardAuth, and similar solutions.\n\n### Supported Proxies\n\n- **Cloudflare Access** - JWT-based authentication with custom role claims\n- **oauth2-proxy** - Standard OAuth2 proxy with email/groups headers\n- **Generic proxies** - Configurable header-based authentication\n\n### Quick Setup\n\n```yaml\nservices:\n  meshmonitor:\n    image: ghcr.io/yeraze/meshmonitor:latest\n    environment:\n      # Enable proxy authentication\n      - PROXY_AUTH_ENABLED=true\n      - PROXY_AUTH_AUTO_PROVISION=true\n      \n      # Admin detection\n      - PROXY_AUTH_ADMIN_GROUPS=admins,mesh-admins\n      - PROXY_AUTH_ADMIN_EMAILS=admin@example.com\n      \n      # Required: Trust the reverse proxy\n      - TRUST_PROXY=1\n      \n      # Optional: Logout redirect\n      - PROXY_AUTH_LOGOUT_URL=https://auth.example.com/oauth2/sign_out\n```\n\n### Security Requirements\n\n⚠️ **IMPORTANT:** Proxy authentication requires:\n1. MeshMonitor is **NOT directly accessible** (use Docker networks, firewall rules, or VPN)\n2. `TRUST_PROXY` is configured to trust your reverse proxy\n3. Your proxy validates authentication before forwarding requests\n\n### Email Uniqueness Caveat\n\n⚠️ **Email uniqueness is NOT enforced** in the database schema. If multiple users share the same email address, the first match will be used. Ensure your proxy provides unique email addresses for each user.\n\n### Configuration Options\n\n```bash\n# Core settings\nPROXY_AUTH_ENABLED=false              # Enable proxy auth (default: false)\nPROXY_AUTH_AUTO_PROVISION=false       # Auto-create users (default: false)\n\n# Admin detection (at least one recommended)\nPROXY_AUTH_ADMIN_GROUPS=              # Comma-separated admin groups (case-insensitive match)\nPROXY_AUTH_ADMIN_EMAILS=              # Comma-separated admin emails (case-insensitive match)\n\n# Normal-user group gate (optional, see below)\nPROXY_AUTH_NORMAL_USER_GROUPS=        # Comma-separated groups allowed to access (empty = all allowed)\n\n# JWT configuration (for Cloudflare Access)\nPROXY_AUTH_JWT_GROUPS_CLAIM=groups    # Groups claim path (supports Auth0 custom namespaces)\n\n# Custom headers (optional, for non-standard proxies)\nPROXY_AUTH_HEADER_EMAIL=              # Custom email header name\nPROXY_AUTH_HEADER_GROUPS=             # Custom groups header name\n\n# Logout\nPROXY_AUTH_LOGOUT_URL=                # Redirect URL after logout\n\n# Audit logging\nPROXY_AUTH_AUDIT_LOGGING=true         # Log auth events (default: true)\n```\n\n### Cloudflare Access JWT Subset Tokens\n\nCloudflare Access application JWTs contain a **subset** of the full identity — typically `email`, `aud`, `iss`, `sub`. Custom OIDC claims (e.g. Auth0 role claims) are only present when the IdP integration is configured to include them. If your `PROXY_AUTH_JWT_GROUPS_CLAIM` (e.g. `https://your-domain/roles`) is **missing** from the `Cf-Access-Jwt-Assertion` header, MeshMonitor will see empty groups and group-based admin will never trigger.\n\n**To verify:** Decode a real request JWT at [jwt.io](https://jwt.io/) using the `Cf-Access-Jwt-Assertion` header from browser DevTools, and confirm the groups claim exists and its shape. Cloudflare often places IdP custom claims under a `custom` object (e.g. `custom[\"https://your-domain/roles\"]`); official examples may show a flatter layout — your decoded token is the ground truth for your tenant.\n\n**Fallback:** Set `PROXY_AUTH_ADMIN_EMAILS` to an operator email allowlist. MeshMonitor matches emails case-insensitively, so admin works even when the app JWT omits custom IdP claims.\n\nSee: [Cloudflare Application Token](https://developers.cloudflare.com/cloudflare-one/identity/authorization-cookie/application-token/)\n\n### JWT Groups Normalization\n\nMeshMonitor normalizes groups claims from the JWT to handle different IdP formats:\n\n- **String arrays** (`[\"admin\", \"user\"]`) — used as-is\n- **Single strings** (`\"admin\"`) — wrapped into an array\n- **Role objects** (`[{ \"name\": \"admin\" }, { \"name\": \"user\" }]`) — `.name` is extracted\n\nThis handles Auth0 Post-Login Actions that emit role objects instead of plain strings. All group matching (admin groups, normal-user groups) is **case-insensitive**.\n\n### Normal-User Group Gate\n\n`PROXY_AUTH_NORMAL_USER_GROUPS` adds an application-layer group check as a second gate, on top of the reverse proxy's URL-level access control.\n\n**Two-layer model:**\n\nWhen configured, only users whose groups contain at least one value from this list (or who are admins) are allowed. Users who passed the proxy but lack a matching group receive `403 FORBIDDEN_PROXY_GROUP`.\n\nWhen empty (default), all proxy-authenticated users are allowed — the reverse proxy is the only gate.\n\n### Examples\n\n**Cloudflare Access + Auth0 (with normal-user gate):**\n```bash\nPROXY_AUTH_ENABLED=true\nPROXY_AUTH_AUTO_PROVISION=true\nPROXY_AUTH_JWT_GROUPS_CLAIM=https://mydomain.com/roles\nPROXY_AUTH_ADMIN_GROUPS=admins\nPROXY_AUTH_NORMAL_USER_GROUPS=meshmonitor-users\nPROXY_AUTH_ADMIN_EMAILS=operator@example.com\nPROXY_AUTH_LOGOUT_URL=https://yourteam.cloudflareaccess.com/cdn-cgi/access/logout\nTRUST_PROXY=1\nCOOKIE_SECURE=true\n```\n\n**oauth2-proxy:**\n```bash\nPROXY_AUTH_ENABLED=true\nPROXY_AUTH_AUTO_PROVISION=true\nPROXY_AUTH_ADMIN_EMAILS=admin@example.com,superuser@example.com\nPROXY_AUTH_LOGOUT_URL=https://auth.example.com/oauth2/sign_out\nTRUST_PROXY=1\n```\n\n### User Migration\n\nWhen proxy authentication is enabled, existing local users are **automatically migrated** on first login if their email matches:\n- `authMethod` updated to `'proxy'`\n- Password cleared (same behavior as OIDC migration)\n- Admin status updated based on groups\n\n⚠️ **Migration is irreversible without admin intervention.** Migrated users cannot revert to local authentication without a password reset.\n\n## Deployment Options\n\nMeshMonitor supports multiple deployment methods:\n\n- **🐳 Docker** (Recommended) - Pre-built multi-architecture images with auto-upgrade support\n  - [Docker Compose Guide](docs/deployment/DEPLOYMENT_GUIDE.md)\n  - Platforms: amd64, arm64, armv7\n\n- **☸️ Kubernetes** - Helm charts for production clusters\n  - [Helm Chart](helm/meshmonitor/)\n  - GitOps-ready with ArgoCD/Flux support\n\n- **📦 Proxmox LXC** - Lightweight containers for Proxmox VE\n  - [Proxmox LXC Guide](docs/deployment/PROXMOX_LXC_GUIDE.md)\n  - Pre-built templates available\n  - Community-supported alternative\n\n- **🔧 Manual** - Direct Node.js deployment\n  - [Manual Installation Guide](docs/deployment/DEPLOYMENT_GUIDE.md#manual-nodejs-deployment)\n  - For development or custom setups\n\n- **🖥️ Desktop Apps** - Native applications for Windows and macOS\n  - Download from [GitHub Releases](https://github.com/Yeraze/meshmonitor/releases)\n  - Runs as a system tray application\n  - Windows (.exe) and macOS (.dmg) installers available\n\n## Key Features\n\n- **Analysis \u0026 Reports (4.2)** - Cross-source analytical workspace at `/reports`; first report is Solar Monitoring Analysis with auto-detection of solar-powered nodes, production overlay, healthy-level reference lines, and multi-day battery forecast simulation\n- **Multi-Source (4.0)** - Monitor multiple Meshtastic nodes from a single deployment; per-source permissions, schedulers, and Virtual Nodes\n- **Real-time Mesh Monitoring** - Live node discovery, telemetry, and message tracking\n- **Modern UI** - Catppuccin theme with message reactions and threading\n- **Interactive Maps** - Node positions and network topology visualization\n- **Multi-Database Support** - SQLite (default), PostgreSQL, and MySQL via Drizzle ORM\n- **Notifications** - Web Push and Apprise integration for 100+ services\n- **Authentication** - Local, OIDC/SSO, and reverse proxy authentication with RBAC\n- **Security Monitoring** - Encryption key analysis and vulnerability detection\n- **Device Configuration** - Full node configuration UI\n- **Virtual Node Server** - Remote TCP access for Meshtastic Python clients\n- **REST API** - v1 API with Bearer token authentication for external integrations\n- **MeshCore Support** - Optional monitoring for MeshCore mesh networks\n- **Docker Ready** - Pre-built multi-architecture images\n- **One-click Self-Upgrade** - Automatic upgrades from the UI with backup and rollback\n- **System Backup \u0026 Restore** - Complete disaster recovery with automated backups\n\nFor a complete feature list and technical details, visit **[meshmonitor.org](https://meshmonitor.org/)**.\n\n## Development\n\n### Prerequisites\n\n- Node.js 20+\n- Docker (recommended) or local Node.js environment\n- A Meshtastic device with WiFi/Ethernet connectivity\n\n### Local Development\n\n```bash\n# Clone with submodules\ngit clone --recurse-submodules https://github.com/Yeraze/meshmonitor.git\ncd meshmonitor\n\n# Install dependencies\nnpm install\n\n# Configure environment\ncp .env.example .env\n# Edit .env to seed the first source (MESHTASTIC_NODE_IP / MESHTASTIC_TCP_PORT); additional nodes are added later via Dashboard → Sources\n\n# Start development servers\nnpm run dev:full\n```\n\nThis starts both the React dev server (port 5173) and the Express API server (port 3001).\n\n### Available Scripts\n\n**Development:**\n- `npm run dev` - Start React development server\n- `npm run dev:server` - Start Express API server\n- `npm run dev:full` - Start both development servers\n- `npm run build` - Build React app for production\n- `npm run build:server` - Build Express server for production\n\n**Testing \u0026 Quality:**\n- `npm run test` - Run tests in watch mode\n- `npm run test:run` - Run all tests once\n- `npm run test:coverage` - Generate coverage report\n- `npm run lint` - Run ESLint\n- `npm run typecheck` - Run TypeScript compiler checks\n\n## Technology Stack\n\n**Frontend:**\n- React 19 with TypeScript\n- Vite 7 (build tool)\n- CSS3 with Catppuccin theme\n- Translation support crowdsourced by [Weblate](https://hosted.weblate.org/projects/meshmonitor/)\n\n**Backend:**\n- Node.js with Express 5\n- TypeScript\n- Drizzle ORM with SQLite, PostgreSQL, and MySQL drivers\n\n**DevOps:**\n- Docker with multi-stage builds\n- Docker Compose for orchestration\n- GitHub Container Registry for images\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details on:\n\n- Development setup\n- Testing requirements\n- Code style guidelines\n- Pull request process\n- CI/CD workflows\n\nQuick start:\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Make your changes and add tests\n4. Run tests locally (`npm run test:run`)\n5. Commit with conventional commits (`feat: add amazing feature`)\n6. Push and create a Pull Request\n\n## License\n\nThis project is licensed under the BSD-3-Clause License - see the [LICENSE](LICENSE) file for details.\n\n## Community \u0026 Support\n\n- **Discord**: [Join our Discord](https://discord.gg/JVR3VBETQE) - Chat with the community and get help\n- **GitHub Issues**: Report bugs and request features\n- **Documentation**: [meshmonitor.org](https://meshmonitor.org/)\n\n## Third-Party Clients\n\n- **[meshmonitor-chat.el](https://git.andros.dev/andros/meshmonitor-chat.el)** - Emacs chat client using the REST API v1. Channel and DM support, delivery confirmation, emoji reactions, polling.\n\n## Acknowledgments\n\n- [Meshtastic](https://meshtastic.org/) - Open source mesh networking\n- [Catppuccin](https://catppuccin.com/) - Soothing pastel theme\n- [React](https://react.dev/) - Frontend framework\n- [Drizzle ORM](https://orm.drizzle.team/) - TypeScript ORM\n- [better-sqlite3](https://github.com/WiseLibs/better-sqlite3) - SQLite driver\n\n## Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=Yeraze/meshmonitor\u0026type=date\u0026legend=top-left)](https://www.star-history.com/#Yeraze/meshmonitor\u0026type=date\u0026legend=top-left)\n\n---\n\n**MeshMonitor** - Monitor your mesh, beautifully. 🌐✨\n\n_This application is brought to you with help from [Claude Code](https://claude.ai/code)._\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyeraze%2Fmeshmonitor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyeraze%2Fmeshmonitor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyeraze%2Fmeshmonitor/lists"}