From 27d6492258eab1b8e4aeeca3f444f45109b685ce Mon Sep 17 00:00:00 2001 From: cynfo3000 Date: Sat, 28 Feb 2026 12:40:44 +0100 Subject: [PATCH] PostgreSQL + TimescaleDB Setup-Anleitung und Installation auf .13 - PostgreSQL 17.8 auf Debian 13 Trixie installiert - TimescaleDB 2.25.1 Extension aktiviert - DB 'rmm', User 'rmm' angelegt - docs/POSTGRES_SETUP.md: Komplette Anleitung - Installation (PG17 + TimescaleDB via Bookworm-Repo) - Schema (agents, config_backups, metrics Hypertable, system_data) - Retention Policy (90 Tage Raw, 365 Tage Hourly Aggregate) - Compression (nach 7 Tagen) - Continuous Aggregate (stuendliche Durchschnitte) - Nuetzliche SQL-Abfragen - Backend config.yaml Anpassung --- docs/POSTGRES_SETUP.md | 284 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 docs/POSTGRES_SETUP.md diff --git a/docs/POSTGRES_SETUP.md b/docs/POSTGRES_SETUP.md new file mode 100644 index 0000000..53ffffb --- /dev/null +++ b/docs/POSTGRES_SETUP.md @@ -0,0 +1,284 @@ +# PostgreSQL + TimescaleDB Setup + +Anleitung fuer die Einrichtung von PostgreSQL mit TimescaleDB-Extension auf dem RMM-Backend-Server (192.168.85.13, Debian 13 Trixie). + +## 1. PostgreSQL installieren + +```bash +# Debian-Pakete +apt update +apt install -y postgresql postgresql-contrib postgresql-common + +# Dienst starten und aktivieren +systemctl enable postgresql +systemctl start postgresql + +# Version pruefen +psql --version +# Erwartet: psql (PostgreSQL) 17.x (Debian 13 Trixie liefert PG17) +``` + +## 2. TimescaleDB installieren + +```bash +# TimescaleDB APT-Repository hinzufuegen +apt install -y curl gnupg +curl -s https://packagecloud.io/install/repositories/timescale/timescaledb/script.deb.sh | bash + +# Bookworm-Repo verwenden (Trixie-Repo existiert noch nicht) +echo "deb https://packagecloud.io/timescale/timescaledb/debian/ bookworm main" \ + > /etc/apt/sources.list.d/timescaledb.list +curl -sL https://packagecloud.io/timescale/timescaledb/gpgkey | gpg --dearmor > /etc/apt/trusted.gpg.d/timescaledb.gpg +apt update + +# WICHTIG: Version muss zur installierten PG-Version passen +# Pruefen: dpkg -l | grep postgresql-17 → z.B. 17.8 +# Dann passende TimescaleDB-Version installieren: +apt install -y timescaledb-2-loader-postgresql-17=2.25.1~debian12-1708 \ + timescaledb-2-postgresql-17=2.25.1~debian12-1708 + +# shared_preload_libraries setzen +sed -i "s/#shared_preload_libraries = ''/shared_preload_libraries = 'timescaledb'/" \ + /etc/postgresql/17/main/postgresql.conf + +# PostgreSQL neustarten +systemctl restart postgresql +``` + +## 3. Datenbank und User anlegen + +```bash +# Als postgres User +sudo -u postgres psql +``` + +```sql +-- Datenbank anlegen +CREATE DATABASE rmm; + +-- User anlegen (Passwort anpassen!) +CREATE USER rmm WITH PASSWORD 'Cynf0-RMM-2026!'; + +-- Rechte vergeben +GRANT ALL PRIVILEGES ON DATABASE rmm TO rmm; + +-- In die rmm-Datenbank wechseln +\c rmm + +-- Schema-Rechte +GRANT ALL ON SCHEMA public TO rmm; + +-- TimescaleDB Extension aktivieren +CREATE EXTENSION IF NOT EXISTS timescaledb; + +-- Pruefen +\dx +-- Sollte timescaledb in der Liste zeigen + +\q +``` + +## 4. pg_hba.conf anpassen (lokaler Zugriff) + +```bash +# Zeile hinzufuegen (lokaler TCP-Zugriff fuer rmm User) +echo "host rmm rmm 127.0.0.1/32 scram-sha-256" >> /etc/postgresql/17/main/pg_hba.conf + +# PostgreSQL neu laden +systemctl reload postgresql +``` + +## 5. Verbindung testen + +```bash +psql -h 127.0.0.1 -U rmm -d rmm -c "SELECT version();" +# Passwort: Cynf0-RMM-2026! + +psql -h 127.0.0.1 -U rmm -d rmm -c "SELECT extname, extversion FROM pg_extension WHERE extname = 'timescaledb';" +# Sollte timescaledb mit Version zeigen +``` + +## 6. Schema anlegen + +Das Backend legt die Tabellen automatisch beim Start an (Auto-Migration). Die Struktur: + +### Relationale Tabellen + +```sql +-- Agent-Registry +CREATE TABLE IF NOT EXISTS agents ( + id TEXT PRIMARY KEY, + name TEXT NOT NULL, + hostname TEXT NOT NULL, + ip TEXT NOT NULL, + opnsense_version TEXT NOT NULL DEFAULT '', + registered_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + last_heartbeat TIMESTAMPTZ +); + +-- Config-Backups (versioniert, dedupliziert nach Hash) +CREATE TABLE IF NOT EXISTS config_backups ( + id SERIAL PRIMARY KEY, + agent_id TEXT NOT NULL REFERENCES agents(id) ON DELETE CASCADE, + hash TEXT NOT NULL, + size INTEGER NOT NULL, + config_xml TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX IF NOT EXISTS idx_config_backups_agent ON config_backups(agent_id, created_at DESC); +CREATE INDEX IF NOT EXISTS idx_config_backups_hash ON config_backups(agent_id, hash); +``` + +### TimescaleDB Hypertable (Metriken) + +```sql +-- Metriken-Tabelle +CREATE TABLE IF NOT EXISTS metrics ( + time TIMESTAMPTZ NOT NULL, + agent_id TEXT NOT NULL, + metric TEXT NOT NULL, -- z.B. 'cpu_usage', 'memory_used_percent', 'disk_used_percent' + value DOUBLE PRECISION NOT NULL, + tags JSONB -- z.B. {"interface":"igb0"}, {"disk":"/dev/ada0"} +); + +-- In Hypertable umwandeln (automatische Partitionierung nach Zeit) +SELECT create_hypertable('metrics', 'time', if_not_exists => TRUE); + +-- Index fuer schnelle Agent+Metrik-Abfragen +CREATE INDEX IF NOT EXISTS idx_metrics_agent_metric ON metrics(agent_id, metric, time DESC); +``` + +### Systemdaten-Snapshots (aktueller Zustand) + +```sql +-- Aktueller Snapshot der vollstaendigen Systemdaten (JSON) +CREATE TABLE IF NOT EXISTS system_data ( + agent_id TEXT PRIMARY KEY REFERENCES agents(id) ON DELETE CASCADE, + data_json JSONB NOT NULL, + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); +``` + +## 7. Retention Policies einrichten + +```sql +-- Metriken aelter als 90 Tage automatisch loeschen +SELECT add_retention_policy('metrics', INTERVAL '90 days'); + +-- Optional: Continuous Aggregate fuer stuendliche Durchschnitte +CREATE MATERIALIZED VIEW metrics_hourly +WITH (timescaledb.continuous) AS +SELECT + time_bucket('1 hour', time) AS bucket, + agent_id, + metric, + AVG(value) AS avg_value, + MIN(value) AS min_value, + MAX(value) AS max_value, + COUNT(*) AS sample_count +FROM metrics +GROUP BY bucket, agent_id, metric +WITH NO DATA; + +-- Automatisch aktualisieren +SELECT add_continuous_aggregate_policy('metrics_hourly', + start_offset => INTERVAL '3 hours', + end_offset => INTERVAL '1 hour', + schedule_interval => INTERVAL '1 hour' +); + +-- Stuendliche Aggregate 1 Jahr behalten +SELECT add_retention_policy('metrics_hourly', INTERVAL '365 days'); +``` + +## 8. Compression aktivieren (optional, spart Speicher) + +```sql +-- Compression fuer Metriken aelter als 7 Tage +ALTER TABLE metrics SET ( + timescaledb.compress, + timescaledb.compress_segmentby = 'agent_id, metric', + timescaledb.compress_orderby = 'time DESC' +); + +SELECT add_compression_policy('metrics', INTERVAL '7 days'); +``` + +## 9. Backend-Konfiguration + +In der `config.yaml` des Backends: + +```yaml +# Alte SQLite-Config entfernen: +# db_path: "rmm.db" + +# Neue PostgreSQL-Config: +database: + host: "127.0.0.1" + port: 5432 + user: "rmm" + password: "Cynf0-RMM-2026!" + dbname: "rmm" + sslmode: "disable" +``` + +## 10. Metriken die der Agent sendet + +Bei jedem Heartbeat (alle 60s) werden folgende Metriken geschrieben: + +| Metrik | Beschreibung | Tags | +|--------|-------------|------| +| `cpu_usage` | CPU-Auslastung in Prozent | — | +| `memory_used_percent` | RAM-Nutzung in Prozent | — | +| `memory_used_bytes` | RAM genutzt in Bytes | — | +| `memory_total_bytes` | RAM gesamt in Bytes | — | +| `disk_used_percent` | Disk-Belegung pro Mountpoint | `{"mountpoint":"/", "dataset":"zroot/ROOT"}` | +| `uptime_seconds` | Uptime in Sekunden | — | +| `interface_rx_bytes` | Empfangene Bytes pro Interface | `{"interface":"igb0"}` | +| `interface_tx_bytes` | Gesendete Bytes pro Interface | `{"interface":"igb0"}` | +| `gateway_rtt_ms` | Gateway RTT in ms | `{"gateway":"WAN_GW"}` | +| `gateway_loss_percent` | Gateway Paketverlust | `{"gateway":"WAN_GW"}` | + +## Nuetzliche Abfragen + +```sql +-- CPU-Auslastung der letzten 24h (5-Minuten-Durchschnitt) +SELECT time_bucket('5 minutes', time) AS t, + agent_id, + AVG(value) AS cpu_avg +FROM metrics +WHERE metric = 'cpu_usage' + AND time > NOW() - INTERVAL '24 hours' +GROUP BY t, agent_id +ORDER BY t; + +-- Aktuelle Werte aller Agents +SELECT DISTINCT ON (agent_id, metric) + agent_id, metric, value, time +FROM metrics +ORDER BY agent_id, metric, time DESC; + +-- Disk-Warnung: > 80% belegt +SELECT agent_id, tags->>'mountpoint' AS mount, + value AS used_percent, time +FROM metrics +WHERE metric = 'disk_used_percent' + AND value > 80 + AND time > NOW() - INTERVAL '1 hour' +ORDER BY value DESC; +``` + +## Zusammenfassung + +| Komponente | Zweck | +|-----------|-------| +| PostgreSQL 17 | Relationale Daten (Agents, Backups) | +| TimescaleDB 2.x | Time-Series Metriken (CPU, RAM, Disk, ...) | +| `agents` | Agent-Registry | +| `config_backups` | Versionierte Firewall-Configs | +| `system_data` | Aktueller JSON-Snapshot | +| `metrics` | Hypertable mit 60s-Aufloesung | +| `metrics_hourly` | Continuous Aggregate (1h) | +| Retention | Raw: 90 Tage, Hourly: 365 Tage | +| Compression | Nach 7 Tagen automatisch |