rmm2/docs/BACKEND.md

18 KiB

Backend — Installation & Konfiguration

Das RMM-Backend laeuft auf Linux (Debian 12+) und stellt die REST API, den WebSocket Hub und den Tunnel Manager bereit.

Komponenten

  • REST API: Agent-Registrierung, Heartbeat, Systemdaten, Tunnel-Management
  • WebSocket Hub: Verwaltet Agent-Verbindungen, routet Commands und Binary-Messages
  • Tunnel Manager: Proxy-Listener, Session-Tracking, Ready-Handshake
  • PostgreSQL + TimescaleDB: Relationale Daten + Time-Series Metriken

1. PostgreSQL + TimescaleDB installieren

# Debian 12+ (Bookworm/Trixie)
apt install -y postgresql postgresql-client

# TimescaleDB Repository hinzufuegen
echo "deb https://packagecloud.io/timescale/timescaledb/debian/ bookworm main" \
  > /etc/apt/sources.list.d/timescaledb.list
curl -L https://packagecloud.io/timescale/timescaledb/gpgkey | gpg --dearmor \
  > /etc/apt/trusted.gpg.d/timescaledb.gpg
apt update

# TimescaleDB passend zur PG-Version installieren (z.B. PG 17)
apt install -y timescaledb-2-postgresql-17

# TimescaleDB in postgresql.conf aktivieren
echo "shared_preload_libraries = 'timescaledb'" >> /etc/postgresql/17/main/conf.d/timescaledb.conf
systemctl restart postgresql

2. Datenbank und User anlegen

sudo -u postgres psql <<EOF
CREATE USER rmm WITH PASSWORD 'SICHERES_PASSWORT';
CREATE DATABASE rmm OWNER rmm;
\c rmm
CREATE EXTENSION IF NOT EXISTS timescaledb;
GRANT ALL ON SCHEMA public TO rmm;
EOF

Verbindung testen:

psql -h 127.0.0.1 -U rmm -d rmm -c "SELECT default_version FROM pg_available_extensions WHERE name='timescaledb';"

3. Build

make all       # Backend (linux/amd64) + Agent (freebsd/amd64)
make backend   # Nur Backend
make agent     # Nur Agent

Binaries landen in build/. Kein CGO — reine Go-Compilation.

4. TLS-Zertifikate generieren

make certs

Oder manuell:

mkdir -p certs
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 \
  -keyout certs/server.key -out certs/server.crt \
  -days 3650 -nodes \
  -subj "/CN=rmm-backend/O=RMM" \
  -addext "subjectAltName=IP:BACKEND_IP,IP:127.0.0.1,DNS:localhost"

5. Backend konfigurieren (config.yaml)

listen_addr: ":8443"
tls_cert: "certs/server.crt"
tls_key: "certs/server.key"
api_keys:
  - "SICHERER_API_KEY"

database:
  host: "127.0.0.1"
  port: 5432
  user: "rmm"
  password: "SICHERES_PASSWORT"
  dbname: "rmm"
  sslmode: "disable"        # "require" wenn PG ueber Netz

Alternativ per Environment-Variablen: RMM_LISTEN_ADDR, RMM_TLS_CERT, RMM_TLS_KEY, RMM_DB_HOST, RMM_DB_PASSWORD.

6. Backend deployen und starten

# Verzeichnis anlegen
ssh root@BACKEND_IP "mkdir -p /opt/rmm/certs"

# Binary + Config + Certs kopieren
scp build/rmm-backend root@BACKEND_IP:/opt/rmm/rmm-backend
scp config.yaml root@BACKEND_IP:/opt/rmm/config.yaml
scp certs/server.* root@BACKEND_IP:/opt/rmm/certs/

# Systemd-Service einrichten (Vorlage liegt unter backend/rmm-backend.service)
scp backend/rmm-backend.service root@BACKEND_IP:/etc/systemd/system/rmm-backend.service
# WorkingDirectory und ExecStart ggf. an eigenen Pfad anpassen

ssh root@BACKEND_IP "systemctl daemon-reload && systemctl enable rmm-backend && systemctl start rmm-backend"

Die mitgelieferte Service-Datei (backend/rmm-backend.service) verwendet /home/cynfo/rmm als Arbeitsverzeichnis — bei abweichendem Pfad anpassen.

Dienste auf dem Backend-Server

Dienst Zweck Management
postgresql Datenbank (PostgreSQL + TimescaleDB) systemctl start/stop/restart postgresql
rmm-backend REST API, WebSocket Hub, Tunnel Manager systemctl start/stop/restart rmm-backend

7. Starten und verifizieren

# Status pruefen
systemctl status rmm-backend

