docs: BACKEND.md vollständiges DB-Schema mit allen Feldern + jwt_secret in config
This commit is contained in:
parent
48ac353d28
commit
9bebf85a6d
297
docs/BACKEND.md
297
docs/BACKEND.md
@ -82,7 +82,8 @@ listen_addr: ":8443"
|
|||||||
tls_cert: "certs/server.crt"
|
tls_cert: "certs/server.crt"
|
||||||
tls_key: "certs/server.key"
|
tls_key: "certs/server.key"
|
||||||
api_keys:
|
api_keys:
|
||||||
- "SICHERER_API_KEY"
|
- "SICHERER_API_KEY" # beliebig lang, wird in X-API-Key Header mitgegeben
|
||||||
|
jwt_secret: "LANGER_ZUFAELLIGER_STRING" # fuer Frontend-Login (JWT-Signierung)
|
||||||
|
|
||||||
database:
|
database:
|
||||||
host: "127.0.0.1"
|
host: "127.0.0.1"
|
||||||
@ -93,6 +94,12 @@ database:
|
|||||||
sslmode: "disable" # "require" wenn PG ueber Netz
|
sslmode: "disable" # "require" wenn PG ueber Netz
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Zufälligen JWT-Secret generieren:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
openssl rand -hex 32
|
||||||
|
```
|
||||||
|
|
||||||
Alternativ per Environment-Variablen: `RMM_LISTEN_ADDR`, `RMM_TLS_CERT`, `RMM_TLS_KEY`, `RMM_DB_HOST`, `RMM_DB_PASSWORD`.
|
Alternativ per Environment-Variablen: `RMM_LISTEN_ADDR`, `RMM_TLS_CERT`, `RMM_TLS_KEY`, `RMM_DB_HOST`, `RMM_DB_PASSWORD`.
|
||||||
|
|
||||||
## 6. Backend deployen und starten
|
## 6. Backend deployen und starten
|
||||||
@ -141,27 +148,285 @@ Beim ersten Start:
|
|||||||
- Retention Policy (90 Tage) und Compression Policy (nach 7 Tagen) werden automatisch gesetzt
|
- Retention Policy (90 Tage) und Compression Policy (nach 7 Tagen) werden automatisch gesetzt
|
||||||
- Default-Admin `admin` / `YOUR_PASSWORD` wird erstellt
|
- Default-Admin `admin` / `YOUR_PASSWORD` wird erstellt
|
||||||
|
|
||||||
## Datenbank-Schema (automatisch)
|
## Datenbank-Schema (vollständig)
|
||||||
|
|
||||||
| Tabelle | Typ | Beschreibung |
|
Alle Tabellen werden beim Backend-Start **automatisch angelegt** (Auto-Migration inkl. ALTER TABLE für neue Spalten). Kein manuelles Schema-Setup nötig.
|
||||||
|---------|-----|-------------|
|
|
||||||
| `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
|
### `agents` — Agent-Registry
|
||||||
- **Compression**: Daten aelter als 7 Tage werden komprimiert (segmentby: agent_id+metric)
|
|
||||||
|
```sql
|
||||||
|
CREATE TABLE agents (
|
||||||
|
id TEXT PRIMARY KEY, -- UUID des Agents (persistent)
|
||||||
|
name TEXT NOT NULL, -- Anzeigename (z.B. "OPN.intra.kunde.de")
|
||||||
|
hostname TEXT NOT NULL, -- Hostname der Firewall
|
||||||
|
ip TEXT NOT NULL, -- IP-Adresse des Agents
|
||||||
|
opnsense_version TEXT NOT NULL DEFAULT '', -- OPNsense-Version (z.B. "25.1.1")
|
||||||
|
agent_version TEXT NOT NULL DEFAULT '', -- Agent-Binary-Version (z.B. "1.0.3")
|
||||||
|
platform TEXT NOT NULL DEFAULT 'freebsd', -- Plattform: "freebsd", "linux"
|
||||||
|
registered_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), -- Erstregistrierung
|
||||||
|
last_heartbeat TIMESTAMPTZ, -- Letzter Heartbeat
|
||||||
|
customer_id INTEGER REFERENCES customers(id), -- Kundenzuordnung (nullable)
|
||||||
|
update_requested BOOLEAN NOT NULL DEFAULT FALSE -- Update-Flag fuer Updater-Daemon
|
||||||
|
);
|
||||||
|
CREATE INDEX idx_agents_customer ON agents(customer_id);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Status-Berechnung** (kein DB-Feld, dynamisch im Backend):
|
||||||
|
|
||||||
|
| Status | Bedingung |
|
||||||
|
|--------|-----------|
|
||||||
|
| `online` | `last_heartbeat` < 2 Minuten |
|
||||||
|
| `stale` | `last_heartbeat` < 5 Minuten |
|
||||||
|
| `offline` | `last_heartbeat` > 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
|
### DB-Funktionen
|
||||||
|
|
||||||
- `GetAgentByName`: Sucht Agent nach Name — verwendet fuer Pre-Registration Matching bei Agent-Registrierung
|
- **`GetAgentByName`**: Sucht Agent nach Name — für Pre-Registration Matching (Agent registriert sich, Backend findet vorregistrierten Platzhalter mit `hostname="(ausstehend)"`).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user