alientimandClaude Sonnet 5 9a390e740d Gruppen-Dropdown: kompaktere Rechtetabelle, Modal bleibt unveraendert
- permission_tree() bekommt einen dritten Parameter compact=false, der
  nur im Dropdown der Hauptseite (Admin-/System-/editierbare Gruppen)
  auf true gesetzt wird, nicht im "Neue Gruppe"-Modal.
- .permission-groups-row--compact verkleinert Zeilen-/Spalten-Padding
  und die Einrueckung der Unterpunkte (32px statt 48px) NUR fuer diese
  Instanzen - das Modal behaelt exakt sein bisheriges Aussehen.
- Modal und Dropdown nutzen weiterhin denselben Code/dieselbe Struktur
  (permission_table()-Macro, Kill-Switch-Logik, JS-Gating), nur die
  Abstaende unterscheiden sich ueber die Zusatzklasse.
- Verifiziert per Screenshot: Dropdown jetzt sichtbar kompakter (engere
  Zellen, kuerzere Zeilen), Modal unveraendert; Gruppen anlegen-mit-
  Rechten und Gruppen-Bearbeiten-Regression funktionieren weiterhin.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 10:25:13 +02:00

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_required und 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.sh per SSH/expect auf 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) und fernet.key (der zugehörige Schlüssel) mit im Git-Repo eingecheckt — die .gitignore dort schließt sie über die !-Regeln versehentlich wieder ein. In diesem Rebuild sind beide Dateien in .gitignore ausgeschlossen 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 immer alles. Zusätzlich gibt es Gruppen mit einem vollständig granularen, an der Navbar gespiegelten Rechtebaum — jeder Bereich der App (nicht nur Devices/Switches) lässt sich einzeln freischalten. Ein Benutzer kann mehreren Gruppen angehören, die Rechte addieren sich (Vereinigung, nicht Schnittmenge).

Zweistufiger Rechtebaum

Der Baum hat genau zwei Ebenen, exakt gespiegelt an den drei Sidebar-Gruppen (Geräte/Logs/Einstellungen). Auf der Gruppen-Seite stehen sie als drei kompakte Spalten nebeneinander, mit einer kurzen Legende direkt darüber. Jede Spalte ist eine kleine Tabelle: die Kopfzeile enthält in EINER Zeile sowohl den Bereichsnamen mit seinem Kästchen (dem Kill-Switch, dicht nebeneinander statt an den Rand gestellt) als auch die Buchstaben-Spalten R(ead/Lesen), W(rite/Schreiben, Anlegen), E(dit/Ändern) — nur die Rechte, die dieser Bereich tatsächlich nutzt. Darunter je eine eingerückte Zeile pro Unterpunkt. „Ändern“ deckt Löschen überall mit ab — es gibt bewusst kein eigenes Löschen-Recht. Eine vierte Spalte D gibt es nur bei Geräte → Clients, und sie bedeutet dort nicht Löschen, sondern PoE-Neustart über das Dashboard-Popup auslösen (automatische Neustarts bei Ausfall über poe.sh sind davon komplett unabhängig und laufen immer). Für Zeilen ohne passendes Recht (z.B. „D“ bei Switche/ Zugangsdaten/Benutzer/Gruppen) wird eine ausgegraute, nicht anklickbare Checkbox angezeigt statt die Zelle wegzulassen:

☑ Geräte    R  W  E  D     ☑ Logs   R  W  E     ☑ Einstellungen  R  W  E
  Clients   ☑ ☑ ☑ ☑          Live   ☑ ☑ ☑         Benutzer       ☑ ☑ ☑
  Switche   ☑ ☑ ☑ ▢          Änd.   ☑ ☑ ☑         Gruppen        ☑ ☑ ☑
  Zugangsd. ☑ ☑ ☑ ▢                                Systemeinst.  ☑ ▢ ☑
                                                    Im-/Export    ☑ ▢ ☑

Das jeweilige „Bereich sichtbar“-Recht (devices_group.view / logs_group.view / settings_group.view, das Kästchen in der Kopfzeile einer Spalte) wirkt als Kill-Switch: ist es für eine Gruppe nicht gesetzt, greift kein einziges Recht darunter mehr — selbst wenn z.B. devices.view einzeln noch angehakt ist. So lässt sich ein ganzer Bereich mit einem Klick sperren, ohne jedes Unterrecht einzeln zurücknehmen zu müssen (User.has_permission() in app.py). Auf der Gruppen-Seite sind die Unterpunkt-Zeilen einer Spalte per JavaScript so lange gesperrt UND sichtbar ausgegraut (nicht nur das dezente native disabled-Styling), bis das Kopfzeilen-Kästchen angehakt ist.

