Skip to content

karamble/diginode-cc

Repository files navigation

DigiNode CC

Command center for Meshtastic mesh networks. Manages nodes, drone detection, WiFi surveillance, geofencing, alerts, and multi-site operations from a single Go binary serving REST API, WebSocket, and embedded React frontend.

Architecture

                    +------------------+
                    |  React Frontend  |
                    |  (web/dist)      |
                    +--------+---------+
                             |
                    +--------+---------+
                    |   Chi HTTP Router |
                    |   165+ REST routes|
                    |   /ws WebSocket   |
                    +--------+---------+
                             |
              +--------------+--------------+
              |              |              |
     +--------+--+   +------+------+  +----+------+
     |  Auth/JWT  |   | Domain Svcs |  | WebSocket |
     |  Middleware |   | (20+ pkgs)  |  |   Hub     |
     +------------+   +------+------+  +-----------+
                             |
              +--------------+--------------+
              |              |              |
     +--------+--+   +------+------+  +----+--------+
     | PostgreSQL |   | Meshtastic  |  | External    |
     |  (pgx)     |   | Dispatcher  |  | Integrations|
     +------------+   +------+------+  +-------------+
                             |              |
                      +------+------+  ADS-B, MQTT,
                      | Serial Port |  ACARS, TAK
                      | (Heltec V3) |
                      +-------------+

Stack: Go 1.25 | PostgreSQL 16 | React 18 + TypeScript + Tailwind | Vite | Docker (2 containers)

Features

  • Mesh Network Management — Node discovery, telemetry (battery, GPS, temperature), online/offline tracking, BLE MAC exposure
  • Bidirectional Chat — Broadcast and DM messaging over Meshtastic mesh, ring buffer history
  • Drone Detection — Real-time tracking with FAA registry enrichment, status classification (FRIENDLY/NEUTRAL/HOSTILE)
  • WiFi Device Inventory — MAC tracking, OUI vendor lookup, RSSI statistics, target promotion
  • Geofencing — Visual polygon editor, entry/exit triggers, alarm integration
  • Alert Rules Engine — Condition matching (MAC, OUI, SSID, RSSI, channel), severity levels, cooldowns
  • Target Tracking — Triangulation from multiple nodes, bearing + RSSI, position history
  • Webhooks — HMAC-SHA256 signed HTTP callbacks with event filtering and wildcard support
  • Command Queue — Rate-limited mesh commands with ACK tracking, retries, and timeout handling
  • Multi-Site — Site-scoped data, per-user site access, MQTT federation between sites
  • ADS-B / ACARS — Aircraft tracking (dump1090 JSON) and ACARS UDP message capture
  • TAK/ATAK — Cursor-on-Target protocol integration
  • Firewall — IP/CIDR blocking, GeoIP, jail tracking
  • Security — JWT auth, TOTP 2FA, bcrypt, account lockout, feature-level RBAC (4 roles), audit logging
  • Self-Update — Git-based version checking with rollback

Quick Start

Docker Compose

cp .env.example .env    # then start — no token required for the default map
docker compose up -d

Open http://localhost:3000 and log in with:

  • Email: admin@example.com
  • Password: admin

Change the default credentials immediately after first login.

Maps render with free OpenStreetMap tiles out of the box — no token needed. If you want the dark "Matrix (JAWG)" style, grab a free token at jawg.io, set JAWG_ACCESS_TOKEN in .env, and switch via the layer control on any map page. Your selection persists across browser reloads and reboots. Operator-supplied env always overrides whatever may be baked into a prebuilt image.

macOS / Docker Desktop note

The bundled docker-compose.yml is Linux-first. USB pass-through to a Heltec/ESP works out of the box on Linux hosts (via privileged: true + /dev:/dev) but does not work on macOS:

  • Docker Desktop runs containers inside a LinuxKit VM, so USB devices plugged into the Mac never appear at /dev/tty.usbserial-* inside the container — SERIAL_DEVICE will not connect to a serial device.
  • privileged: true and the /dev:/dev bind mount only elevate within the VM; neither makes host USB visible.

