{% extends "admin/layout.html" %} {% block title %}{{ organization.name if organization else organization_id }} — Tuxflotte Admin{% endblock %} {% block admin_content %}

← Organisationen

{{ organization.name if organization else organization_id }}

{% include "admin/_kunden_nav.html" %} {% if aktiver_tab == "organisationsdaten" %} {# GUI-Runde 23.10.2026: Hostnamenkonvention und Ressourcen waren eigene Reiter; jetzt aufklappbare Abschnitte, ein Anker (#hostname, #ressourcen, #einstufung) klappt den passenden nach dem Speichern auf. #} {% set kg = (kundengruppen or []) | selectattr("id", "equalto", organization.kundengruppe_id if organization else none) | first %}
Kontakt und Notizen {{ organization.kontakt_name or "" if organization else "" }}
Kundengruppe, Ausrollstufe, Workspace-Creator {{ kg.name if kg else "keine Kundengruppe" }} · {{ "Vorab" if organization and organization.ausrollstufe == "vorab" else "Testing" }} · Creator {{ "frei" if workspace_creator_frei else "gesperrt" }}

Kundengruppe

Legt fest, welche Vorlagen-Workspaces die Organisation sieht und zuweisen kann. Ohne Kundengruppe sieht sie nur global freigegebene Vorlagen.

Ausrollstufe

Legt fest, welchen Stand der Rollen die Geräte dieser Organisation beim Check-in ziehen. Testing: Änderungen, die nach den Vorab-Tests freigegeben sind (Standard, Testschulen). Vorab: jede Änderung sofort (nur Tuxflotte: Testlab, Liebherr). „Stabil“ für zahlende Kunden, die selbst über das Einspielen entscheiden, folgt später. Die Umstellung wirkt beim nächsten Check-in der Geräte.

Workspace-Creator

Freigeschaltet können die Kunden-Admins dieser Organisation unter „Workspace“ eigene Workspaces erstellen, bearbeiten, veröffentlichen und unter „Organisation › Struktur“ ihren OEs zuweisen. Gesperrt sehen sie nur, welche Workspaces für sie bereitstehen, und tuxflotte richtet alles ein.

Hostnamenkonvention {{ (hostname_konvention.praefix if hostname_konvention else none) or "tuxflotte" }}-{{ "0" * ((hostname_konvention.stellen if hostname_konvention else 4) - 1) }}1 · {{ "zufällig" if hostname_konvention and hostname_konvention.nummer_modus == "zufaellig" else "sequenziell" }}

Legt fest, wie Geräte dieser Organisation bei der Installation automatisch benannt werden ("<Präfix>-<Nummer>"). Leerer Präfix = Standard "tuxflotte". Ein bereits bekanntes Gerät behält bei einer Neuinstallation seinen Namen, wenn er zur Konvention passt; sonst bekommt es einen neuen.

{% if hostname_konvention %}

Nächste sequenzielle Nummer: {{ hostname_konvention.naechste_sequenz }} (nur relevant im sequenziellen Modus)

{% endif %}
Ressourcen {{ ressourcen | length }} eingerichtet{% if not ressourcen_freigeschaltet %} · noch nicht freigeschaltet{% endif %} {% if not ressourcen_freigeschaltet %}

Für diese Organisation noch nicht freigeschaltet (Ausrollstufe „Testing“): die Ressourcen werden gespeichert, aber nicht an Geräte verteilt, und die Kunden-Seite ist ausgeblendet.

{% endif %} {% set basis_url = "/admin/kunden/" ~ organization_id ~ "/ressourcen" %} {% set darf_bearbeiten = true %} {% include "_ressourcen.html" %}
{# Entscheidung A (25.10.2026): archivieren statt löschen. #}
Organisation archivieren {% if request.query_params.get("archiv_fehler") %}

{{ request.query_params.get("archiv_fehler") }}

{% endif %}

Die Organisation verschwindet aus allen Listen. Ihre Kunden-Konten können sich nicht mehr anmelden, Installationsmedien und Aktivierungscodes werden ungültig, laufende Einladungen zur Personalisierung zurückgezogen. Die Daten bleiben für den Verlauf erhalten. Geht nur, wenn alle Geräte gelöscht sind; die lassen sich danach in einer anderen Organisation neu installieren.

{% endif %} {% if aktiver_tab == "diagnosezugang" %}

Richtet auf Geräten, die mit einem danach erstellten Installationsmedium installiert werden, einen root-Zugang ein (per SSH, ohne „Konsolenwechsel sperren“ auch an der Konsole). Nur für die Fehlersuche gedacht. Das Passwort ist ausschließlich hier im Admin-Bereich sichtbar, auf das Installationsmedium gelangt nur sein Hash. Ausschalten wirkt nur auf neu erstellte Installationsmedien.

Bereits installierte Geräte: Dort sperrt das Härtungs-Merkmal „Diagnosezugang sperren“ (Workspace, OE oder Gruppe) den Zugang – root-Passwort gesperrt, SSH aus. Abwählen stellt ihn wieder her. Hinweis: Das Merkmal „Konsolenwechsel sperren“ nimmt die Anmeldung an der Textkonsole weg; der Diagnosezugang geht dann nur per SSH.

{% if diagnosezugang.aktiv %}

Status: aktiv

Benutzer: root
Passwort: {{ diagnosezugang.passwort or "— (nicht lesbar)" }}

Ein neues Passwort gilt nur für danach erstellte Installationsmedien – vorhandene Medien und Geräte behalten das alte.

{% else %}

Status: aus

{% endif %}
{% endif %} {% if aktiver_tab == "aktivitaeten" %} {# GUI-Runde 23.10.2026: früherer Reiter "Flows" #} {% if unassigned_devices %}

Unbestätigte Geräte

Geräte ohne Bereitstellungsvorlagen-Zuweisung. Bestätigung setzt eine Vorlage und schaltet die Installation frei (deckt den serverseitigen Teil aus ADR-0008 ab, nicht das Installer-seitige Warten im Auto-Modus).

{% for device in unassigned_devices %} {% endfor %}
{{ device.hostname or device.device_fingerprint }} {{ device.created_at | datum }}
{% endif %} {% macro session_tabelle(sessions) %}
{% for es in sessions %} {% endfor %}
ErstelltVorlageGeräteLäuft abStatus
{{ es.created_at | datum }} {{ es.bereitstellungsvorlage_label }} {{ es.devices_used }} / {{ es.max_devices }} {{ es.expires_at | datum }} {{ es.status }} {% if not es.revoked_at %}
{% endif %}
{% endmacro %}
{% set gueltig = enrollment_sessions | selectattr("status", "equalto", "gültig") | list | length %}
Ausgegebene Medien {{ enrollment_sessions | length }} insgesamt, {{ gueltig }} gültig

Je erstelltem Installationsmedium eine Enrollment Session, neueste zuerst. Ein neues Medium macht ältere nicht ungültig (Entscheidung 22.10.2026); „Widerrufen“ sperrt ein Medium für weitere Installationen.

{% if enrollment_sessions %} {{ session_tabelle(enrollment_sessions) }} {% else %}

Noch keine Enrollment Sessions.

{% endif %}
Neue Enrollment Session anlegen

Aktivitäten

Installationen und Agent-Läufe der Geräte dieser Organisation, neueste zuerst (die letzten {{ aktivitaeten_abruf }} Ereignisse). Ein Agent-Lauf prüft alle Merkmale eines Geräts. Läufe ohne Fehler stehen je Gerät und Tag in einer Zeile, Fehler und Installationen einzeln und markiert.

{% if aktivitaeten_tage %}
{% for tag in aktivitaeten_tage %}
{{ tag.titel }} ({{ tag.eintraege | length }}{% if tag.fehler %}, {{ tag.fehler }} mit Fehler{% endif %})
{% for a in tag.eintraege %} {% endfor %}
ZeitGerätEreignis
{{ (a.zeit | datum)[-5:] }} {{ a.hostname }} {% if a.problem %}{{ a.text }}{% else %}{{ a.text }}{% endif %}{% if a.laeufe > 1 %} ({{ a.laeufe }} Läufe an diesem Tag, hier der letzte){% endif %}
{% endfor %} {% else %}

Noch keine Aktivitäten protokolliert.

{% endif %}
{% endif %} {% if aktiver_tab == "bereitstellungsvorlagen" %}
{% if vorlage_fehler %}

{{ vorlage_fehler }}

{% endif %} {% if bearbeiten %} {# GUI-Runde 09.10.2026: Bearbeiten einer bestehenden Vorlage #}

← alle Bereitstellungsvorlagen

„{{ bearbeiten.label }}“ bearbeiten

{% if bearbeiten.geraete_anzahl or bearbeiten.medien_anzahl %}

Wird verwendet von {{ bearbeiten.geraete_anzahl }} Gerät(en) und {{ bearbeiten.medien_anzahl }} Installationsmedium/-medien. Änderungen gelten für künftige Installationen und für den Workspace dieser Geräte, sofern ihre OE keinen eigenen Workspace hat.

{% endif %} {% set v = bearbeiten %} {% set aktion = "/admin/kunden/" ~ organization_id ~ "/bereitstellungsvorlagen/" ~ bearbeiten.id %} {% set knopf = "Änderungen speichern" %} {% include "admin/_bereitstellungsvorlage_formular.html" %}

Löschen

{% if bearbeiten.geraete_anzahl or bearbeiten.medien_anzahl %}

Nicht möglich, solange Geräte oder Installationsmedien die Vorlage verwenden.

{% else %}
Vorlage löschen
{% endif %} {% else %}

Bereitstellungsvorlage oder Workspace? Die Bereitstellungsvorlage regelt die Installation: Distro, Partitionierung, Verschlüsselung und mit welchem Workspace das Gerät startet. Sie wirkt nur einmal, beim Installieren. Der Workspace regelt den Inhalt: Programme, Einstellungen, Merkmale. Ihn hält der Agent auf dem Gerät dauerhaft aktuell; hat die OE des Geräts einen eigenen Workspace (gleiche Distro), gilt dieser. Zum Bearbeiten oder Löschen auf die Bezeichnung klicken.

{% if bereitstellungsvorlagen %}
{% for v in bereitstellungsvorlagen %} {% set ws_distro = (workspace_distro.get(v.workspace.id) or {}) %} {% endfor %}
BezeichnungWorkspaceDistro PartitionierungStandardGeräteMedien
{{ v.label }} {{ v.workspace.name }} {{ v.backend.name }} {{ v.backend.version }} {% if ws_distro and ws_distro.id != v.backend.id %}
passt nicht zum Workspace ({{ ws_distro.name }}){% endif %}
{{ v.partitioning.root_filesystem }} {% if v.partitioning.scheme == "custom" and v.partitioning.extra_partitions %} + {% for p in v.partitioning.extra_partitions %}{{ p.mountpoint }} {{ p.percent }} %{{ ", " if not loop.last else "" }}{% endfor %} {% endif %} {% if v.disk_encryption %}
verschlüsselt{% endif %} {% if v.secure_boot_required %}
Secure Boot{% endif %}
{{ "ja" if v.is_default else "–" }} {{ v.geraete_anzahl }} {{ v.medien_anzahl }}
{% else %}

Noch keine Bereitstellungsvorlagen.

{% endif %} Neue Bereitstellungsvorlage anlegen {% set v = None %} {% set aktion = "/admin/kunden/" ~ organization_id ~ "/bereitstellungsvorlagen" %} {% set knopf = "Anlegen" %} {% include "admin/_bereitstellungsvorlage_formular.html" %} {# GUI-Runde 09.10.2026: Gültigkeit, Nutzung, Deaktivieren/Löschen #}

Aktivierungscodes

Für Installationen ohne persönliches Installationsmedium (allgemeines Boot-Medium, Lokal-Test): Der Code wird im Installer eingetippt und ordnet das Gerät dieser Organisation zu; die Bereitstellungsvorlage wählt man danach im Installer aus (vorausgewählt ist die Standard-Vorlage). Medien, die der Kunde unter „Installationsmedium“ erstellt, brauchen keinen Code: Sie tragen ihre Vorlage schon in sich. Deaktivierte oder abgelaufene Codes werden abgelehnt; bereits installierte Geräte bleiben davon unberührt.

{% if activation_codes %}
{% for ac in activation_codes %} {% endfor %}
CodeBezeichnungStatusGültig bisVerwendetAngelegtAktionen
{{ ac.code }} {{ ac.bezeichnung or "–" }} {% if not ac.active %}deaktiviert {% elif ac.abgelaufen %}abgelaufen {% else %}aktiv{% endif %} {{ ac.gueltig_bis | datum(False) if ac.gueltig_bis else "unbegrenzt" }} {% if ac.verwendet_anzahl %}{{ ac.verwendet_anzahl }}× · {{ ac.zuletzt_verwendet | datum(False) }}{% else %}noch nie{% endif %} {{ ac.created_at | datum(False) }}
Löschen
{% else %}

Noch keine Aktivierungscodes.

{% endif %}
Neuen Aktivierungscode erzeugen
{% endif %}
{% endif %} {% if aktiver_tab == "konten" %}

Plattform-Admin-Konten (organisationsübergreifend) werden getrennt unter Admin-Accounts verwaltet, tauchen hier absichtlich nicht auf.

{% for b in benutzer %} {% endfor %}
E-MailOrg-AdminAngelegt
{{ b.email }} {{ "ja" if b.ist_organisationsadmin else "nein" }} {{ b.created_at | datum(False) }}
Ändern
Neues Konto anlegen
{% endif %} {% if aktiver_tab == "struktur" %} {# Struktur & Workspaces (Workspace-Creator neu, Schritt F, 07.10.2026): Workspace an der OE, vererbt nach unten. Die Distro-Konfliktregel prüft anode beim Speichern. #}
{% set meldung_oe = request.query_params.get("oe") %} {% if not meldung_oe %} {% if request.query_params.get("fehler") %}

{{ request.query_params.get("fehler") }}

{% endif %} {% if request.query_params.get("hinweis") %}

{{ request.query_params.get("hinweis") }}

{% endif %} {% endif %}

Ein Workspace an einer OE gilt für alle Geräte darin und in ihren Unter-OEs (außer eine Unter-OE hat einen eigenen). Geräte müssen zur Distro des Workspace passen – sonst wird das Speichern mit Begründung abgelehnt. Gruppen ergänzen nur.

{% macro oe_knoten(oe, oes, tiefe) %}
{{ oe.name }}{% if oe.ist_standard %} (Standard){% endif %} · {{ oe.anzahl_geraete }} Gerät(e){% if oe.distros %}: {{ oe.distros | join(", ") }}{% endif %}
{% if oe.workspace %} Workspace: {{ oe.workspace.name }} ({{ oe.workspace.distro }}, {{ "automatisch neueste Version" if oe.workspace.automatisch else "auf v" ~ oe.workspace.version ~ " gepinnt" }}) {% elif oe.wirksamer_workspace %} Workspace geerbt: {{ oe.wirksamer_workspace.name }} von {{ oe.wirksamer_workspace.geerbt_von }} {% else %} Kein Workspace – es gilt der Workspace der Installation {% endif %} {% set hier = request.query_params.get("oe") == oe.id %} {% set oe_fehler = request.query_params.get("fehler") if hier %} {% set oe_hinweis = request.query_params.get("hinweis") if hier %} {% if oe_hinweis %}

{{ oe_hinweis }}

{% endif %}
Workspace ändern · Unter-OE anlegen {% if oe_fehler %}

{{ oe_fehler }}

{% endif %}
{% for kind in oes | selectattr("parent_id", "equalto", oe.id) %}{{ oe_knoten(kind, oes, tiefe + 1) }}{% endfor %} {% endmacro %} {% for wurzel in organisationseinheiten | selectattr("parent_id", "equalto", none) %}{{ oe_knoten(wurzel, organisationseinheiten, 0) }}{% endfor %}
{% endif %} {% if aktiver_tab == "gruppen" %}

Querschnitts-Gruppen (z.B. Lehrer/Schulleitung) — ein Gerät kann in mehreren gleichzeitig sein.

{% if not gruppen %}

Keine Gruppen angelegt.

{% else %}
{% for gruppe in gruppen %} {% endfor %}
Name
{{ gruppe.name }} Verwalten
{% endif %}
Neue Gruppe anlegen
{% endif %} {% endblock %}