Logging & Log-Rotation, Zeitzone, Dashboard-UX, Design-Politur

Logging-Infrastruktur (Logs können nach einem Import mit vielen Geräten
schnell vollaufen):
- Vier eigene, rotierte Log-Dateien statt allem in /var/log vermischt:
  Live (poe.sh, jetzt eine einzige durchgehend fortgeschriebene Datei
  statt vorher ein neues rpi-<timestamp>.log pro Dienst-Neustart),
  Änderungen (Spiegel der audit_log-Tabelle), App (Flask-Fehler/
  Warnungen, vorher nur im journalctl-Output), Kea-DHCP (eigene
  Logging-Konfiguration in der generierten kea-dhcp4.conf)
- Kea-DHCP-Log bewusst NICHT im gemeinsamen Verzeichnis: Keas
  AppArmor-Profil erlaubt Schreibzugriff exklusiv auf
  /var/log/kea/kea-dhcp4.log (kein Verzeichnis-Wildcard) -- live als
  "DENIED ... mknod ... .lock" reproduziert; die App nutzt Keas eigenen,
  bereits erlaubten Pfad statt das AppArmor-Profil eines Systemdienstes
  aufzuweichen. logrotate deckt trotzdem beide Verzeichnisse mit einer
  Regel ab
- Neue Log-Seite "Kea-DHCP" (Logs-Bereich, eigenes Recht logs_kea.view)
- Rotation (Intervall täglich/wöchentlich/monatlich, Aufbewahrung als
  Anzahl Rotationen) unter Systemeinstellungen → Logs einstellbar,
  generiert /etc/logrotate.d/poe-manager; copytruncate, da keiner der
  drei schreibenden Prozesse ein Reopen-Signal implementiert
- Einmalige Migration räumt alte, verwaiste rpi-*.log-Dateien auf

Zeitzone (Systemeinstellungen, mit Hostname in einer Kachel "Host"):
setzt die System-Zeitzone per timedatectl, damit Logs/Änderungsverlauf
die tatsächliche lokale Zeit statt UTC zeigen. time.tzset() direkt nach
dem Setzen lässt die bereits laufende poe_web.service-Instanz die neue
Zeitzone sofort übernehmen, ohne Neustart.

Systemeinstellungen neu sortiert: Host + Netzwerkeinstellungen (beide
Host-Konfiguration) nebeneinander, dann Logs, dann Prüfintervall.

Netzwerkeinstellungen: DNS-Anzeige zeigte bisher den lokalen
systemd-resolved-Stub (127.0.0.53) aus /etc/resolv.conf statt der
echten Server -- jetzt über "resolvectl dns <interface>", inkl. Fix
für eine falsch geparste IPv6-Fortsetzungszeile ohne Label, und
gefiltert auf IPv4 (diese Seite verwaltet nur IPv4-Konfiguration, per
IPv6-Router-Advertisement gelernte Server sind hier irreführend).

Dashboard: die vier Stat-Kacheln (Online/Offline/Deaktiviert/Gesamt)
sind jetzt klickbare Filter (blenden alle anderen Abschnitte aus, Klick
auf die aktive Kachel oder "Gesamt" hebt den Filter auf); jeder
Abschnitt lässt sich unabhängig davon per Klick auf seinen Titel ein-/
ausklappen. Beide Zustände bleiben über die automatischen Live-Updates
hinweg erhalten.