Recommended on macOS: run the Go binary natively (see Without Docker) and keep only Postgres containerized. The native binary opens /dev/tty.usbserial-* directly via go.bug.st/serial. See the Technical Handbook §12 for the full recipe and notes on advanced workarounds (usbip, ser2net, Colima vz).

Without Docker

Prerequisites: Go 1.25+, Node.js 20+, PostgreSQL 16

# 1. Start PostgreSQL (or use an existing instance)
createdb diginode

# 2. Build frontend + backend
make all

# 3. Run
export JWT_SECRET="your-secret"
export DATABASE_URL="postgres://user:pass@localhost:5432/diginode?sslmode=disable"
make run

The server starts on http://localhost:3000, serving both the API and the built frontend.

Development (hot-reload)

Run the Go backend and Vite dev server separately for live frontend reloading:

# Terminal 1 — Go backend on :3000
export JWT_SECRET="dev-secret"
export DATABASE_URL="postgres://diginode:diginode@localhost:5432/diginode?sslmode=disable"
make build && ./diginode-cc

# Terminal 2 — Vite dev server on :5173 (proxies /api and /ws to :3000)
cd web && npm install && npm run dev

Open http://localhost:5173 for hot-reloading frontend development. API calls and WebSocket connections are automatically proxied to the Go backend.

Environment Variables

Variable Default Description
JWT_SECRET (required) JWT signing secret
DATABASE_URL postgres://diginode:diginode@localhost:5432/diginode?sslmode=disable PostgreSQL connection
LISTEN_ADDR :3000 HTTP listen address
SERIAL_DEVICE (empty) Meshtastic serial port (e.g. /dev/ttyUSB0)
SERIAL_BAUD 115200 Serial baud rate
MQTT_ENABLED false Enable MQTT federation
ADSB_ENABLED false Enable ADS-B aircraft polling
ACARS_ENABLED false Enable ACARS UDP listener
TAK_ENABLED false Enable TAK/ATAK integration
JAWG_ACCESS_TOKEN (empty) Optional map tile auth token from jawg.io. When set, the "Matrix (JAWG)" base layer becomes selectable from the in-map layer control; otherwise maps fall back to free OpenStreetMap tiles.

See the Technical Handbook for the full configuration reference including SMTP, GeoIP, and runtime AppConfig keys.

Building

Makefile Targets

make all                # Build frontend + backend
make build              # Build Go binary only
make build-frontend     # Build React frontend only
make run                # Build + run locally
make test               # Run Go tests
make clean              # Remove binary + dist/

Docker

# Build the image locally
make docker-build

# Container management
make docker-up
make docker-down
make docker-logs

The docker-prod-build / docker-prod-push targets push ARM64 images to karamble/diginode-cc on Docker Hub and are maintainer-only. Contributors building their own images should use make docker-build.

Project Structure

