14 KiB
MQTT Provisioning Integration
Diese Anleitung beschreibt die Integration des MQTT Provisioning Systems (aus mosquitto-automation) in die Location Tracker App.
🎯 Übersicht
Die Integration vereint zwei vormals separate Systeme:
- mosquitto-automation: Device Provisioning und MQTT Credential Management
- location-tracker-app: GPS Tracking Visualisierung mit OwnTracks
Was wurde integriert?
✅ MQTT Credentials Management - Direkt im Admin Panel ✅ ACL (Access Control List) Management - Feine Kontrolle über Topic-Berechtigungen ✅ Mosquitto Sync - Password & ACL Files werden automatisch generiert ✅ MQTT Subscriber - Direkte Verarbeitung von OwnTracks Messages (kein n8n mehr nötig) ✅ Docker Compose Setup - All-in-One Deployment
📋 Features
Admin Panel: MQTT Provisioning
Route: /admin/mqtt
Device Provisioning
- Erstelle MQTT Credentials für registrierte Devices
- Automatische Generierung von Username & Passwort
- Passwörter werden mit
mosquitto_passwdgehasht - Default ACL Regel:
owntracks/[device-id]/#(readwrite)
Credentials Management
- Liste aller provisionierten Devices
- Enable/Disable MQTT Zugriff pro Device
- Passwort Regenerierung
- Credentials löschen (inkl. ACL Regeln)
ACL Management
- Custom Topic Patterns definieren
- Berechtigungen:
read,write,readwrite - Wildcard Support mit
# - Regeln pro Device verwalten
Mosquitto Sync
- "Zu Mosquitto Syncen" Button im Admin Panel
- Generiert
/mosquitto/config/password.txt - Generiert
/mosquitto/config/acl.txt - Sendet SIGHUP an Mosquitto Container (Config Reload)
- Zeigt ausstehende Änderungen an
🗄️ Datenbankschema
Neue Tabellen
mqtt_credentials
CREATE TABLE mqtt_credentials (
id INTEGER PRIMARY KEY AUTOINCREMENT,
device_id TEXT NOT NULL UNIQUE, -- Referenz zu Device Tabelle
mqtt_username TEXT NOT NULL UNIQUE,
mqtt_password_hash TEXT NOT NULL, -- Mosquitto-kompatible Hash
enabled INTEGER DEFAULT 1, -- 0 = disabled, 1 = enabled
created_at TEXT,
updated_at TEXT,
FOREIGN KEY (device_id) REFERENCES Device(id) ON DELETE CASCADE
);
mqtt_acl_rules
CREATE TABLE mqtt_acl_rules (
id INTEGER PRIMARY KEY AUTOINCREMENT,
device_id TEXT NOT NULL,
topic_pattern TEXT NOT NULL, -- z.B. "owntracks/device10/#"
permission TEXT NOT NULL, -- read | write | readwrite
created_at TEXT,
FOREIGN KEY (device_id) REFERENCES Device(id) ON DELETE CASCADE
);
mqtt_sync_status
CREATE TABLE mqtt_sync_status (
id INTEGER PRIMARY KEY CHECK (id = 1), -- Singleton
pending_changes INTEGER DEFAULT 0,
last_sync_at TEXT,
last_sync_status TEXT, -- success | error: ...
created_at TEXT,
updated_at TEXT
);
Migration
# Datenbanken initialisieren
npm run db:init
# MQTT Tabellen hinzufügen
node scripts/add-mqtt-tables.js
🚀 Installation & Setup
Voraussetzungen
- Docker & Docker Compose
- Node.js 20+ (für lokale Entwicklung)
1. Repository Setup
cd location-tracker-app
# Dependencies installieren
npm install
# .env Datei erstellen
cp .env.example .env
2. Environment Variables
Bearbeite .env:
# MQTT Configuration
MQTT_BROKER_URL=mqtt://mosquitto:1883
MQTT_ADMIN_USERNAME=admin
MQTT_ADMIN_PASSWORD=dein-sicheres-passwort
MOSQUITTO_PASSWORD_FILE=/mosquitto/config/password.txt
MOSQUITTO_ACL_FILE=/mosquitto/config/acl.txt
MOSQUITTO_CONTAINER_NAME=mosquitto
# NextAuth
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=<generiere mit: openssl rand -base64 32>
# Verschlüsselung für SMTP Passwords
ENCRYPTION_KEY=<generiere mit: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))">
3. Docker Compose Start
# Build und Start
docker-compose up -d
# Logs verfolgen
docker-compose logs -f
# Status prüfen
docker-compose ps
Die App läuft auf: http://localhost:3000
Mosquitto MQTT Broker: mqtt://localhost:1883
4. Admin Zugang
Default Credentials:
- Username:
admin - Password:
admin123
⚠️ Ändere das Passwort nach dem ersten Login!
🔧 Entwicklung
Lokale Entwicklung (ohne Docker)
# 1. Mosquitto extern starten (oder Docker Compose nur Mosquitto)
docker run -d -p 1883:1883 -p 9001:9001 \
-v $(pwd)/mosquitto.conf:/mosquitto/config/mosquitto.conf \
-v mosquitto_data:/mosquitto/data \
eclipse-mosquitto:2
# 2. .env anpassen
MQTT_BROKER_URL=mqtt://localhost:1883
# 3. Datenbanken initialisieren
npm run db:init
node scripts/add-mqtt-tables.js
# 4. App starten
npm run dev
Neue MQTT Credentials testen
# Mit mosquitto_sub testen
mosquitto_sub -h localhost -p 1883 \
-u "device_10_abc123" \
-P "dein-generiertes-passwort" \
-t "owntracks/10/#" \
-v
# OwnTracks Message simulieren
mosquitto_pub -h localhost -p 1883 \
-u "device_10_abc123" \
-P "dein-generiertes-passwort" \
-t "owntracks/10/device" \
-m '{"_type":"location","lat":52.5200,"lon":13.4050,"tst":1234567890,"batt":85,"vel":5.2}'
📡 MQTT Subscriber
Der MQTT Subscriber läuft automatisch beim App-Start und verarbeitet OwnTracks Messages.
Implementierung
- Service:
lib/mqtt-subscriber.ts - Startup:
instrumentation.ts(Next.js Hook) - Topic:
owntracks/+/+ - Datenbank: Schreibt direkt in
locations.sqlite
OwnTracks Message Format
{
"_type": "location",
"tid": "XX",
"lat": 52.5200,
"lon": 13.4050,
"tst": 1234567890,
"batt": 85,
"vel": 5.2,
"acc": 10,
"alt": 50
}
Logs
# Docker Logs
docker-compose logs -f app
# Du solltest sehen:
# ✓ Connected to MQTT broker
# ✓ Subscribed to owntracks/+/+
# ✓ Location saved: device10 at (52.52, 13.405)
🔐 Sicherheit
Mosquitto Authentication
- Keine Anonymous Connections:
allow_anonymous false - Password File: Mosquitto-kompatible Hashes (SHA512)
- ACL File: Topic-basierte Access Control
Best Practices
- Starke Admin Passwörter: Ändere
MQTT_ADMIN_PASSWORDin.env - Device Passwörter: Auto-generierte Passwörter haben 128 Bit Entropie
- ACL Regeln: Gib Devices nur Zugriff auf ihre eigenen Topics
- Docker Socket: Container benötigt Zugriff für Mosquitto Reload (optional)
ACL Beispiele
# Device darf nur in eigenes Topic schreiben
user device_10_abc123
topic readwrite owntracks/10/#
# Device mit zusätzlichem Read-only Topic
user device_11_xyz789
topic readwrite owntracks/11/#
topic read status/#
# Admin hat vollen Zugriff
user admin
topic readwrite #
🐛 Troubleshooting
Problem: "Mosquitto configuration reloaded" fehlgeschlagen
Symptom: Nach Sync kommt Warnung "Could not reload Mosquitto automatically"
Lösung: Docker Socket Zugriff fehlt. Entweder:
# Option 1: Manuelle Mosquitto Neustart
docker-compose restart mosquitto
# Option 2: Docker Socket in docker-compose.yml freigeben (bereits konfiguriert)
volumes:
- /var/run/docker.sock:/var/run/docker.sock
Problem: MQTT Subscriber verbindet nicht
Debug Steps:
# 1. Prüfe Mosquitto läuft
docker-compose ps mosquitto
# 2. Prüfe Mosquitto Logs
docker-compose logs mosquitto
# 3. Prüfe App Logs
docker-compose logs app | grep MQTT
# 4. Teste MQTT Verbindung manuell
mosquitto_sub -h localhost -p 1883 -u admin -P admin -t '#'
Problem: Password Hash falsch
Symptom: Authentication failed im Mosquitto Log
Lösung: mosquitto_passwd Tool muss im Container verfügbar sein (ist im Dockerfile installiert)
# Im Container testen
docker exec -it location-tracker-app mosquitto_passwd -h
Problem: ACL Regeln funktionieren nicht
Debug:
# ACL File prüfen
docker exec -it location-tracker-app cat /mosquitto/config/acl.txt
# Mosquitto Logs auf "Access denied" prüfen
docker-compose logs mosquitto | grep -i denied
📊 API Endpoints
MQTT Credentials
# Liste aller Credentials
GET /api/mqtt/credentials
# Credential für Device abrufen
GET /api/mqtt/credentials/{device_id}
# Neue Credentials erstellen
POST /api/mqtt/credentials
Content-Type: application/json
{
"device_id": "10",
"auto_generate": true
}
# Credentials aktualisieren
PATCH /api/mqtt/credentials/{device_id}
Content-Type: application/json
{
"regenerate_password": true,
"enabled": true
}
# Credentials löschen
DELETE /api/mqtt/credentials/{device_id}
ACL Rules
# ACL Regeln für Device
GET /api/mqtt/acl?device_id=10
# Neue ACL Regel erstellen
POST /api/mqtt/acl
Content-Type: application/json
{
"device_id": "10",
"topic_pattern": "owntracks/10/#",
"permission": "readwrite"
}
# ACL Regel löschen
DELETE /api/mqtt/acl/{rule_id}
Mosquitto Sync
# Sync Status abrufen
GET /api/mqtt/sync
# Sync triggern
POST /api/mqtt/sync
Alle Endpoints erfordern Admin-Authentifizierung (Role: ADMIN).
🔄 Migration von mosquitto-automation
Wenn du bereits Devices in mosquitto-automation hast:
Automatische Migration (TODO)
# Script erstellen das aus der alten DB liest
node scripts/migrate-from-mosquitto-automation.js \
--old-db /pfad/zu/mosquitto-automation/data/devices.db
Manuelle Migration
- Exportiere Devices aus alter DB:
SELECT id, name, username, password_hash, permissions
FROM devices
WHERE active = 1;
- Erstelle Devices im neuen System über Admin Panel
- Provisioniere MQTT Credentials manuell
- Importiere ACL Regeln
📚 Architektur
Komponenten
┌─────────────────────────────────────────────────────┐
│ Location Tracker App (Next.js) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────┐ │
│ │ Admin Panel │ │ MQTT Service │ │ API │ │
│ │ /admin/mqtt │ │ Subscriber │ │ Routes │ │
│ └──────────────┘ └──────────────┘ └──────────┘ │
│ │ │ │ │
│ └──────────────────┴────────────────┘ │
│ │ │
│ ┌────▼────┐ │
│ │ SQLite │ │
│ │ DB │ │
│ └────┬────┘ │
│ │ │
│ ┌────▼────────┐ │
│ │ Mosquitto │ │
│ │ Sync Service│ │
│ └────┬────────┘ │
└─────────────────────────┼──────────────────────────┘
│
┌───────────▼───────────┐
│ Mosquitto Broker │
│ │
│ • password.txt │
│ • acl.txt │
└───────────┬───────────┘
│
┌───────────▼───────────┐
│ GPS Tracking │
│ Devices │
│ (OwnTracks) │
└───────────────────────┘
Datei-Struktur
location-tracker-app/
├── app/
│ ├── admin/
│ │ └── mqtt/
│ │ └── page.tsx # MQTT Provisioning UI
│ └── api/
│ └── mqtt/
│ ├── credentials/ # Credentials Management
│ ├── acl/ # ACL Management
│ └── sync/ # Mosquitto Sync
├── lib/
│ ├── mqtt-db.ts # MQTT Datenbank Operations
│ ├── mqtt-subscriber.ts # MQTT Message Processing
│ ├── mosquitto-sync.ts # Config File Generation
│ └── startup.ts # Service Initialization
├── scripts/
│ └── add-mqtt-tables.js # Datenbank Migration
├── docker-compose.yml # Docker Setup
├── Dockerfile # App Container
├── mosquitto.conf # Mosquitto Config
└── instrumentation.ts # Next.js Startup Hook
✨ Vorteile der Integration
Vorher (Separate Systeme)
GPS Device → MQTT → n8n → HTTP API → location-tracker-app → UI
↓
mosquitto-automation (separate)
Probleme:
- n8n als zusätzliche Dependency
- Zwei separate Admin Panels
- Keine zentrale User/Device Verwaltung
- Komplexes Setup
Nachher (Integriert)
GPS Device → MQTT → location-tracker-app → UI
↓
(integriertes Provisioning)
Vorteile: ✅ Ein Admin Panel für alles ✅ Direkte MQTT Verarbeitung (schneller) ✅ Einfaches Docker Compose Setup ✅ Zentrale Datenbank ✅ Weniger Dependencies
🎉 Fertig!
Die Integration ist komplett. Du kannst jetzt:
- Devices verwalten unter
/admin/devices - MQTT Credentials provisionieren unter
/admin/mqtt - ACL Regeln definieren im MQTT Panel
- Zu Mosquitto syncen mit einem Klick
- GPS Tracking visualisieren auf der Hauptseite
Bei Fragen oder Problemen: Siehe Troubleshooting oder check die Logs.
Happy Tracking! 🚀📍