kundenplattform/README.md
Thomas Stallinger c4825acd61 feat: initiale Kundenplattform (Login + Auftragskatalog-Auswahl)
Neuer, von provisioning-server (anode) getrennter Dienst, siehe ADR-0011:
FastAPI + Jinja2, eigene Postgres-DB (benutzer-Tabelle), eigenes
Service-Token (TUXFLOTTE_KUNDENPLATTFORM_TOKEN) für die Kommunikation mit
anode. Org-Zugehörigkeits-Prüfung passiert hier in der Anwendung vor jedem
Aufruf gegen anode.

Umfang v1: Login, Geräteliste, Auftragskatalog geräteweise aus-/abwählen
(inkl. der standardbrowser-Option für Brave). systemd-Unit läuft unter
eigenem unprivilegiertem System-User statt root.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 17:00:03 +02:00

2.2 KiB

kundenplattform

Kunden-Web-UI für den Tuxflotte-Auftragskatalog — von provisioning-server (anode) bewusst getrennter Dienst, siehe ADR-0011.

Architektur

  • FastAPI + Jinja2 (serverseitig gerendert, kein Frontend-Build).
  • Eigene Postgres-Datenbank (benutzer-Tabelle: E-Mail/Passwort-Hash pro Organisation) — getrennt von provisioning-servers Datenbank, keine Cross-Database-Referenzen.
  • Spricht mit anode ausschließlich über dessen HTTP-API, authentifiziert mit einem eigenen Service-Token (TUXFLOTTE_KUNDENPLATTFORM_TOKEN, getrennt vom Admin-Token). Organisationszugehörigkeits-Prüfung (darf dieser Login auf dieses Gerät zugreifen?) passiert hier in der Anwendung, vor jedem Aufruf gegen anode — siehe find_device_in_organization() in app.py.

Setup (lokal)

python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
KUNDENPLATTFORM_DATABASE_URL=postgresql://... .venv/bin/psql ... -f migrations/0001_initial_schema.sql

Env-Variablen:

  • TUXFLOTTE_ANODE_URL (Default http://127.0.0.1:8080)
  • TUXFLOTTE_KUNDENPLATTFORM_TOKEN — muss mit dem gleichnamigen Wert in provisioning-servers /etc/tuxflotte/provisioning-server.env übereinstimmen
  • KUNDENPLATTFORM_DATABASE_URL
  • KUNDENPLATTFORM_SESSION_SECRET — beliebiger zufälliger String zum Signieren der Session-Cookie (z.B. openssl rand -base64 32)

Start: .venv/bin/uvicorn app:app --port 8081

Konto anlegen

Kein Self-Service in v1 (siehe ADR-0011) — Konten werden manuell angelegt:

KUNDENPLATTFORM_DATABASE_URL=... .venv/bin/python scripts/create_user.py \
    --organization-id <organization-uuid> \
    --email admin@schule-beispiel.de

Deploy (anode)

Wie bei provisioning-server, git-basiert statt scp:

git pull --ff-only
systemctl restart kundenplattform

Läuft unter einem eigenen, unprivilegierten System-User kundenplattform (nicht root, anders als provisioning-server) — siehe kundenplattform.service. Port 8081 (provisioning-server belegt 8080).

Öffentliche Erreichbarkeit über Pangolin ist nicht Teil dieses Repos — das ist ein separater Ops/DNS/Reverse-Proxy-Schritt.