- Agent: WAU registry config check (include/exclude URLs), pending updates count - Backend: /wau/compliance per customer, /wau/compliance/summary all customers - Frontend: compliance badge in customer list, compliance panel in WAU tab - config.js: no longer gitignored (secrets-free, reads from env/window.__RMM_CONFIG__) - vite.config.js: reads backend URL from .env instead of hardcoded value - .env.example added for clean setup
RMM Frontend
React + Vite + TailwindCSS Web-Frontend fuer das OPNsense RMM System.
Eckdaten
| Server | your-backend (Debian 13, Nginx) |
| Tech | React 18, Vite, TailwindCSS, Recharts, Zustand, lucide-react |
| Theme | Dark mit Orange-Akzent, komplett deutsch |
| Auth | JWT Login (8h Token) |
| Default-Login | admin / YOUR_PASSWORD |
| Backend | https://your-backend:8443 |
Seiten
| Seite | Route | Beschreibung |
|---|---|---|
| Login | /login |
JWT Login |
| Dashboard | / |
Status-Kacheln, Agent-Liste, AgentPanel per Klick |
| Firewalls | /agents |
Suchbare Tabelle, AgentPanel mit Tabs, Hinzufuegen/Loeschen |
| Tunnel | /tunnels |
Globale Tunnel-Uebersicht ueber alle Firewalls |
| Firmware | /firmware |
Multi-Plattform Upload, Agent-Update-Trigger |
| Kunden | /customers |
CRUD Kundenverwaltung |
| Einstellungen | /settings |
Benutzerverwaltung, Passwoerter aendern |
AgentPanel Tabs
Das Side-Panel oeffnet sich per Klick auf eine Firewall (Dashboard oder Firewalls-Seite):
| Tab | Inhalt |
|---|---|
| Uebersicht | Hardware, OS, Uptime, CPU/RAM, Lizenz (Business Edition) |
| Interfaces | Netzwerk-Interfaces mit IP, MAC, Status, RX/TX |
| Dienste | Laufende Services mit Status-Badge |
| Tunnel | Quick-Buttons (WebGUI, SSH, Custom), aktive Tunnel |
| VPN | WireGuard-Instanzen mit Transfer-Statistiken |
| WireGuard | Peer-Management (CRUD), Client-Config mit Copy-Button |
| Routen | Routing-Tabelle |
| DHCP | Aktive Leases mit Suche (IP, MAC, Hostname) |
| Zertifikate | Karten-Layout mit Ablaufdatum und Fortschrittsbalken |
| Backups | Config-Backup erstellen, Liste, Download als XML |
| Agent | Version, Agent-ID, Update-Button, Remote-Befehle |
API Endpoints
Alle Aufrufe gehen ueber den API Client (src/api/client.js).
Base-URL wird ueber VITE_API_URL oder Nginx-Proxy konfiguriert.
Auth: JWT Bearer Token im Authorization Header.
Authentifizierung
POST /api/v1/auth/login Login (username, password) → JWT Token
GET /api/v1/auth/me Eigene Benutzerdaten
Beispiel:
# Login
curl -sk -X POST https://your-backend:8443/api/v1/auth/login \
-d '{"username":"admin","password":"YOUR_PASSWORD"}'
# → {"token":"eyJhbG...","user":{"id":1,"username":"admin"}}
# Eigene Daten
curl -sk -H "Authorization: Bearer <TOKEN>" \
https://your-backend:8443/api/v1/auth/me
Agents (Firewalls)
GET /api/v1/agents Alle Agents auflisten
GET /api/v1/agents/{id} Agent + Systemdaten abrufen
DELETE /api/v1/agents/{id} Agent loeschen
POST /api/v1/agents Firewall pre-registrieren
GET /api/v1/agents/{id}/events Agent-Events (limit=N)
PUT /api/v1/agents/{id}/customer Kunden zuordnen
DELETE /api/v1/agents/{id}/customer Kundenzuordnung entfernen
Beispiele:
# Alle Agents
curl -sk -H "Authorization: Bearer <TOKEN>" \
https://your-backend:8443/api/v1/agents
# Agent-Details mit Systemdaten
curl -sk -H "Authorization: Bearer <TOKEN>" \
https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee
# Firewall pre-registrieren
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
https://your-backend:8443/api/v1/agents \
-d '{"name":"OPN.intra.kunde.de","customer_id":1}'
# Agent loeschen
curl -sk -H "Authorization: Bearer <TOKEN>" -X DELETE \
https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887
# Events (letzte 50)
curl -sk -H "Authorization: Bearer <TOKEN>" \
"https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/events?limit=50"
# Kunden zuordnen
curl -sk -H "Authorization: Bearer <TOKEN>" -X PUT \
https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/customer \
-d '{"customer_id":1}'
Kunden (Customers)
GET /api/v1/customers Alle Kunden
POST /api/v1/customers Neuen Kunden anlegen
PUT /api/v1/customers/{id} Kunden aktualisieren
DELETE /api/v1/customers/{id} Kunden loeschen
GET /api/v1/customers/{id}/agents Agents eines Kunden
Beispiele:
# Kunden anlegen
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
https://your-backend:8443/api/v1/customers \
-d '{"number":"K05001","name":"Beispiel GmbH"}'
# Kunden aktualisieren
curl -sk -H "Authorization: Bearer <TOKEN>" -X PUT \
https://your-backend:8443/api/v1/customers/1 \
-d '{"number":"K05001","name":"Beispiel AG"}'
# Agents eines Kunden
curl -sk -H "Authorization: Bearer <TOKEN>" \
https://your-backend:8443/api/v1/customers/1/agents
Benutzer (Users)
GET /api/v1/users Alle Benutzer
POST /api/v1/users Neuen Benutzer anlegen
PUT /api/v1/users/{id}/password Passwort aendern (min. 6 Zeichen)
DELETE /api/v1/users/{id} Benutzer loeschen
Beispiele:
# Benutzer anlegen
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
https://your-backend:8443/api/v1/users \
-d '{"username":"operator","password":"Sicher!123"}'
# Passwort aendern
curl -sk -H "Authorization: Bearer <TOKEN>" -X PUT \
https://your-backend:8443/api/v1/users/1/password \
-d '{"password":"NeuesPasswort!123"}'
Metriken (TimescaleDB)
GET /api/v1/agents/{id}/metrics Rohe Metriken
GET /api/v1/agents/{id}/metrics/summary Aggregierte Metriken
Verfuegbare Metriken: cpu_usage, memory_used_percent, memory_used_bytes, memory_total_bytes, uptime_seconds, disk_used_percent, disk_used_bytes, interface_rx_bytes, interface_tx_bytes, gateway_rtt_ms, gateway_loss_percent
Beispiele:
# CPU letzte 24h
curl -sk -H "Authorization: Bearer <TOKEN>" \
"https://your-backend:8443/api/v1/agents/6beb8dfd.../metrics?metric=cpu_usage"
# RAM mit Zeitraum
curl -sk -H "Authorization: Bearer <TOKEN>" \
"https://your-backend:8443/api/v1/agents/6beb8dfd.../metrics?metric=memory_used_percent&from=2026-03-01T00:00:00Z&to=2026-03-01T23:59:59Z"
# 5-Minuten-Durchschnitte
curl -sk -H "Authorization: Bearer <TOKEN>" \
"https://your-backend:8443/api/v1/agents/6beb8dfd.../metrics/summary?metric=cpu_usage&bucket=5+minutes"
Config-Backups
POST /api/v1/agents/{id}/backup Backup jetzt ausloesen
GET /api/v1/agents/{id}/backups Alle Backups auflisten
GET /api/v1/agents/{id}/backups/{id} Backup herunterladen (?format=xml)
GET /api/v1/agents/{id}/backups/latest Neuestes Backup
DELETE /api/v1/agents/{id}/backups/{id} Backup loeschen
GET /api/v1/agents/{id}/backups/diff Diff (?a=ID&b=ID)
Beispiele:
# Backup ausloesen
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
https://your-backend:8443/api/v1/agents/6beb8dfd.../backup
# Backups auflisten
curl -sk -H "Authorization: Bearer <TOKEN>" \
https://your-backend:8443/api/v1/agents/6beb8dfd.../backups
# Als XML herunterladen
curl -sk -H "Authorization: Bearer <TOKEN>" \
"https://your-backend:8443/api/v1/agents/6beb8dfd.../backups/latest?format=xml" \
-o config-backup.xml
# Diff zwischen zwei Backups
curl -sk -H "Authorization: Bearer <TOKEN>" \
"https://your-backend:8443/api/v1/agents/6beb8dfd.../backups/diff?a=1&b=3"
Tunnel
POST /api/v1/agents/{id}/tunnel Tunnel oeffnen
GET /api/v1/agents/{id}/tunnels Aktive Tunnel auflisten
DELETE /api/v1/agents/{id}/tunnel/{tid} Tunnel schliessen
Beispiele:
# SSH-Tunnel
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
https://your-backend:8443/api/v1/agents/e92e87a6.../tunnel \
-d '{"target_host":"127.0.0.1","target_port":22}'
# → {"tunnel_id":"abc123","proxy_port":10000,...}
# Dann: ssh -p 10000 root@your-backend
# WebGUI-Tunnel (OPNsense Port 4444)
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
https://your-backend:8443/api/v1/agents/e92e87a6.../tunnel \
-d '{"target_host":"127.0.0.1","target_port":4444}'
# Im Browser: https://your-backend:10001/
# PVE WebGUI-Tunnel (Proxmox Port 8006)
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
https://your-backend:8443/api/v1/agents/3f0a83a2.../tunnel \
-d '{"target_host":"127.0.0.1","target_port":8006}'
# Aktive Tunnel
curl -sk -H "Authorization: Bearer <TOKEN>" \
https://your-backend:8443/api/v1/agents/e92e87a6.../tunnels
# Tunnel schliessen
curl -sk -H "Authorization: Bearer <TOKEN>" -X DELETE \
https://your-backend:8443/api/v1/agents/e92e87a6.../tunnel/abc123
WireGuard Peer-Management
GET /api/v1/agents/{id}/wireguard/peers Alle Peers auflisten
POST /api/v1/agents/{id}/wireguard/peers Neuen Peer anlegen
DELETE /api/v1/agents/{id}/wireguard/peers/{uuid} Peer loeschen
Beispiele:
# Peer anlegen (Auto: Keypair, naechste freie IP, Endpoint)
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
https://your-backend:8443/api/v1/agents/6beb8dfd.../wireguard/peers \
-d '{"name":"VPN_MUELLER","allowed_ips":"0.0.0.0/0","dns":"10.172.100.210"}'
# → {peer_config: "[Interface]\nPrivateKey=...\n[Peer]\n...", ...}
# Alle Peers
curl -sk -H "Authorization: Bearer <TOKEN>" \
https://your-backend:8443/api/v1/agents/6beb8dfd.../wireguard/peers
# Peer loeschen
curl -sk -H "Authorization: Bearer <TOKEN>" -X DELETE \
https://your-backend:8443/api/v1/agents/6beb8dfd.../wireguard/peers/89c10e2d-148e-11f1-a7af-7c5a1c6c7b73
Remote-Befehle (Exec)
POST /api/v1/agents/{id}/exec Befehl ausfuehren
Beispiel:
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
https://your-backend:8443/api/v1/agents/e92e87a6.../exec \
-d '{"command":"uptime","timeout":30}'
# → {"data":{"output":"10:30AM up 45 days, ..."}, "status":"ok"}
Updates
POST /api/v1/agents/{id}/update-check Verfuegbare Updates pruefen
POST /api/v1/agents/{id}/update Normales Update (Core + Packages)
POST /api/v1/agents/{id}/major-update Major-Upgrade (2-Phasen)
POST /api/v1/agents/{id}/reboot Reboot
Beispiele:
# Update-Check
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
https://your-backend:8443/api/v1/agents/e92e87a6.../update-check
# Update mit Reboot
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
https://your-backend:8443/api/v1/agents/e92e87a6.../update \
-d '{"reboot":true}'
# Major-Update Phase 1
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
https://your-backend:8443/api/v1/agents/e92e87a6.../major-update \
-d '{"version":"26.1","reboot":true}'
Firmware / Agent-Update
GET /api/v1/firmware Alle Firmware-Versionen
POST /api/v1/firmware/upload?version=X&platform=Y Binary hochladen
GET /api/v1/firmware/download?platform=Y Binary herunterladen (Updater)
POST /api/v1/agents/{id}/request-update Update-Flag setzen
DELETE /api/v1/agents/{id}/request-update Update-Flag zuruecksetzen
POST /api/v1/agents/request-update-all Alle Agents updaten
Beispiele:
# Firmware-Info
curl -sk -H "Authorization: Bearer <TOKEN>" \
https://your-backend:8443/api/v1/firmware
# Firmware hochladen (FreeBSD)
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
"https://your-backend:8443/api/v1/firmware/upload?version=1.0.3&platform=freebsd" \
--data-binary @build/rmm-agent
# Firmware hochladen (Linux)
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
"https://your-backend:8443/api/v1/firmware/upload?version=1.0.1&platform=linux" \
--data-binary @build/rmm-agent-linux
# Update fuer einzelnen Agent anfordern
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
https://your-backend:8443/api/v1/agents/e92e87a6.../request-update
# Update fuer alle Agents
curl -sk -H "Authorization: Bearer <TOKEN>" -X POST \
https://your-backend:8443/api/v1/agents/request-update-all
Hub-Status
GET /api/v1/hub/status WebSocket Hub Status
Beispiel:
curl -sk -H "Authorization: Bearer <TOKEN>" \
https://your-backend:8443/api/v1/hub/status
# → {"connected_agents":3,"active_tunnels":1}
Build & Deploy
cd frontend
npm install
npm run build # ~330 KB JS, ~32 KB CSS
# Deploy
ssh root@your-backend 'rm -rf /var/www/html/assets/*' # Alte Hashes loeschen!
scp -r dist/* root@your-backend:/var/www/html/
Wichtig: Vor Deploy immer assets/ loeschen — Vite generiert Hash-basierte Dateinamen, alte Dateien bleiben sonst auf dem Server.
Entwicklung
cd frontend
npm run dev # Startet Vite Dev-Server mit Proxy zu Backend
Vite Proxy-Config (vite.config.js): /api/ wird auf https://your-backend:8443 weitergeleitet.
Dateistruktur
frontend/
├── src/
│ ├── App.jsx # Router + ProtectedRoute
│ ├── main.jsx # Entry Point
│ ├── index.css # TailwindCSS + Custom Styles
│ ├── api/client.js # API Client (alle Endpoints)
│ ├── stores/auth.js # Zustand Auth Store (JWT Token)
│ ├── layouts/AppLayout.jsx # Sidebar Navigation + Outlet
│ ├── components/
│ │ ├── AgentPanel.jsx # Side Panel mit 11 Tabs
│ │ └── StatusBadge.jsx # Online/Offline/Stale Badge
│ └── pages/
│ ├── Dashboard.jsx # Status-Kacheln + Agent-Liste
│ ├── Agents.jsx # Firewall-Tabelle + Pre-Registration
│ ├── AgentDetail.jsx # Detail-Ansicht (full page, legacy)
│ ├── Tunnels.jsx # Globale Tunnel-Uebersicht
│ ├── Firmware.jsx # Multi-Plattform Firmware + Updates
│ ├── Customers.jsx # Kunden CRUD
│ ├── SettingsPage.jsx # User-Management + Passwort
│ └── Login.jsx # JWT Login
├── vite.config.js # Vite Config mit API Proxy
├── tailwind.config.js
└── package.json