Systemgruppen

Zwei Gruppen sind fest und weder umbenennbar noch in ihren Rechten änderbar (auch nicht durch Admins über die UI) — Mitgliedschaft bleibt bei beiden frei verwaltbar:

  • Admin — virtuell (kein echter groups-Datensatz), intern über den is_admin-Schalter der Benutzer gesteuert, immer alle Rechte. Mindestens ein Admin muss bestehen bleiben (serverseitig erzwungen).
  • Benutzer — die Standardgruppe (is_system-Flag), der jeder neu angelegte Nicht-Admin automatisch zugeordnet wird. Fester Rechtesatz: Geräte-Bereich + Clients/Switche lesen, Logs-Bereich + Live-Log lesen.

Alle anderen Gruppen sind vom jeweiligen Rechteinhaber (groups.edit, das auch Anlegen und Löschen von Gruppen umfasst) frei konfigurierbar.

Eskalationsschutz

Da jetzt auch Benutzer- und Gruppenverwaltung delegierbar sind (z.B. eine Gruppe mit nur users.edit, ohne Admin zu sein), gelten zusätzlich zu den granularen Rechten diese fest einprogrammierten Schranken, unabhängig davon, was eine Gruppe an Rechten hat:

  • Ein Benutzer als Admin anlegen/dazu machen (group_id=admin bei Anlegen/Zuweisen) bleibt echten Admins vorbehalten.
  • Ein bestehendes Admin-Konto bearbeiten, löschen oder ihm die Gruppe ändern bleibt echten Admins vorbehalten.
  • Wer Admin ist, wird ausschließlich über „Admin-Mitglieder verwalten“ auf der Gruppen-Seite gesteuert — bleibt admin-exklusiv, unabhängig von groups.edit.

Sowohl das Anzeigen jeder Seite als auch jede einzelne Aktion (Buttons, Formulare) ist an das jeweilige Recht gekoppelt — im Frontend ausgeblendet und im Backend serverseitig durchgesetzt, unabhängig vom Frontend.

Datenmodell: groups (inkl. is_default- und is_system-Flag), group_permissions (Gruppe → Recht), user_groups (Benutzer → Gruppe). Bestehende Datenbanken werden beim App-Start automatisch migriert (_ensure_schema() in app.py): devices.toggledevices.edit, switches.* → gespiegelte credentials.*, nachträgliches Setzen der neuen Bereichs-Rechte für bereits vergebene Unterrechte, sowie (spätere Revision) sämtliche *.delete-Rechte → *.edit (Löschen wurde nachträglich überall in Ändern gefaltet). Jede dieser Migrationen läuft nur einmalig über einen eigenen Guard in der settings-Tabelle, damit z.B. ein bewusst deaktiviertes Bereichs-Recht nicht bei jedem Neustart automatisch wieder gesetzt wird.

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.

Jeder Switch kann außerdem einen individuellen SSH-Port hinterlegen (Feld „SSH-Port“ beim Anlegen/Bearbeiten) — bleibt er leer, wird überall automatisch Port 22 angenommen (SWITCH_DEFAULT_SSH_PORT in app.py). Der Port wird konsistent an allen drei Stellen verwendet, an denen die App sich per SSH mit einem Switch verbindet: dem Web-Terminal (Verbindungstest), generate_ips.py (liefert ihn als eigenes Feld an poe.sh) und den expect-Aufrufen in poe.sh selbst (ssh -p <port> ...) für automatische wie manuelle PoE-Neustarts.

DHCP-Reservierungen & eigene Options (Systemeinstellungen → DHCP)

Erzeugt aus den vorhandenen Client-Stammdaten (MAC + IP + Name) automatisch feste DHCP-Reservierungen inkl. eigener/herstellerspezifischer Options, ohne die Daten ein zweites Mal pflegen zu müssen. Eigenes Rechtepaar settings_dhcp.view/settings_dhcp.edit, gespiegelt in der Navbar unter Einstellungen.