# Log pruefen
journalctl -u rmm-backend -f

# API testen
curl -sk -H "X-API-Key: DEIN_API_KEY" https://BACKEND_IP:8443/api/v1/agents

Beim ersten Start:

  • Tabellen werden automatisch angelegt
  • Hypertable metrics wird erstellt (TimescaleDB)
  • Retention Policy (90 Tage) und Compression Policy (nach 7 Tagen) werden automatisch gesetzt
  • Default-Admin admin / YOUR_PASSWORD wird erstellt

Datenbank-Schema (automatisch)

Tabelle Typ Beschreibung
agents Relational Agent-Registry (ID, Name, Hostname, IP, Version, Heartbeat, customer_id, update_requested)
system_data Relational Letzte Systemdaten pro Agent (JSONB)
config_backups Relational OPNsense Config-Backups (dedupliziert per SHA256)
agent_events Relational Online/Offline/Connected Events
customers Relational Kundenstammdaten (Nummer, Name)
users Relational Benutzer (Username, bcrypt-Hash, Display-Name)
agent_firmware Relational Agent-Binaries pro Plattform+Version (BYTEA, SHA256)
metrics TimescaleDB Hypertable Time-Series Metriken (CPU, RAM, Disk, Network, Gateway)

TimescaleDB Policies

  • Retention: Rohdaten werden nach 90 Tagen automatisch geloescht
  • Compression: Daten aelter als 7 Tage werden komprimiert (segmentby: agent_id+metric)

DB-Funktionen

  • GetAgentByName: Sucht Agent nach Name — verwendet fuer Pre-Registration Matching bei Agent-Registrierung

API Endpoints

Base-URL: https://your-backend:8443/api/v1

Authentifizierung

Zwei Auth-Methoden (CombinedAuth Middleware):

  • API-Key (Header X-API-Key): Fuer Agents und Automatisierung
  • JWT Bearer (Header Authorization: Bearer <token>): Fuer Frontend
POST   /auth/login     Login → JWT Token (8h Ablauf)
GET    /auth/me         Eigene Benutzerdaten
# 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"}}

Agents

GET    /agents                    Alle Agents auflisten
GET    /agents/{id}               Agent + Systemdaten
GET    /agents/{id}/system        Nur Systemdaten (JSONB)
DELETE /agents/{id}               Agent loeschen (inkl. Daten, Events, Backups, Metriken)
POST   /agents                    Firewall pre-registrieren
PUT    /agents/{id}/customer      Kunden zuordnen
DELETE /agents/{id}/customer      Kundenzuordnung entfernen
POST   /agent/register            Agent-Registrierung (vom Agent selbst)
POST   /agent/heartbeat           Heartbeat + Systemdaten (vom Agent)
# Alle Agents
curl -sk -H "X-API-Key: YOUR_API_KEY" \
  https://your-backend:8443/api/v1/agents

# Agent mit Systemdaten
curl -sk -H "X-API-Key: YOUR_API_KEY" \
  https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee

# Nur Systemdaten
curl -sk -H "X-API-Key: YOUR_API_KEY" \
  https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/system

# Pre-Registrierung
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
  https://your-backend:8443/api/v1/agents \
  -d '{"name":"OPN.intra.kunde.de","customer_id":1}'

# Agent loeschen
curl -sk -H "X-API-Key: YOUR_API_KEY" -X DELETE \
  https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887

# Kunden zuordnen
curl -sk -H "X-API-Key: YOUR_API_KEY" -X PUT \
  https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/customer \
  -d '{"customer_id":1}'

Agent-Status (automatisch berechnet):

Status Bedingung
online Heartbeat < 2 Minuten
stale Heartbeat < 5 Minuten
offline Heartbeat > 5 Minuten
unknown Kein Heartbeat

Agent-Events

GET    /agents/events             Alle Events (?limit=N&type=X)
GET    /agents/{id}/events        Events eines Agents

Event-Typen: online, offline, stale, connected, disconnected

curl -sk -H "X-API-Key: YOUR_API_KEY" \
  "https://your-backend:8443/api/v1/agents/events?limit=10"

curl -sk -H "X-API-Key: YOUR_API_KEY" \
  "https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/events?type=offline"

Remote-Befehle (Exec)

POST   /agents/{id}/exec          Shell-Befehl ausfuehren
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
  https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887/exec \
  -d '{"command":"uptime","timeout":30}'
# → {"data":{"output":"10:30AM  up 45 days, ..."},"status":"ok"}

Tunnel-Management

