# 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 ```bash # 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 ```bash sudo -u postgres psql < 5 Minuten | | `unknown` | `last_heartbeat` ist NULL | --- ### `customers` — Kundenstammdaten ```sql CREATE TABLE customers ( id SERIAL PRIMARY KEY, number TEXT NOT NULL UNIQUE, -- RMM-Kundennummer (z.B. "K05068") name TEXT NOT NULL, -- Kundenname created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); ``` --- ### `users` — Benutzer (Frontend-Login) ```sql CREATE TABLE users ( id SERIAL PRIMARY KEY, username TEXT NOT NULL UNIQUE, password_hash TEXT NOT NULL, -- bcrypt-Hash display_name TEXT NOT NULL DEFAULT '', role TEXT NOT NULL DEFAULT 'admin', -- aktuell nur "admin" created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), last_login TIMESTAMPTZ -- nullable ); ``` Standard-Admin wird beim ersten Start angelegt: `admin` / `Start!123` (sofort ändern). --- ### `system_data` — Aktueller Systemzustand pro Agent ```sql CREATE TABLE system_data ( agent_id TEXT PRIMARY KEY REFERENCES agents(id) ON DELETE CASCADE, data_json JSONB NOT NULL, -- Vollständiger Heartbeat-Payload des Agents updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); ``` --- ### `config_backups` — Versionierte OPNsense-Configs ```sql CREATE TABLE config_backups ( id SERIAL PRIMARY KEY, agent_id TEXT NOT NULL REFERENCES agents(id) ON DELETE CASCADE, hash TEXT NOT NULL, -- SHA256 der config.xml (Deduplizierung) size INTEGER NOT NULL, -- Grösse in Bytes config_xml TEXT NOT NULL, -- Vollständige config.xml created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX idx_config_backups_agent ON config_backups(agent_id, created_at DESC); CREATE INDEX idx_config_backups_hash ON config_backups(agent_id, hash); ``` Deduplizierung: gleicher SHA256 → kein neuer Eintrag. --- ### `agent_events` — Online/Offline-Ereignisse ```sql CREATE TABLE agent_events ( id SERIAL PRIMARY KEY, agent_id TEXT NOT NULL REFERENCES agents(id) ON DELETE CASCADE, event_type TEXT NOT NULL, -- "online", "offline", "stale", "connected", "disconnected" message TEXT, -- optionale Zusatzinfo created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX idx_agent_events_agent ON agent_events(agent_id, created_at DESC); ``` --- ### `agent_firmware` — Agent-Binaries pro Plattform ```sql CREATE TABLE agent_firmware ( version TEXT NOT NULL, -- z.B. "1.0.3" platform TEXT NOT NULL DEFAULT 'freebsd', -- "freebsd", "linux", "windows" hash TEXT NOT NULL, -- SHA256 des Binaries binary_data BYTEA NOT NULL, -- Das Binary selbst uploaded_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE (version, platform) ); ``` --- ### `tasks` — Task-Scheduler (geplante Aufgaben) ```sql CREATE TABLE tasks ( id SERIAL PRIMARY KEY, agent_id TEXT NOT NULL REFERENCES agents(id) ON DELETE CASCADE, name TEXT DEFAULT '', -- Anzeigename der Aufgabe action TEXT NOT NULL, -- "update", "backup", "reboot", ... status TEXT NOT NULL DEFAULT 'scheduled', -- "scheduled","running","completed","failed" schedule_type TEXT DEFAULT 'once', -- "once", "daily", "weekly", "monthly" schedule_time TEXT DEFAULT '02:00', -- Uhrzeit (HH:MM) schedule_weekday INT, -- 0=So, 1=Mo, ... 6=Sa (nur bei "weekly") schedule_monthday INT, -- 1-31 (nur bei "monthly") reboot BOOLEAN DEFAULT FALSE, -- Nach Update neu starten health_check BOOLEAN DEFAULT FALSE, -- Nach Aufgabe Erreichbarkeit prüfen health_check_timeout INT DEFAULT 600, -- Sekunden bis Timeout des Health-Checks active BOOLEAN DEFAULT TRUE, -- Recurring: aktiv/inaktiv scheduled_at TIMESTAMPTZ NOT NULL, -- Nächste/erste Ausführung (once) started_at TIMESTAMPTZ, -- Tatsächlicher Start finished_at TIMESTAMPTZ, -- Ende der Ausführung last_run TIMESTAMPTZ, -- Letzter Lauf (recurring) next_run TIMESTAMPTZ, -- Nächster Lauf (recurring) run_count INT DEFAULT 0, -- Anzahl Ausführungen (recurring) result JSONB, -- Ergebnis-Payload webhook_url TEXT, -- URL für Webhook nach Abschluss webhook_sent BOOLEAN DEFAULT FALSE, webhook_response TEXT, -- HTTP-Response des Webhooks created_by TEXT, -- Username des Erstellers created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX idx_tasks_status_scheduled ON tasks(status, scheduled_at); CREATE INDEX idx_tasks_active_next_run ON tasks(active, next_run) WHERE active = TRUE; ``` **Webhook-Payload** (gesendetes JSON bei `webhook_url` gesetzt): ```json { "customer_id": "K05068", "hostname": "opnsense.kunde.de", "opnsense_version": "25.1.1", "timestamp": "2026-03-06T08:00:00Z", "trigger": "update_completed", "reachable": true, "update_status": "completed" } ``` --- ### `api_keys` — API-Keys (zusätzlich zu config.yaml) ```sql CREATE TABLE api_keys ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, key TEXT NOT NULL UNIQUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), last_used TIMESTAMPTZ ); ``` --- ### `installers` — OPNsense Plugin-Pakete ```sql CREATE TABLE installers ( id SERIAL PRIMARY KEY, platform TEXT NOT NULL UNIQUE, -- "freebsd", "linux" filename TEXT NOT NULL, data BYTEA NOT NULL, -- ZIP-Paket (install.sh + Plugin) sha256 TEXT NOT NULL, size INTEGER NOT NULL, uploaded_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); ``` --- ### `audit_log` — Audit-Protokoll ```sql CREATE TABLE audit_log ( id SERIAL PRIMARY KEY, timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(), user_name TEXT NOT NULL, action TEXT NOT NULL, -- z.B. "login", "delete_agent", "update_customer" target_type TEXT, -- z.B. "agent", "customer", "user" target_id TEXT, target_name TEXT, details TEXT, source_ip TEXT ); CREATE INDEX idx_audit_log_timestamp ON audit_log(timestamp DESC); ``` --- ### `system_settings` — Backend-Einstellungen (Key/Value) ```sql CREATE TABLE system_settings ( key TEXT PRIMARY KEY, -- "backend_url_internal", "backend_url_external", "api_key" value TEXT NOT NULL, updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); ``` --- ### `metrics` — TimescaleDB Hypertable (Zeitreihen) ```sql CREATE TABLE metrics ( time TIMESTAMPTZ NOT NULL, agent_id TEXT NOT NULL, metric TEXT NOT NULL, -- Name der Metrik value DOUBLE PRECISION NOT NULL, tags JSONB -- z.B. {"interface":"igb0"} ); -- In Hypertable umwandeln: SELECT create_hypertable('metrics', 'time', if_not_exists => TRUE); CREATE INDEX idx_metrics_agent_metric ON metrics(agent_id, metric, time DESC); ``` **Verfügbare Metriken:** | Metrik | Einheit | Tags | |--------|---------|------| | `cpu_usage` | Prozent | — | | `memory_used_percent` | Prozent | — | | `memory_used_bytes` | Bytes | — | | `memory_total_bytes` | Bytes | — | | `uptime_seconds` | Sekunden | — | | `disk_used_percent` | Prozent | `{"mountpoint":"/","dataset":"zroot/ROOT"}` | | `disk_used_bytes` | Bytes | `{"mountpoint":"/"}` | | `interface_rx_bytes` | Bytes | `{"interface":"igb0"}` | | `interface_tx_bytes` | Bytes | `{"interface":"igb0"}` | | `gateway_rtt_ms` | Millisekunden | `{"gateway":"WAN_GW"}` | | `gateway_loss_percent` | Prozent | `{"gateway":"WAN_GW"}` | **TimescaleDB Policies** (automatisch gesetzt): - **Retention**: Rohdaten nach 90 Tagen gelöscht - **Compression**: Daten älter als 7 Tage komprimiert (`segmentby: agent_id, metric`) --- ### DB-Funktionen - **`GetAgentByName`**: Sucht Agent nach Name — für Pre-Registration Matching (Agent registriert sich, Backend findet vorregistrierten Platzhalter mit `hostname="(ausstehend)"`). --- ## 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 `): Fuer Frontend ``` POST /auth/login Login → JWT Token (8h Ablauf) GET /auth/me Eigene Benutzerdaten ``` ```bash # 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) ``` ```bash # 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` ```bash 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 ``` ```bash 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 ``` ```bash # 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) ``` ```bash # 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. ```bash # 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 ``` ```bash # 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 ``` ```bash # Benutzer anlegen curl -sk -H "Authorization: Bearer " -X POST \ https://your-backend:8443/api/v1/users \ -d '{"username":"operator","password":"Sicher!123"}' # Passwort aendern curl -sk -H "Authorization: Bearer " -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` ```bash # 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 ``` ```bash # 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 ``` ```bash # 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 ``` ```bash # 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