Backend: Kea DHCP (kea-dhcp4-server), nicht das ältere isc-dhcp-server — ISC hat isc-dhcp-server 2022 als EOL erklärt, Kea ist der aktiv weiterentwickelte Nachfolger und bildet „globaler Wert, pro Client überschreibbar“ nativ ab (siehe unten).

  • Status-Erkennung (rein lesend): shutil.which("kea-dhcp4") + systemctl is-active/is-enabled. Zeigt Version, Lauf- und Autostart-Status.
  • Installation & Dienststeuerung: eigene, jeweils einzeln bestätigte Buttons — „kea-dhcp4-server installieren“ (apt-get install -y), „Aktivieren & (neu) starten“ (systemctl enable + restart) und „Stoppen“. Bewusst nicht automatisch an „Konfiguration speichern“ oder „In Datei schreiben“ gekoppelt — ein unerwartet aktiver oder fehlkonfigurierter DHCP-Server kann ein ganzes Netzsegment stören, jede dieser Aktionen soll ein bewusster, separater Klick bleiben.
  • Netzwerk-Kopplung: Subnet, Netzmaske und Gateway werden nie manuell eingegeben, sondern bei jeder Anzeige/Generierung live aus der System-Netzwerkkonfiguration des gewählten Interfaces gelesen (_detect_interface_network(): ip -4 addr show dev <iface> + ip route show default). Die generierte Kea-Konfiguration ist dadurch immer an das Netz gekoppelt, in dem der Host tatsächlich hängt, auch wenn sich dessen IP/Subnet mal ändert — nur das Interface selbst (Dropdown, echte vorhandene Interfaces aus /sys/class/net), die Lease-Range, DNS-Server, Domain, Lease-Zeiten und der Ausgabepfad sind konfigurierbar (dhcp_*-Schlüssel in der settings-Tabelle).
  • Eigene Options (dhcp_option_defs/dhcp_option_values, analog den „Vordefinierten Optionen und Werten“ eines Windows-DHCP-Servers): Code, Name, Kea-Datentyp und Beschreibung frei definierbar (z.B. herstellerspezifische Options wie eine Terminal-Boot-URL). Jede Option hat einen globalen Wert sowie optional einen Wert pro Client — ein Client-Override überschreibt den globalen Wert ausschließlich für dieses eine Gerät (technisch: globale Werte landen im Top-Level option-data, Overrides im option-data der jeweiligen Kea-Reservierung, was Kea automatisch pro Client Vorrang geben lässt).
  • Reservierungen: für jedes aktive Gerät mit gültiger MAC + IP innerhalb des erkannten Subnets wird eine Kea-Reservierung erzeugt; der Hostname wird aus dem Gerätenamen abgeleitet (nur a-z0-9-, Kollisionen bekommen automatisch ein -2/-3-Suffix). Geräte ohne MAC/IP oder mit einer IP außerhalb des Subnets werden mit Hinweis übersprungen — Kea lehnt eine Reservierung außerhalb ihres Subnets als Konfigurationsfehler ab (mit einer echten Kea-Instanz verifiziert).
  • Schreiben: „In Datei schreiben“ (nur mit settings_dhcp.edit) schreibt die vollständige, generierte Kea-JSON-Konfiguration an den konfigurierten Ausgabepfad. Wirksam wird sie erst nach einem Dienst-Neustart über den separaten Button.

Live gegen eine echte, frisch installierte Kea-Instanz verifiziert: Installation, generierte Konfiguration besteht kea-dhcp4 -t, Dienststart übernimmt sie fehlerfrei (DHCP4_CONFIG_COMPLETE), globaler Options-Wert sowie Client-spezifischer Override erscheinen korrekt getrennt in der Konfiguration.

Ä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 → Ä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.

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=True laufen (ist bereits so konfiguriert) — für einen echten Produktivbetrieb empfiehlt sich ohnehin ein WSGI-Server mit WebSocket-Unterstützung (z.B. Gunicorn mit gevent- oder eventlet-Worker) statt des eingebauten Dev-Servers.
  • Da poe_web.service (wie im Original) als root lä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.service künftig unter einem eigenen, unprivilegierten Systembenutzer laufen zu lassen (im Original wie auch hier aktuell root, 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
S
Description
Modernes UI-Rebuild des Aruba-PoE Managers (Dashboard, Rechtesystem, Browser-SSH-Terminal)
Readme
3.1 MiB
TESM 2.0.9
Latest
2026-09-03 16:18:53 +02:00
Languages
Python 65.7%
HTML 20.6%
Shell 6.5%
CSS 4.6%
JavaScript 2.6%