POST   /agents/{id}/tunnel        Tunnel oeffnen
GET    /agents/{id}/tunnels       Aktive Tunnel auflisten
DELETE /agents/{id}/tunnel/{tid}  Tunnel schliessen
# SSH-Tunnel
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
  https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887/tunnel \
  -d '{"target_host":"127.0.0.1","target_port":22}'
# → {"tunnel_id":"abc123","proxy_port":10000,...}
# Verbinden: ssh -p 10000 root@your-backend

# WebGUI-Tunnel (OPNsense Port 4444)
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
  https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887/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 "X-API-Key: YOUR_API_KEY" -X POST \
  https://your-backend:8443/api/v1/agents/3f0a83a25d6fcdd8a623e76953559c87/tunnel \
  -d '{"target_host":"127.0.0.1","target_port":8006}'

# Aktive Tunnel
curl -sk -H "X-API-Key: YOUR_API_KEY" \
  https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887/tunnels

# Tunnel schliessen
curl -sk -H "X-API-Key: YOUR_API_KEY" -X DELETE \
  https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887/tunnel/abc123

Tunnel-Architektur:

  • Proxy-Port-Range: 10000-20000 (dynamisch)
  • Jede TCP-Verbindung am Proxy bekommt eigene Session
  • Agent oeffnet Ziel-Verbindung erst bei erstem Datenpaket (Lazy Connect)
  • Binary WebSocket Messages: [id_len:1][session_id][tcp_payload]

Config-Backups

POST   /agents/{id}/backup                 Backup ausloesen (via WebSocket)
GET    /agents/{id}/backups                Alle Backups (?limit=N)
GET    /agents/{id}/backups/{id|latest}    Backup herunterladen (?format=xml)
DELETE /agents/{id}/backups/{id}           Backup loeschen
GET    /agents/{id}/backups/diff           Diff (?a=ID&b=ID)
# Backup ausloesen
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
  https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/backup

# Alle Backups
curl -sk -H "X-API-Key: YOUR_API_KEY" \
  https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/backups

# Neuestes als XML
curl -sk -H "X-API-Key: YOUR_API_KEY" \
  "https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887/backups/latest?format=xml" \
  -o config-backup.xml

# Diff
curl -sk -H "X-API-Key: YOUR_API_KEY" \
  "https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887/backups/diff?a=1&b=3"

Deduplizierung: Gleicher SHA256-Hash = kein neuer Eintrag.

WireGuard Peer-Management

GET    /agents/{id}/wireguard/peers        Alle Peers (?server_name=X)
POST   /agents/{id}/wireguard/peers        Peer anlegen
DELETE /agents/{id}/wireguard/peers/{uuid}  Peer loeschen

Peer-Anlage: Keypair generiert auf Firewall, naechste freie IP automatisch, Endpoint Auto-Detect via WAN-IP.

# Peer anlegen
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
  https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/wireguard/peers \
  -d '{"name":"VPN_MUELLER","allowed_ips":"0.0.0.0/0","dns":"10.172.100.210"}'

# Alle Peers
curl -sk -H "X-API-Key: YOUR_API_KEY" \
  https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/wireguard/peers

# Peer loeschen
curl -sk -H "X-API-Key: YOUR_API_KEY" -X DELETE \
  https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/wireguard/peers/89c10e2d-148e-11f1-a7af-7c5a1c6c7b73

Kunden (Customers)

GET    /customers                  Alle Kunden
POST   /customers                  Neuen Kunden anlegen
GET    /customers/{id}             Einzelnen Kunden abrufen
PUT    /customers/{id}             Kunden aktualisieren
DELETE /customers/{id}             Kunden loeschen
GET    /customers/{id}/agents      Agents eines Kunden
# Kunden anlegen
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
  https://your-backend:8443/api/v1/customers \
  -d '{"number":"K05001","name":"Beispiel GmbH"}'

# Kunden aktualisieren
curl -sk -H "X-API-Key: YOUR_API_KEY" -X PUT \
  https://your-backend:8443/api/v1/customers/1 \
  -d '{"number":"K05001","name":"Beispiel AG"}'

# Agents eines Kunden
curl -sk -H "X-API-Key: YOUR_API_KEY" \
  https://your-backend:8443/api/v1/customers/1/agents

Benutzer (Users)

GET    /users                      Alle Benutzer
POST   /users                      Neuen Benutzer anlegen
PUT    /users/{id}/password        Passwort aendern (min. 6 Zeichen)
DELETE /users/{id}                 Benutzer loeschen
# 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    /agents/{id}/metrics          Rohe Metriken (?metric=X&from=&to=&limit=N)
GET    /agents/{id}/metrics/summary  Aggregiert (?metric=X&bucket=5+minutes&from=&to=)

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

# CPU letzte 24h
curl -sk -H "X-API-Key: YOUR_API_KEY" \
  "https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/metrics?metric=cpu_usage"