Design-Politur:
- Hauptinhaltsbereich nutzt jetzt die volle verfügbare Breite (kein
  Bootstrap-typisches festes max-width mehr) -- Modals bleiben bewusst
  bei ihrer kompakten, festen Breite
  Akzentfarbe exakt auf das Orange aus dem WiS-Logo abgestimmt
  (#ff7100, per Pixel-Sampling ermittelt) statt einer nur ähnlichen,
  frei gewählten Nuance
- Abmelden führt zurück auf das (auch ohne Login einsehbare) Dashboard
  statt auf die Login-Seite

Live gegen die echte Test-VM verifiziert: alle vier Logs werden
geschrieben, logrotate-Konfiguration korrekt generiert, ein
Zeitzonenwechsel (UTC → Europe/Berlin) wirkte sofort, DNS-Anzeige zeigt
jetzt die echten IPv4-Server (1.1.1.1, 8.8.8.8) statt Stub/IPv6,
Dashboard-Filter/-Collapse und Logout-Redirect per Playwright bestätigt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-12 13:30:56 +02:00
co-authored by Claude Sonnet 5
parent d525ef2e0a
commit 7b30ebce7b
9 changed files with 714 additions and 93 deletions
+93 -7
View File
@@ -15,7 +15,18 @@ Die App ermöglicht:
Aktivieren/Deaktivieren und PoE-Neustart bleiben hinter dem Login. Eingeloggt
sind zusätzlich deaktivierte Geräte sichtbar (eigene Kachel-Sektion). Alle
Kacheln sind durchsuchbar und in drei Abschnitten sortiert: Offline, Online,
Deaktiviert — jeweils alphabetisch
Deaktiviert — jeweils alphabetisch. Die vier Stat-Kacheln oben (Online/
Offline/Deaktiviert/Gesamt) sind klickbare Filter — ein Klick blendet alle
anderen Abschnitte aus, „Gesamt“ oder ein erneuter Klick auf die aktive
Kachel hebt den Filter wieder auf. Jeder Abschnitt lässt sich unabhängig
davon per Klick auf seinen Titel ein-/ausklappen (z.B. um eine lange
Offline-Liste vorübergehend zu verstecken, ohne den Filter zu nutzen) —
beide Zustände bleiben über die automatischen Live-Updates hinweg erhalten.
Abmelden führt zurück auf dieses (auch ohne Login einsehbare) Dashboard
statt auf die Login-Seite
- Der Hauptinhaltsbereich nutzt die **volle verfügbare Breite** (kein
Bootstrap-typisches, festes `max-width` mehr) — nur Modals/Dialoge behalten
bewusst ihre kompakte, feste Breite
- Verwaltung von Devices und Switches
- **Zugangsdaten als eigene, wiederverwendbare Entität**: SSH-Logins werden
einmal angelegt und können mehreren Switchen zugeordnet werden; beim
@@ -76,11 +87,16 @@ Die App ermöglicht:
## Was ist neu gegenüber dem Original?
- **Komplett neues Frontend**: eigenes Design-System (kein Bootstrap mehr),
Logo mittig in der Topbar (auf jeder Seite, skaliert auf die Balkenhöhe),
Sidebar-Navigation (nur für eingeloggte Nutzer sichtbar), Dark/Light-
Umschalter, Karten-Dashboard mit Live-Zählern, moderne Modals/Toasts statt
Browser-`confirm()` und Bootstrap-Alerts.
- **Komplett neues Frontend**: eigenes Design-System (kein Bootstrap mehr
der Hauptinhaltsbereich nutzt bewusst die volle verfügbare Breite statt
eines festen, Bootstrap-typischen `max-width`; nur Modals/Dialoge behalten
ihre kompakte, feste Breite), Logo mittig in der Topbar (auf jeder Seite,
skaliert auf die Balkenhöhe), Sidebar-Navigation (nur für eingeloggte
Nutzer sichtbar), Dark/Light-Umschalter, Karten-Dashboard mit Live-Zählern,
moderne Modals/Toasts statt Browser-`confirm()` und Bootstrap-Alerts. Der
Akzent-Ton (`--accent` in `style.css`) ist exakt das Orange aus dem
WiS-Logo (`#ff7100`, per Pixel-Sampling aus `logo.png` ermittelt), nicht
nur eine ähnliche, frei gewählte Nuance.
- **Dashboard jetzt teilweise öffentlich**: `/` ist ohne Login erreichbar und
zeigt eine reduzierte Lese-Ansicht (Hostname, IP, Status, letzte Prüfung)
mit Login-Button; alle Verwaltungsseiten und der PoE-Neustart bleiben
@@ -546,6 +562,18 @@ da eine Änderung nicht die Erreichbarkeit kappt).
`interface`-Block von `/etc/dhcpcd.conf`, bzw. bei netplan am `dynamic`-Flag
des Kernels auf der aktuellen Adresse — zuverlässiger als die u.U. mehreren
überlagernden YAML-Dateien unter `/etc/netplan/` selbst zu parsen).
**DNS-Server-Anzeige**: nicht aus `/etc/resolv.conf` gelesen — unter
systemd-resolved (Standard auf aktuellem Ubuntu) steht dort immer nur der
lokale Stub-Resolver `127.0.0.53`, nie die echten Upstream-Server (live
genau so reproduziert). Stattdessen `resolvectl dns <interface>`, dessen
mehrzeilige Ausgabe bei vielen Servern korrekt geparst wird (eine
Fortsetzungszeile ohne `Link N (iface):`-Label trägt selbst
Doppelpunkte — eine IPv6-Adresse — ein naives Aufteilen an jedem
Doppelpunkt hätte sie sonst am Anfang abgeschnitten, live genau so
reproduziert und gefixt). Zusätzlich auf **IPv4** gefiltert, da diese
Seite ausschließlich die IPv4-Konfiguration des Hosts verwaltet — von
`resolvectl` ungefragt mitgelieferte, per IPv6-Router-Advertisement
gelernte DNS-Server gehören nicht dazu und wären hier nur irreführend.
- **Änderung**: Interface, Modus (DHCP/Statisch), bei Statisch zusätzlich
IP/Prefix/Gateway, sowie unabhängig davon eigene DNS-Server (funktioniert
in beiden Modi — z.B. IP per DHCP, aber feste DNS-Server). Bei netplan
@@ -587,13 +615,71 @@ Geräten, Switchen, Zugangsdaten, Benutzern und Gruppen wird in der Tabelle
einsehbar unter **Logs → Änderungen** (Recht `logs_activity.view`). Zusätzlich merken
sich Geräte und Switche direkt am Datensatz (`last_modified_by`,
`last_modified_at`), wer sie zuletzt geändert hat, damit man das nicht erst
im Log nachschlagen muss.
im Log nachschlagen muss. Jeder Eintrag wird zusätzlich in eine eigene Datei
gespiegelt (siehe [Logs & Log-Rotation](#logs--log-rotation)) — die
`audit_log`-Tabelle bleibt dabei die Quelle für diese durchsuchbare/
sortierbare Seite.
PoE-Neustarts werden **bewusst nicht** im Änderungslog erfasst — die stehen
bereits im Live-Log von `poe.sh`. Eine Ausnahme ist die Änderung des
Prüfintervalls selbst (eine Einstellungsänderung, kein Neustart), die wird
mitprotokolliert.
## Logs & Log-Rotation
Vier getrennte, eigene Log-Dateien statt allem in `/var/log` vermischt oder
nur im journalctl-Output — jede mit derselben, unter **Systemeinstellungen →
Logs** einstellbaren Rotation (Intervall täglich/wöchentlich/monatlich,
Standard wöchentlich; Aufbewahrung als Anzahl Rotationen, Standard 4 ≈ 1
Monat Historie):
| Log | Datei | Einsehbar unter |
|-----|-------|------------------|
| Live (Ping-Check/PoE-Neustart) | `/var/log/poe-manager/live.log` | Logs → Live |
| Änderungen (Audit-Trail) | `/var/log/poe-manager/changes.log` | Logs → Änderungen (aus der DB) |
| App (Fehler/Warnungen der Flask-App) | `/var/log/poe-manager/app.log` | nur Datei, keine eigene Seite |
| Kea-DHCP | `/var/log/kea/kea-dhcp4.log` | Logs → Kea-DHCP (Recht `logs_kea.view`) |
- **Live-Log ist jetzt eine einzige, durchgehend fortgeschriebene Datei**
statt vorher bei jedem (auch täglich per `rpi-check-restart.timer`
automatisch ausgelösten) Dienst-Neustart ein neues `rpi-<timestamp>.log`
`poe.sh` räumt nicht mehr selbst nach 30 Tagen auf, das übernimmt jetzt
zentral logrotate. Bestehende alte `rpi-*.log`-Dateien werden beim ersten
Start dieser Version einmalig aufgeräumt (Migration).
- **Kea-DHCP-Log liegt bewusst NICHT unter `/var/log/poe-manager/`**: Keas
AppArmor-Profil (`/etc/apparmor.d/usr.sbin.kea-dhcp4`) erlaubt
Schreibzugriff exklusiv auf den Dateinamen `/var/log/kea/kea-dhcp4.log`
(kein Verzeichnis-Wildcard) — ein anderer Pfad wird mit `DENIED ... mknod
... .lock` abgelehnt (live so reproduziert). Statt das AppArmor-Profil
eines Systemdienstes aufzuweichen, nutzt die App Keas eigenen, bereits
erlaubten Pfad; die logrotate-Konfiguration deckt trotzdem beide
Verzeichnisse mit derselben Regel ab.
- **`copytruncate` statt Signal-/Neustart-basierter Rotation**: keiner der
drei schreibenden Prozesse (`poe.sh`, Flask, `kea-dhcp4-server`)
implementiert ein Log-Reopen-Signal (SIGHUP o.ä.) — `copytruncate`
funktioniert ohne jede Kooperation des schreibenden Prozesses und läuft
als root, ist also auch von Keas AppArmor-Profil nicht betroffen.
- **App-Log** (`app.log`) fängt Fehler/Warnungen der Flask-App ab (vorher
nur im journalctl-Output von `poe_web.service` sichtbar, ohne von der App
selbst kontrollierbare Aufbewahrung) — bewusst nur `WARNING` und höher,
kein Access-/Request-Rauschen.
- **Zeitzone** (Systemeinstellungen, zusammen mit dem Hostnamen in der
Kachel „Host“): setzt die System-Zeitzone per `timedatectl
set-timezone`, damit alle vier Logs sowie das Änderungslog die
tatsächliche lokale Zeit statt UTC zeigen. Wirkt über `time.tzset()`
sofort für die bereits laufende `poe_web.service`-Instanz (kein
Neustart nötig) — `poe.sh`/`date` liest die Zeitzone ohnehin bei jedem
Prüf-Durchlauf frisch, da es ein neuer Prozess pro Durchlauf ist.
- **Systemeinstellungen neu sortiert**: Host (Hostname + Zeitzone in einer
Kachel) und Netzwerkeinstellungen stehen als thematisch zusammengehörige
Host-Konfiguration nebeneinander, gefolgt von Logs und Prüfintervall.
Live verifiziert: alle vier Log-Dateien werden geschrieben, die
logrotate-Konfiguration korrekt generiert und bei einer Änderung der
Einstellung neu geschrieben, ein Zeitzonenwechsel (UTC → Europe/Berlin)
wirkte sofort — die Log-Zeile, die den Wechsel selbst protokolliert, trug
bereits den neuen Zeitstempel.
## Import/Export
Unter **Einstellungen** lassen sich Geräte, Switche und Zugangsdaten