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
ssh root@BACKEND_IP 'cat > /etc/systemd/system/rmm-backend.service << EOF
[Unit]
Description=RMM Backend
After=network.target postgresql.service
[Service]
Type=simple
WorkingDirectory=/opt/rmm
ExecStart=/opt/rmm/rmm-backend /opt/rmm/config.yaml
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF'
ssh root@BACKEND_IP "systemctl daemon-reload && systemctl enable rmm-backend && systemctl start rmm-backend"
Oder per Makefile: make deploy-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
metricswird erstellt (TimescaleDB) - Retention Policy (90 Tage) und Compression Policy (nach 7 Tagen) werden automatisch gesetzt
- Default-Admin
admin/YOUR_PASSWORDwird 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 -cfuer Commands