# 5-Minuten-Durchschnitte
curl -sk -H "X-API-Key: YOUR_API_KEY" \
  "https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/metrics/summary?metric=cpu_usage&bucket=5+minutes"

# Stuendliche RAM-Zusammenfassung mit Zeitraum
curl -sk -H "X-API-Key: YOUR_API_KEY" \
  "https://your-backend:8443/api/v1/agents/6beb8dfd38ecf03eab6c0f21b4ac7bee/metrics/summary?metric=memory_used_percent&bucket=1+hour&from=2026-03-01T00:00:00Z&to=2026-03-01T23:59:59Z"

Updates & Reboot

POST   /agents/{id}/update-check   Verfuegbare Updates pruefen
POST   /agents/{id}/update          Normales Update (Core + Packages)
POST   /agents/{id}/major-update    Major-Upgrade (2-Phasen)
POST   /agents/{id}/reboot          Reboot
# Update-Check
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
  https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887/update-check

# Update mit Reboot
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
  https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887/update \
  -d '{"reboot":true}'

# Major-Update Phase 1 (Base+Kernel, dann Reboot)
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
  https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887/major-update \
  -d '{"version":"26.1","reboot":true}'

# Major-Update Phase 2 (nach Reboot: Packages)
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
  https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887/major-update \
  -d '{"version":"26.1","phase":"2"}'

# Reboot
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
  https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887/reboot \
  -d '{"delay":5}'

Firmware / Agent-Update

GET    /firmware                           Alle Firmware-Versionen (?platform=X)
POST   /firmware/upload?version=X&platform=Y  Binary hochladen
GET    /firmware/download?platform=Y       Binary herunterladen (fuer Updater)
POST   /agents/{id}/request-update         Update-Flag setzen
DELETE /agents/{id}/request-update         Update-Flag zuruecksetzen
POST   /agents/request-update-all          Alle Agents updaten
POST   /agents/{id}/agent-update           Legacy: Binary direkt via WebSocket pushen
# Firmware-Info
curl -sk -H "X-API-Key: YOUR_API_KEY" \
  https://your-backend:8443/api/v1/firmware

# Nur FreeBSD-Firmware
curl -sk -H "X-API-Key: YOUR_API_KEY" \
  "https://your-backend:8443/api/v1/firmware?platform=freebsd"

# Firmware hochladen (FreeBSD)
curl -sk -H "X-API-Key: YOUR_API_KEY" -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 "X-API-Key: YOUR_API_KEY" -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 "X-API-Key: YOUR_API_KEY" -X POST \
  https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887/request-update

# Update-Flag zuruecksetzen
curl -sk -H "X-API-Key: YOUR_API_KEY" -X DELETE \
  https://your-backend:8443/api/v1/agents/e92e87a684b20db15d8d2344583c5887/request-update

# Alle Agents updaten
curl -sk -H "X-API-Key: YOUR_API_KEY" -X POST \
  https://your-backend:8443/api/v1/agents/request-update-all

Update-Flow: Frontend setzt Flag → Updater (separater Prozess auf Firewall) pollt alle 60s → Download + SHA256-Verify + Rollback bei Fehler → Flag wird geloescht.

WebSocket

GET    /agent/ws?agent_id=X&api_key=X    WebSocket-Verbindung (Agent)
GET    /hub/status                        Hub-Status
# Hub-Status (verbundene Agents, aktive Tunnel)
curl -sk -H "X-API-Key: YOUR_API_KEY" \
  https://your-backend:8443/api/v1/hub/status

WebSocket Commands (Backend → Agent):

Command Parameter Beschreibung
exec command, timeout Shell-Befehl ausfuehren
backup Config.xml lesen + senden
update_check Verfuegbare Updates pruefen
update reboot Normales Update
major_update version, phase, reboot Major-Upgrade
reboot delay Reboot
tunnel_connect session_id, tunnel_id, target_host, target_port TCP-Tunnel oeffnen
tunnel_disconnect session_id Tunnel-Session schliessen
wg_add_peer name, server_name, allowed_ips, dns, endpoint WireGuard Peer anlegen
wg_list_peers server_name WireGuard Peers auflisten
wg_delete_peer uuid WireGuard Peer loeschen
agent_update Binary + Hash (im Data-Feld) Agent-Binary aktualisieren (Legacy)

Hinweise

  • Backend braucht kein root — laeuft als normaler User auf Port 8443
  • Beim Deploy: alte Prozesse killen bevor neuer startet (sonst "bind: address already in use")
  • FreeBSD csh hat kein $() — Agent verwendet /bin/sh -c fuer Commands