- section-head: Button ("+ Neue Zugangsdaten" etc.) rutscht bei langer
Beschreibung nicht mehr in die nächste Zeile — bleibt immer rechts oben,
der Beschreibungstext wickelt stattdessen innerhalb seiner eigenen Spalte.
- Suchfeld-Icon überlappte den Platzhaltertext: eine spätere, generische
Input-Regel mit gleicher Spezifität hat die padding-left-Regel des
Lupe-Icons überschrieben (reine Reihenfolge-im-Stylesheet-Sache) — Selektor
spezifischer gemacht.
- Live-Log: Neustart-bezogene Zeilen (manueller Neustart, automatischer
PoE-Restart bei Ausfall) werden jetzt orange markiert statt farblos.
- Aufgeklappte Nav-Gruppen bleiben über Seitenwechsel hinweg erhalten
(localStorage), zusätzlich zur automatischen Aufklappung der Gruppe der
aktuell aktiven Seite.
- Datei-Auswahl (Import) im Dark Mode gestylt (Text + Button), inkl.
color-scheme-bewusster Browser-Widgets.
- Manueller "Jetzt prüfen"-Trigger (Icon neben dem globalen Timer, nur
Admins): startet rpi-check.service neu -> frisches Logfile + sofortiger
Durchlauf, Countdown synchronisiert sich auf den manuellen Zeitpunkt.
- Dashboard und Live-Log aktualisieren sich jetzt per AJAX im Hintergrund
(kein voller Seiten-Reload mehr): neue Route /dashboard/tiles liefert das
Kachel-Fragment (_dashboard_tiles.html, von index.html eingebunden und vom
Live-Update nachgeladen), get_log() liefert den aktuellen Dateinamen als
Header mit, damit die Anzeige nach einem Service-Neustart aktuell bleibt.
- Root-Cause für "Intervall bleibt immer bei 300s": in der WSL-Testumgebung
lief poe_wrapper.py nur als manuell gestarteter Hintergrundprozess statt
als echter rpi-check.service — "systemctl restart" lief dadurch ins Leere.
Echten systemd-Service in WSL eingerichtet und Intervalländerung end-to-end
verifiziert (Log-Zeilenabstand folgt jetzt dem neu gesetzten Intervall).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
PoE Manager — Modern UI Rebuild
Webbasierte Verwaltung und Monitoring von PoE-Devices und Aruba-Switchen — funktionales Rebuild von Aruba-PoE mit komplett neuem, modernem Frontend und einem granularen Rechtesystem.
Das Projekt ist ausschließlich für Linux ausgelegt (Zielsystem: eine Linux-VM). Entwickelt wird unter WSL2 (Ubuntu) unter Windows — siehe Entwicklung unter WSL weiter unten.
Die App ermöglicht:
- Öffentliches Kachel-Dashboard ohne Login — zeigt nur aktive (nicht deaktivierte) Geräte, nur Online/Offline/Gesamt-Statistik; volle Verwaltung, 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
- Verwaltung von Devices und Switches
- Zugangsdaten als eigene, wiederverwendbare Entität: SSH-Logins werden einmal angelegt und können mehreren Switchen zugeordnet werden; beim Anlegen eines Switches lassen sich bestehende Zugangsdaten auswählen oder direkt neue hinterlegen, ohne vorher zu „Zugangsdaten“ wechseln zu müssen
- Browser-SSH-Terminal beim Anlegen/Bearbeiten eines Switches, um den Host-Key zu bestätigen und die Zugangsdaten direkt zu prüfen, bevor der Switch gespeichert wird — funktioniert auf jedem Betriebssystem, die SSH-Verbindung wird dabei immer vom PoE-Server aus aufgebaut
- Manueller PoE-Neustart einzelner Geräte per Klick; bei deaktivierten Geräten bietet das Detail-Popup stattdessen direkt eine Aktivieren-Option
- Einstellbares Prüfintervall (steuert den Hintergrund-Check-Dienst) — der Countdown „Nächste Prüfung“ wird aus dem tatsächlichen letzten Log-Eintrag berechnet, nicht bei jedem Seitenaufruf neu gestartet, und läuft global in der Topbar auf jeder Seite (nicht nur im Dashboard)
- Live-Log-Ansicht mit farblicher Hervorhebung (online/offline/Neustart); Dashboard und Live-Log aktualisieren sich automatisch im Hintergrund (per AJAX, ohne vollen Seiten-Reload). Ein „Jetzt prüfen"-Icon neben dem Timer (nur Admins) startet manuell einen sofortigen Prüf-Durchlauf — der Countdown setzt sich dabei auf den manuell ausgelösten Zeitpunkt zurück
- Einheitliches Seiten-Layout: die Topbar zeigt rechts ausschließlich den „Nächste Prüfung“-Timer; Anlegen-Buttons und eine kurze Beschreibung sitzen stattdessen direkt über der jeweiligen Tabelle. Die Listen (Geräte, Switche, Zugangsdaten, Benutzer, Gruppen) sind per Klick auf die Spaltenüberschrift sortierbar
- Rechtesystem mit Gruppen: Admins dürfen immer alles (als Gruppe „Admin“ überall mit aufgeführt); normalen Benutzern lassen sich über Gruppen einzelne Verwaltungsrechte gezielt zuweisen, inkl. reiner Ansichtsrechte (siehe Rechtesystem)
- Einklappbare Sidebar (Desktop: dauerhaft, über Neuladen hinweg gemerkt; mobil: temporäres Überlagern)
- Änderungslog: jede Anlage/Bearbeitung/Löschung sowie Aktivieren/ Deaktivieren von Geräten, Switchen, Zugangsdaten, Benutzern und Gruppen wird protokolliert (wer, wann, was) — einsehbar unter „Logs → Änderungslog“; Geräte und Switche merken sich zusätzlich direkt am Datensatz, wer sie zuletzt geändert hat. PoE-Neustarts werden bewusst nicht geloggt (siehe Änderungslog)
- Verschlüsselter Import/Export: Geräte, Switche und Zugangsdaten lassen sich unter „Einstellungen → Im-/Export" als ein mit selbstgewählter Passphrase verschlüsseltes Bundle exportieren und auf einer neuen Umgebung wieder importieren (siehe Import/Export)
- Eigenes Konto: das Zahnrad-Symbol neben dem eigenen Namen unten in der Sidebar führt zu „Mein Konto“ — Vor-/Nachname, eigenes Passwort und Profilbild pflegen (siehe Eigenes Konto)
- Anpassbare Navigation: Admins legen dort zusätzlich die Reihenfolge der Sidebar-Hauptpunkte per Auf-/Ab-Buttons fest; jeder Benutzer sieht davon ohnehin nur, wofür er berechtigt ist — auch pro Unterpunkt innerhalb einer Gruppe (siehe Navigation anpassen)
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. - 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@login_requiredund zusätzlich rechtebasiert (s.u.). - Browser-SSH-Terminal für Switche, implementiert mit paramiko (reines
Python) statt eines lokalen pty + System-
ssh-Client — läuft dadurch plattformunabhängig. Die SSH-Verbindung zum Switch wird immer serverseitig (vom PoE-Server) aufgebaut, nie vom Browser/Client aus. - Granulares Rechtesystem mit Gruppen (neu, siehe unten) statt der ursprünglichen reinen Admin/User-Unterscheidung.
- Gleiche Kernlogik: Datenbankschema (erweitert um Gruppen/Rechte),
Login, PoE-Restart-Mechanismus (
poe.shper SSH/expectauf die Aruba-Switche) sind ansonsten unverändert. - Aufgeräumtes Backend: konsistente, konfigurierbare Pfade (
POE_DB_PATH,POE_SCRIPT,POE_LOG_GLOB, …) statt hart codierter/inkonsistenter Pfade; Secret-Key und Fernet-Key werden beim ersten Start automatisch generiert statt im Repo zu liegen.
⚠️ Sicherheitshinweis zum Original-Repo: Im Original sind
sqlite.db(Nutzer-Passwort-Hashes, verschlüsselte Switch-Passwörter) undfernet.key(der zugehörige Schlüssel) mit im Git-Repo eingecheckt — die.gitignoredort schließt sie über die!-Regeln versehentlich wieder ein. In diesem Rebuild sind beide Dateien in.gitignoreausgeschlossen und werden beim ersten Start frisch erzeugt. Empfehlung fürs Original-Repo: beide Dateien aus der Git-Historie entfernen und Fernet-Key sowie alle Switch-/User- Passwörter rotieren.
Rechtesystem (Gruppen & Berechtigungen)
Admins dürfen wie bisher alles, inklusive Benutzer-/Gruppen-/ Settingsverwaltung — das bleibt exklusiv Admins vorbehalten. Zusätzlich gibt es Gruppen: eine Gruppe bündelt einzelne Verwaltungsrechte, die dann normalen Benutzern zugewiesen werden können, ohne sie zu Admins zu machen. Ein Benutzer kann nur einer Gruppe/Rolle gleichzeitig zugeordnet sein (über den Button „Gruppe zuweisen“, analog zur Switch-Zuordnung bei Devices) — technisch sind mehrere Gruppen pro Benutzer möglich (Rechte würden sich addieren), die UI bildet aber bewusst nur eine 1:1-Zuordnung ab.
Auf der Gruppen-Seite (nur für Admins) werden zur Übersicht immer auch die beiden Systemrollen mit aufgeführt:
- Admin — eine feste, nicht editierbare Zeile mit allen Rechten;
Mitgliedschaft wird direkt hier verwaltet (Button „Mitglieder verwalten“),
intern über den
is_admin-Schalter der Benutzer. Mindestens ein Admin muss immer bestehen bleiben (serverseitig erzwungen). - Benutzer — die Standardgruppe, mit der alle Ansichtsrechte
(
devices.view,switches.view) vorbelegt sind. Jeder neu angelegte, nicht-admin Benutzer wird ihr automatisch zugeordnet; sie kann nicht gelöscht werden.
Jede Gruppe lässt sich über „Rechte anzeigen/bearbeiten“ aufklappen (wie ein Akkordeon) und zeigt dort die volle Checkbox-Liste; Mitglieder werden über einen eigenen Button/Modal verwaltet (nur die Anzahl steht in der Tabelle).
Verfügbare Rechte:
| Bereich | Recht | Bedeutung |
|---|---|---|
| Devices | devices.view |
Devices-Seite ansehen |
| Devices | devices.toggle |
Geräte aktivieren/deaktivieren |
| Devices | devices.create |
Geräte anlegen |
| Devices | devices.edit |
Geräte bearbeiten (inkl. Switch-Zuordnung) |
| Devices | devices.delete |
Geräte löschen |
| Devices | devices.restart |
PoE-Neustart/Aktivieren über das Dashboard |
| Switches | switches.view |
Switches- und Zugangsdaten-Seite ansehen |
| Switches | switches.create |
Switche und Zugangsdaten anlegen |
| Switches | switches.edit |
Switche und Zugangsdaten bearbeiten |
| Switches | switches.delete |
Switche und Zugangsdaten löschen |
Sowohl das Anzeigen der Devices-/Switches-Seiten als auch jede einzelne Aktion (Buttons, Toggle-Switches, Formulare) ist an das jeweilige Recht gekoppelt — im Frontend ausgeblendet und im Backend serverseitig durchgesetzt, unabhängig vom Frontend.
Datenmodell: groups (inkl. is_default-Flag), group_permissions
(Gruppe → Recht), user_groups (Benutzer → Gruppe). Bestehende Datenbanken
werden beim App-Start automatisch migriert (_ensure_schema() in app.py,
inkl. Nachrüsten der Standardgruppe und Zuordnung bestehender Benutzer ohne
Gruppe) — kein manuelles Migrations-Skript nötig.
Zugangsdaten (wiederverwendbare SSH-Logins)
Switch-Zugangsdaten (Username + verschlüsseltes Passwort) sind eine eigene
Entität (credentials-Tabelle) statt direkt am Switch zu hängen — mehrere
Switche mit demselben Login teilen sich einen Eintrag. Beim Anlegen/Bearbeiten
eines Switches lässt sich per Dropdown ein bestehender Eintrag auswählen oder
über „+ Neue Zugangsdaten anlegen“ direkt im selben Formular ein neuer
anlegen, ohne vorher zur eigenen Zugangsdaten-Seite wechseln zu müssen.
Löschen ist nur möglich, wenn kein Switch mehr auf den Eintrag verweist.
Bestehende Datenbanken aus einer älteren Version (Username/Passwort direkt
am Switch) werden beim ersten Start automatisch migriert.
Änderungslog
Jede Anlage, Bearbeitung, Löschung sowie jedes Aktivieren/Deaktivieren von
Geräten, Switchen, Zugangsdaten, Benutzern und Gruppen wird in der Tabelle
audit_log protokolliert (Zeitpunkt, Benutzer, Aktion, Ziel, Details) —
einsehbar unter Logs → Änderungslog (nur für Admins). 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.
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.
Import/Export
Unter Einstellungen lassen sich Geräte, Switche und Zugangsdaten
(inkl. entschlüsselter Passwörter) als ein einziges JSON-Bundle exportieren.
Das Bundle wird mit einem aus einer selbstgewählten Passphrase abgeleiteten
Schlüssel verschlüsselt (PBKDF2-HMAC-SHA256 + Fernet) — unabhängig vom
fernet.key dieser Installation, damit die Datei auf einer komplett neuen
Umgebung (mit eigenem, neu generiertem fernet.key) wieder eingelesen
werden kann. Gedacht für einen Umzug auf einen neuen Server.
Beim Import wird dieselbe Passphrase erneut abgefragt; Zugangsdaten werden nach Name, Switche nach Hostname und Geräte nach MAC-Adresse abgeglichen — bestehende Einträge mit gleichem Schlüssel werden aktualisiert, neue werden angelegt. Switche referenzieren ihre Zugangsdaten dabei über den Namen (nicht die interne ID), damit der Import auch bei abweichender ID-Vergabe auf dem Zielsystem korrekt verknüpft.
Eigenes Konto & Profilbild
Das Zahnrad-Symbol neben dem eigenen Namen unten in der Sidebar führt zu
„Mein Konto“ (/account): Vor-/Nachname ändern, ein Profilbild
hochladen (PNG/JPG/GIF/WEBP) und das eigene Passwort ändern (erfordert
Eingabe des aktuellen Passworts). Das ist bewusst getrennt vom Admin-Bereich
„Benutzer“, der andere Konten verwaltet. Ist ein Profilbild hinterlegt,
erscheint es statt der Initialen sowohl in der Sidebar als auch im
Änderungslog neben dem Benutzernamen. Admins sehen auf derselben Seite
zusätzlich die Navbar-Reihenfolge (siehe unten).
Navigation anpassen
Die Sidebar ist in drei aufklappbare Gruppen strukturiert:
- Geräte — Clients (die eigentlichen Devices), Switche, Zugangsdaten
- Einstellungen — Benutzer, Gruppen, Systemeinstellungen (Prüfintervall), Im-/Export
- Logs — Live, Änderungen (Änderungslog)
Die Reihenfolge dieser drei Gruppen (und von „Dashboard“) ist für Admins
unter Mein Konto (Zahnrad-Symbol in der Sidebar) per Auf-/Ab-Buttons
konfigurierbar (gespeichert als JSON-Liste unter settings.nav_order) und
gilt global für alle Benutzer. Unabhängig von der Reihenfolge sieht jeder
Benutzer ohnehin nur, wofür er berechtigt ist — sowohl auf Gruppenebene als
auch pro Unterpunkt: hat ein Benutzer z.B. nur devices.view, erscheint die
Gruppe „Geräte“ nur mit dem Unterpunkt „Clients“ (ohne Switche/
Zugangsdaten); eine Gruppe verschwindet komplett, wenn kein Unterpunkt
sichtbar ist.
Entwicklung unter WSL
Da das Projekt ausschließlich für Linux gebaut ist, empfiehlt sich die
Entwicklung direkt unter WSL2 (Ubuntu), auch wenn der Editor unter Windows
läuft — das Projektverzeichnis liegt dabei ganz normal unter
C:\...\aruba-poe-modern und wird aus WSL über /mnt/c/... erreicht:
wsl --install -d Ubuntu # einmalig, falls noch nicht vorhanden
wsl -d Ubuntu
sudo apt update && sudo apt install -y python3 python3-venv python3-pip sqlite3 expect openssh-client
cd /mnt/c/Users/<dich>/aruba-poe-modern/srv/poe_manager
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
./venv/bin/python create_db.py
./venv/bin/python create_admin.py
./venv/bin/python app.py # http://localhost:5000 — via WSL2-Portweiterleitung
# auch aus dem Windows-Browser erreichbar
Hinweis zu rpi-check.service: Der „Speichern & Service neustarten“-Button
unter Systemeinstellungen sowie das „Jetzt prüfen“-Icon funktionieren nur,
wenn rpi-check.service tatsächlich als echter systemd-Service läuft (viele
aktuelle WSL2-Installationen unterstützen systemd, siehe wsl.conf
[boot] systemd=true). Für lokale Tests reicht es, etc/systemd/system/ rpi-check.service sowie usr/local/bin/custom/poe.sh per Symlink an ihre
Produktivpfade (/etc/systemd/system/, /usr/local/bin/custom/) zu legen
und /srv/poe_manager auf den Checkout zu verlinken, dann systemctl daemon-reload && systemctl enable --now rpi-check.service. Ohne systemd
(z.B. systemctl nicht vorhanden) scheitert der Neustart-Aufruf lautlos —
das Intervall in der DB wird trotzdem aktualisiert, greift dann aber erst
nach einem manuellen Neustart des Prozesses.
Lokal starten (Entwicklung)
cd srv/poe_manager
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python create_db.py # legt sqlite.db + Tabellen an
python create_admin.py # legt ersten Admin-Benutzer an
python app.py # http://localhost:5000
Produktiv-Deployment (auf der Ziel-VM, App landet unter /srv/poe_manager)
Das Repo wird bewusst nicht direkt nach /srv/poe_manager geklont —
install.sh kopiert (rsync) den Inhalt von srv/poe_manager/ aus dem Repo
gezielt dorthin und lässt Quell-Checkout und Zielverzeichnis damit sauber
getrennt (kein doppeltes /srv/poe_manager/srv/poe_manager/…):
sudo git clone <dieses-repo> /opt/aruba-poe-modern-src
cd /opt/aruba-poe-modern-src
sudo bash install.sh
sudo /srv/poe_manager/venv/bin/python3 /srv/poe_manager/create_admin.py
Nach der Installation liegt die laufende App vollständig unter
/srv/poe_manager (so wie es poe_web.service, rpi-check.service und
POE_SCRIPT/POE_DB_PATH als Default erwarten) — /opt/aruba-poe-modern-src
wird nur als Checkout-Quelle für install.sh gebraucht und kann danach
liegen bleiben (für spätere Updates: git pull dort, dann install.sh
erneut ausführen) oder gelöscht werden.
install.sh installiert Systempakete, richtet die venv ein, initialisiert die
Datenbank (falls nicht vorhanden), kopiert poe.sh nach
/usr/local/bin/custom/, registriert die systemd-Units
(poe_web.service, rpi-check.service, rpi-check-restart.timer) und
konfiguriert nginx als Reverse-Proxy auf Port 80.
Relevante Umgebungsvariablen (optional)
| Variable | Zweck | Default |
|---|---|---|
POE_DB_PATH |
Pfad zur SQLite-DB | <app-dir>/sqlite.db |
POE_SCRIPT |
Pfad zum PoE-Restart-Skript | /usr/local/bin/custom/poe.sh |
POE_LOG_GLOB |
Glob-Pattern der Check-Logs | /var/log/rpi-*.log |
POE_FERNET_KEY |
Pfad zum Fernet-Schlüssel | <app-dir>/fernet.key (auto-erzeugt) |
POE_KNOWN_HOSTS |
Pfad zur SSH-known_hosts-Datei des Terminals | <app-dir>/known_hosts (auto-erzeugt) |
POE_SECRET_KEY |
Flask Secret Key (überschreibt Datei) | zufällig, in secret.key gespeichert |
PORT, FLASK_DEBUG |
Flask-Serverport / Debug-Modus | 5000 / aus |
Browser-SSH-Terminal (Switch-Verbindungstest)
„Verbindung testen“ im Switch-Modal öffnet eine WebSocket-Verbindung zu
/ws/ssh_terminal. Serverseitig baut paramiko eine echte SSH-Sitzung
zum Switch auf (inkl. interaktiver Host-Key-Bestätigung beim Erstkontakt,
danach dauerhaft in known_hosts gemerkt) und reicht eine interaktive Shell
1:1 an ein xterm.js-Terminal im Browser durch. Die Zugangsdaten aus dem
Formular werden direkt für die SSH-Authentifizierung verwendet (nicht als
Tastatureingabe in die Shell getippt) — Erfolg/Fehlschlag der Anmeldung wird
sofort und eindeutig im Terminal angezeigt. Ein Klick auf „Passwort
einfügen“ sendet den aktuell im Formular eingetragenen Wert zusätzlich als
Tastatureingabe (z.B. für ein sudo-Passwort in der geöffneten Sitzung).
Voraussetzungen:
- Läuft auf jedem Betriebssystem (paramiko ist reines Python) — die SSH-Verbindung wird dabei immer vom PoE-Server aus aufgebaut, nie vom Browser/Client.
- Nur für eingeloggte Admins erreichbar.
- Der Flask-Entwicklungsserver muss mit
threaded=Truelaufen (ist bereits so konfiguriert) — für einen echten Produktivbetrieb empfiehlt sich ohnehin ein WSGI-Server mit WebSocket-Unterstützung (z.B. Gunicorn mitgevent- odereventlet-Worker) statt des eingebauten Dev-Servers. - Da
poe_web.service(wie im Original) alsrootläuft, kann über dieses Terminal im Prinzip jeder erreichbare Host per SSH kontaktiert werden — bewusst so gewählt, da Admins über die App ohnehin schon vollen Zugriff auf alle hinterlegten Switch-Zugangsdaten haben. Für eine strengere Trennung empfiehlt es sich,poe_web.servicekünftig unter einem eigenen, unprivilegierten Systembenutzer laufen zu lassen (im Original wie auch hier aktuellroot, um Änderungen am produktiven Setup nicht zu vergrößern).
Projektstruktur
srv/poe_manager/ Flask-App (Backend + Templates + Static-Assets)
usr/local/bin/custom/ poe.sh — Ping-Check & PoE-Restart per SSH (expect)
etc/systemd/system/ Service-/Timer-Units (Web-App + Check-Dienst)
etc/nginx/ Reverse-Proxy-Konfiguration
install.sh Produktiv-Installer