Import und Export in Uptime Kuma
Ich benötigte für ein Projekt ein kleines Monitoring Tool, welches eine Vielzahl an PCs überwacht und mir anzeigt, wann welcher PC eingeschaltet war.
Für die Umsetzung habe ich Uptime Kuma genutzt. Da es sich um meherere hundert PCs handelt, wollte ich diese gerne per CSV importieren, da das manuelle anlegen zu aufwendig gewesen wäre.
Danach wollte ich bei Bedarf einen Export machen können, der mir den Online-Status der PCs anzeigt.
Schritt 1: Uptime Kuma installieren
Die Installation erfolgte mit Docker Compose.
mkdir -p /opt/uptime-kuma
cd /opt/uptime-kuma
nano compose.yaml
Nun folgendes Docker Compose Script erstellen und die MariaDB-Passwörter ändern.
services:
mariadb:
image: mariadb:11
container_name: uptime-kuma-db
restart: unless-stopped
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: <SICHERES_PASSWORT>
MYSQL_DATABASE: uptime_kuma
MYSQL_USER: kuma
MYSQL_PASSWORD: <SICHERES_PASSWORT>
volumes:
- ./mariadb_data:/var/lib/mysql
uptime-kuma:
image: louislam/uptime-kuma:2
container_name: uptime-kuma
restart: always
ports:
- "30001:3001"
volumes:
- ./data:/app/data
environment:
- TZ=Europe/Berlin
- UMASK=0022
depends_on:
- mariadb
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001"]
interval: 30s
retries: 3
start_period: 10s
timeout: 5s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Nun muss der Compose-Stack noch gestartet werden.
docker compose up -d
Schritt 2: Reverse Proxy und SSL-Zertifikat
Da der Server in einem Netzwerk mit sehr vielen PCs hängt, sollte das Webinterface nur per https aufrufbar sein. Dafür habe ich einen Nginx Reverse Proxy genutzt.
apt update && sudo apt install nginx -y
Danach ein selbstsigniertes SSL-Zertifikat generieren. Die IP-Adressen müssen noch angepasst werden.
sudo mkdir -p /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/selfsigned.key \
-out /etc/nginx/ssl/selfsigned.crt \
-subj "/CN=192.168.x.x" \
-addext "subjectAltName=IP:192.168.x.x"
Nun die Konfigurationsdatei erstellen:
sudo nano /etc/nginx/sites-available/uptime-kuma
# HTTP → HTTPS Weiterleitung (optional, aber empfohlen)
server {
listen 80;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name _; # "_" akzeptiert Anfragen auf jede IP/Domain
ssl_certificate /etc/nginx/ssl/selfsigned.crt;
ssl_certificate_key /etc/nginx/ssl/selfsigned.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://localhost:30001/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Nun noch die Konfiguration aktivueren und Nginx starten.
# Symlink erstellen
sudo ln -s /etc/nginx/sites-available/uptime-kuma /etc/nginx/sites-enabled/
# Syntax prüfen
sudo nginx -t
# nginx neu laden
sudo systemctl reload nginx
Es bietet sich ausserdem an die UFW Firewall zu aktivieren und Port 80/tcp und 443/tcp freizugeben.
Dafür gibt es bereits folgende Anleitung:
https://checkpoint-it.net/firewall-mit-ufw-konfigurieren/
Schritt 3: Uptime Kuma einrichten
Wenn alles geklappt hat sollte Uptime Kuma nun über die IP im Brwoser aufrufbar sein.
Als Datenbankverbindung muss „MariaDB/MySQL“ ausgewählt werden und mit den Zugangsdaten aus der Compose-Datei gefüllt werden.
Als Host „mariadb“ eintragen
Schritt 4: Importscript erstellen
Um nun den Import der Geräte vorzunehmen wird als erstes eine CSV-Datei namen Geraete.csv benötigt, welche nach folgenden Schema erstellt werden muss:
nano /opt/uptime-kuma/Geraete.csv
#Name;Typ;IPv4
raum1-pc00;COMPUTER;192.168.1.100
raum2-pc01;COMPUTER;192.168.1.101
raum3-pc02;COMPUTER;192.168.1.102
Jetzt muss Python und die benötigte Python Bibliothek installiert werden:
sudo apt install python3-pip -y
pip3 install uptime-kuma-api --break-system-packages
pip3 install mysql-connector-python --break-system-packages
Jetzt das Script erstellen und die folgenden 3 Zeilen anpassen:
UPTIME_KUMA_URL = "http://localhost:30001"
USERNAME = "UPTIME-KUMA-BENUTZER"
PASSWORD = "UPTIME-KUMA-PASSWORT"
Hier das Script:
nano import_uptime_kuma.py
#!/usr/bin/env python3
"""
Uptime Kuma Monitor Import
Liest eine CSV-Datei und legt alle Geräte als Ping-Monitor an.
Verwendung:
python3 import_uptime_kuma.py
"""
from uptime_kuma_api import UptimeKumaApi, MonitorType
import csv
import sys
# -------------------------------------------------------
# KONFIGURATION – hier anpassen
# -------------------------------------------------------
UPTIME_KUMA_URL = "http://localhost:30001"
USERNAME = "UPTIME-KUMA-BENUTZER"
PASSWORD = "UPTIME-KUMA-PASSWORT"
CSV_DATEI = "Geraete.csv" # Pfad zur CSV-Datei
PING_INTERVALL = 300 # Sekunden (300 = 5 Minuten)
# -------------------------------------------------------
def main():
print(f"Verbinde mit Uptime Kuma unter {UPTIME_KUMA_URL} ...")
try:
api = UptimeKumaApi(UPTIME_KUMA_URL)
api.login(USERNAME, PASSWORD)
print("Login erfolgreich.\n")
except Exception as e:
import traceback
traceback.print_exc()
sys.exit(1)
# Vorhandene Monitore laden, um Duplikate zu vermeiden
vorhandene = api.get_monitors()
vorhandene_namen = {m["name"] for m in vorhandene}
print(f"{len(vorhandene_namen)} Monitore bereits vorhanden.\n")
hinzugefuegt = 0
uebersprungen = 0
fehler = 0
with open(CSV_DATEI, encoding="utf-8-sig") as f:
reader = csv.DictReader(f, delimiter=";")
for zeile in reader:
name = zeile["#Name"].strip()
ip = zeile["IPv4"].strip()
if not name or not ip:
continue
if name in vorhandene_namen:
print(f" [SKIP] {name} ({ip}) – bereits vorhanden")
uebersprungen += 1
continue
try:
api.add_monitor(
type=MonitorType.PING,
name=name,
hostname=ip,
interval=PING_INTERVALL,
)
print(f" [OK] {name} ({ip})")
hinzugefuegt += 1
except Exception as e:
print(f" [FEHLER] {name} ({ip}): {e}")
fehler += 1
api.disconnect()
print(f"\n--- Fertig ---")
print(f"Hinzugefügt: {hinzugefuegt}")
print(f"Übersprungen: {uebersprungen}")
print(f"Fehler: {fehler}")
if __name__ == "__main__":
main()
Nun das Script ausführen:
python3 import_uptime_kuma.py
Das Ergebnis sollte in etwa so aussehen:
[OK] raum1-pc00 (192.168.1.100
...
--- Fertig ---
Hinzugefügt: 150
Übersprungen: 0
Fehler: 0
Wichtig: Das Skript prüft automatisch ob ein Monitor mit dem gleichen Namen schon existiert und überspringt ihn dann – du kannst es also problemlos mehrfach ausführen ohne Duplikate zu erzeugen.
Schritt 5: Export der Daten
Nun müssen die Daten noch exportiert werden. Dazu folgendes Export.Script erstellen und das „DB_PASSWORD“ anpassen:
nano /opt/uptime-kuma/export_uptime_kuma.py
#!/usr/bin/env python3
"""
Uptime Kuma - Online-Zeiten Export
Exportiert pro Gerät und Tag die Online-Zeiten aus der MariaDB in eine CSV-Datei.
Verwendung:
python3 export_uptime_kuma.py
Voraussetzungen:
pip3 install mysql-connector-python --break-system-packages
"""
import mysql.connector
import csv
from datetime import datetime, date
# -------------------------------------------------------
# KONFIGURATION – hier anpassen
# -------------------------------------------------------
DB_HOST = "127.0.0.1"
DB_PORT = 3306 # Standard MariaDB Port (nicht der Docker-Port!)
DB_NAME = "uptime_kuma"
DB_USER = "kuma"
DB_PASSWORD = "DATENBANK-PASSWORT"
# Zeitraum filtern (None = alles exportieren)
DATUM_VON = None # z.B. "2025-01-01"
DATUM_BIS = None # z.B. "2025-12-31"
# Ausgabedatei
AUSGABE_CSV = f"uptime_export_{date.today().strftime('%Y-%m-%d')}.csv"
# -------------------------------------------------------
def verbinden():
return mysql.connector.connect(
host=DB_HOST,
port=DB_PORT,
database=DB_NAME,
user=DB_USER,
password=DB_PASSWORD,
)
def daten_abfragen(cursor):
bedingungen = ["h.status = 1"]
parameter = []
if DATUM_VON:
bedingungen.append("DATE(h.time) >= %s")
parameter.append(DATUM_VON)
if DATUM_BIS:
bedingungen.append("DATE(h.time) <= %s")
parameter.append(DATUM_BIS)
where = " AND ".join(bedingungen)
query = f"""
SELECT
m.name AS geraet,
DATE(h.time) AS datum,
MIN(h.time) AS erstes_online,
MAX(h.time) AS letztes_online,
COUNT(*) AS ping_anzahl,
ROUND(COUNT(*) * 5 / 60.0, 1) AS online_stunden
FROM heartbeat h
JOIN monitor m ON h.monitor_id = m.id
WHERE {where}
GROUP BY m.name, DATE(h.time)
ORDER BY m.name, datum;
"""
cursor.execute(query, parameter)
return cursor.fetchall(), [d[0] for d in cursor.description]
def exportieren(zeilen, spalten):
with open(AUSGABE_CSV, "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f, delimiter=";")
writer.writerow(spalten)
writer.writerows(zeilen)
def zusammenfassung(zeilen):
geraete = set(z[0] for z in zeilen)
tage = set(z[1] for z in zeilen)
print(f" Geräte: {len(geraete)}")
print(f" Tage im Export: {len(tage)}")
print(f" Datensätze: {len(zeilen)}")
if zeilen:
print(f"\n Beispiel (erste 5 Einträge):")
print(f" {'Gerät':<20} {'Datum':<12} {'Erstes Online':<22} {'Letztes Online':<22} {'Pings':<8} {'Stunden'}")
print(f" {'-'*95}")
for z in zeilen[:5]:
print(f" {str(z[0]):<20} {str(z[1]):<12} {str(z[2]):<22} {str(z[3]):<22} {str(z[4]):<8} {z[5]}")
def main():
print("Uptime Kuma Export\n")
if DATUM_VON or DATUM_BIS:
print(f" Zeitraum: {DATUM_VON or 'Anfang'} bis {DATUM_BIS or 'heute'}")
else:
print(" Zeitraum: gesamter Verlauf")
print(f" Ausgabedatei: {AUSGABE_CSV}\n")
print("Verbinde mit MariaDB ...")
try:
conn = verbinden()
cursor = conn.cursor()
print("Verbindung erfolgreich.\n")
except Exception as e:
print(f"FEHLER bei der Verbindung: {e}")
return
print("Frage Daten ab ...")
try:
zeilen, spalten = daten_abfragen(cursor)
except Exception as e:
print(f"FEHLER bei der Abfrage: {e}")
cursor.close()
conn.close()
return
if not zeilen:
print("Keine Daten gefunden. Sind schon Monitore aktiv und Daten gesammelt worden?")
cursor.close()
conn.close()
return
print(f"{len(zeilen)} Datensätze gefunden.\n")
zusammenfassung(zeilen)
print(f"\nSchreibe CSV ...")
exportieren(zeilen, spalten)
print(f"Fertig! Datei gespeichert: {AUSGABE_CSV}")
cursor.close()
conn.close()
if __name__ == "__main__":
main()
Je nach Bedarf können auch noch die Zeiten angepasst werden, welche exportiert werden sollen:
# Nur einen bestimmten Zeitraum exportieren:
DATUM_VON = "2026-01-01"
DATUM_BIS = "2026-03-31"
# Oder alles:
DATUM_VON = None
DATUM_BIS = None
Danach liegt eine neue CSV-Datei unter /opt/uptime-kuma/