diginode-cc/
├── cmd/diginode-cc/        # Entry point + startup wiring
├── internal/
│   ├── api/                # Chi router, 165+ REST handlers
│   ├── auth/               # JWT + 2FA (TOTP) + bcrypt
│   ├── serial/             # Meshtastic serial framing + encoding
│   ├── meshtastic/         # Packet dispatcher + port routing
│   ├── nodes/              # Mesh node tracking + telemetry
│   ├── drones/             # Drone detection + FAA enrichment
│   ├── chat/               # Mesh messaging + ring buffer
│   ├── commands/           # Command queue + ACK tracking
│   ├── alerts/             # Rule engine + evaluator
│   ├── geofences/          # Polygon geofence engine
│   ├── targets/            # Target tracking + triangulation
│   ├── inventory/          # WiFi device inventory + OUI
│   ├── webhooks/           # HTTP dispatch + HMAC signing
│   ├── ws/                 # WebSocket hub + broadcast
│   ├── database/           # PostgreSQL pool + migrations
│   ├── config/             # Environment + runtime config
│   ├── users/              # User CRUD + invitations + RBAC
│   ├── sites/              # Multi-site management
│   ├── adsb/               # ADS-B aircraft feed
│   ├── acars/              # ACARS UDP listener
│   ├── mqtt/               # MQTT broker federation
│   ├── tak/                # TAK/ATAK COT protocol
│   ├── faa/                # FAA aircraft registry
│   ├── firewall/           # IP blocking + GeoIP
│   ├── alarms/             # Audio/visual alerts
│   ├── exports/            # CSV/JSON export
│   ├── audit/              # Action audit logging
│   ├── permissions/        # Feature-level RBAC
│   ├── mail/               # SMTP delivery
│   └── updates/            # Self-update + rollback
├── web/                    # React frontend (Vite + Tailwind)
│   ├── src/
│   │   ├── pages/          # 17 page components
│   │   ├── stores/         # Zustand state stores
│   │   ├── api/            # REST + WebSocket clients
│   │   └── types/          # TypeScript interfaces
│   └── dist/               # Built frontend (served by Go)
├── docker/
│   └── Dockerfile          # Multi-stage (Go + Node + Alpine)
├── docker-compose.yml
├── Makefile
└── docs/
    └── TECHNICAL_HANDBOOK.md

Meshtastic Integration

Communicates with a Heltec WiFi LoRa 32 V3 (or compatible Meshtastic device) over serial:

  • Protocol: Binary frames (0x94 0xC3 + length + protobuf) with text fallback
  • Handshake: wantConfig on connect triggers full node/config dump
  • Keepalive: Heartbeat every 15s, config refresh every 10 minutes
  • Deduplication: SHA-256 hash with 15s window (512 entry max)
  • Reconnect: Exponential backoff (500ms → 15s, 1.5x, ±20% jitter)
  • Port routing: TEXT_MESSAGE (1), POSITION (3), ADMIN (6), TELEMETRY (67), DETECTION_SENSOR (10)

WebSocket

Connect to GET /ws with JWT token (query param ?token= or Authorization header).

Events: init, drone.telemetry, drone.status, drone.remove, node.update, node.position, node.remove, chat.message, alert, command.update, geofence.event, inventory.update, target.update, adsb.update, acars.message, health, config.update

Frontend

17-page React dashboard:

Page Description
Map Leaflet map with color-coded node/drone/target markers
Nodes Mesh node list with telemetry, online/offline status
Drones Drone detections with FAA data, status management
Chat Broadcast + DM messaging with unread indicators
Targets Entity tracking with triangulation
Inventory WiFi device list with OUI lookup
Alerts Rule configuration + event log
Geofences Visual polygon editor on Leaflet map
Commands Mesh command queue with status tracking
Webhooks HTTP callback configuration + testing
ADS-B Aircraft tracking feed
ACARS ACARS message viewer
Terminal Real-time WebSocket event monitor
Config Application settings
Exports CSV/JSON data export
Users User management + permissions

Documentation

  • Technical Handbook — Full architecture, protocol details, API reference, database schema, deployment guide

Upstream / Related Projects

  • AntiHunter by lukeswitz — the AntiHunter sensor firmware (ESP32-S3 + Heltec V3) that DigiNode CC commands and ingests data from
  • AntiHunter-Command-Control-PRO by TheRealSirHaXalot — the original NestJS Command & Control server that DigiNode CC reimplements in Go
  • meshtastic-gate-sensor — Meshtastic-based gate/perimeter sensor that reports state changes over the same LoRa mesh DigiNode CC operates on

License

This project is licensed under the ISC License.

About

Situational awareness platform for distributed counter-surveillance sensors over LoRa mesh.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors