docs: document provisioning handshake and persistence model

This commit is contained in:
Thomas Stallinger 2026-07-14 10:28:30 +02:00
parent 25d71b0b5e
commit 40d9bc77a6
7 changed files with 623 additions and 1 deletions

View File

@ -0,0 +1,61 @@
# ADR-0001: PostgreSQL als persistente Plattformdatenbank
**Status:** Beschlossen
**Datum:** 12.07.2026
## Kontext
Tuxflotte verwaltet zunehmend persistente und miteinander verknüpfte Plattformdaten.
Dazu gehören unter anderem:
- Organisationen
- Geräte
- Gerätezuordnungen
- Hardware-Snapshots
- Netzwerkprofile
- Workspaces
- Backends
- Runtime Blueprints
- Secret-Referenzen
Die bisherige dateibasierte Device Registry diente dem Nachweis des grundlegenden Provisioning-Handshakes.
Für das langfristige Plattformmodell ist eine strukturierte persistente Datenhaltung erforderlich.
## Entscheidung
Tuxflotte verwendet PostgreSQL als persistente Plattformdatenbank.
Die Datenbank bildet die Beziehungen zwischen Organisationen, Geräten, Hardware-Snapshots, Workspaces, Backends und Gerätezuordnungen ab.
Die dateibasierte Device Registry wird nicht als dauerhaftes Persistenzmodell weitergeführt.
Hardwareinformationen werden als zeitbezogene Snapshots gespeichert.
Die stabile Geräteidentität und der erfasste Hardwarezustand werden getrennt behandelt.
Secrets werden nicht als Klartextbestandteil der fachlichen Plattformdaten gespeichert.
Das konkrete Secret-Management wird in einer separaten Architekturentscheidung definiert.
## Konsequenzen
Der Provisioning-Server erhält eine PostgreSQL-Anbindung.
Änderungen am Datenbankschema werden über versionierte Migrationen verwaltet.
Geräte erhalten eine interne, von Hardwaremerkmalen unabhängige Datenbank-ID.
Der Hardware-Fingerprint dient der Wiedererkennung eines Geräts während des Provisioning-Handshakes.
Hardwaredaten werden getrennt von der Geräteidentität als Snapshots gespeichert.
Ein Gerät kann mehrere Hardware-Snapshots besitzen.
Netzwerkinterfaces und Massenspeicher können einem Hardware-Snapshot zugeordnet werden.
Die bestehende dateibasierte Device Registry wird nach erfolgreicher Einführung der Datenbank entfernt.
Die Provisioning API bleibt von der konkreten Persistenzimplementierung unabhängig.

View File

@ -0,0 +1,51 @@
Boot
Preflight
Netzwerk
Hardware Identity
Server Discovery
Device Registration
Assignment
Runtime Blueprint
Backend Selection
Backend API
Native Installer
First Boot
Provisioning Agent
Managed System
## Aktivierung und Gerätebindung
Ein neues Gerät authentifiziert den ersten Provisionierungsvorgang mit einem Aktivierungscode.
Nach erfolgreicher Prüfung wird der vom Installer erzeugte Hardware-Fingerprint an den Provisioning-Server übertragen.
Der Server bindet den Fingerprint an die Aktivierung beziehungsweise an die zugehörige Organisation.
Der Aktivierungscode ist damit die initiale Berechtigung.
Der Hardware-Fingerprint dient anschließend zur Wiedererkennung des Geräts.
Ablauf:
Aktivierungscode
Hardware-Fingerprint
Geräteregistrierung oder Wiedererkennung
Profil- beziehungsweise Workspace-Zuordnung
Runtime Blueprint

View File

@ -0,0 +1,66 @@
# Runtime Blueprint Model
**Status:** Stable
## Zweck dieses Dokuments
Dieses Dokument beschreibt das Runtime Blueprint als zentralen Integrationspunkt des Provisionierungsprozesses von Tuxflotte.
Es definiert seine Aufgabe innerhalb der Plattform und beschreibt seine Verantwortung sowie seine Abgrenzung zu den übrigen Komponenten der Architektur.
---
## Motivation
Workspace, Organization und Backend beschreiben jeweils einen eigenständigen Aspekt einer Bereitstellung.
Erst durch ihr Zusammenführen entsteht die vollständige Beschreibung einer konkreten Bereitstellung.
Das Runtime Blueprint verbindet diese Informationen und bildet die Grundlage für den weiteren Provisionierungsprozess.
---
## Definition
Das Runtime Blueprint beschreibt den vollständigen Zielzustand einer konkreten Bereitstellung.
Es wird zentral aus den Informationen von Workspace, Organization und Backend erzeugt und bereitgestellt.
Jede Bereitstellung erhält ihr eigenes Runtime Blueprint.
---
## Provisionierungsprozess
Der Provisionierungsprozess beginnt mit der Auswahl eines Workspace und endet nicht mit der Installation des Betriebssystems.
Er beschreibt den Weg von der fachlichen Beschreibung eines Arbeitsplatzes bis zur Umsetzung des gewünschten Zielzustands.
Während dieses Prozesses wird das Runtime Blueprint zentral erzeugt und den ausführenden Komponenten der Plattform bereitgestellt.
Der Installer setzt den beschriebenen Zielzustand während der Erstbereitstellung um.
Nach der Registrierung setzt der Provisioning Agent Änderungen des Zielzustands im weiteren Lebenszyklus um.
---
## Verantwortungsbereich
Das Runtime Blueprint beschreibt insbesondere
den vollständigen Zielzustand einer konkreten Bereitstellung,
die Zusammenführung der Informationen aus Workspace, Organization und Backend,
alle für die Umsetzung erforderlichen Informationen sowie
die Grundlage für die Umsetzung durch Installer und Provisionierungs-Agent.
Das Runtime Blueprint beschreibt den Zielzustand.
Die Umsetzung dieses Zielzustands erfolgt durch die ausführenden Komponenten der Plattform.
---
## Zusammenfassung
Das Runtime Blueprint verbindet die fachlichen Modelle von Tuxflotte mit ihrer konkreten Umsetzung.
Es bildet den zentralen Integrationspunkt des Provisionierungsprozesses und beschreibt den vollständigen Zielzustand eines konkreten Systems.

View File

@ -0,0 +1,56 @@
# Runtime Layout
## Laufzeitverzeichnis
Alle Installer-Module kommunizieren ausschließlich über:
/run/tuxflotte/
Jedes Modul besitzt genau ein eigenes Unterverzeichnis.
## Verzeichnisstruktur
/run/tuxflotte/
├── network/
├── hardware/
├── server/
├── runtime/
├── backend/
└── logs/
## Eigentümer der Verzeichnisse
network/
Besitzer: 05_network.sh
hardware/
Besitzer: 10_hardware.sh
server/
Besitzer: 15_server_handshake.sh
runtime/
Besitzer: Runtime-Builder
backend/
Besitzer: Backend-Orchestrator
logs/
Besitzer: zentraler Installer-Orchestrator
## Lese- und Schreibregeln
Ein Modul darf ausschließlich in sein eigenes Verzeichnis schreiben.
Andere Modulverzeichnisse dürfen nur gelesen werden, wenn dies für den definierten Ablauf erforderlich ist.
Beispiele:
- 10_hardware.sh schreibt nur nach /run/tuxflotte/hardware/
- 15_server_handshake.sh liest aus /run/tuxflotte/network/ und /run/tuxflotte/hardware/
- Der Runtime-Builder liest aus /run/tuxflotte/server/
- Der Backend-Orchestrator liest aus /run/tuxflotte/runtime/
Direkte Funktionsaufrufe zwischen Modulen sind nicht vorgesehen.
Die Kommunikation erfolgt ausschließlich über Dateien im Runtime-Verzeichnis.

View File

@ -0,0 +1,142 @@
# Provisioning API
## Zweck
Die Provisioning API beschreibt die Kommunikation zwischen dem Tuxflotte-Installer und dem Provisioning-Server.
Sie ist distributionsunabhängig.
Die Backend API (06-backend-api.md) beginnt erst nach der Erstellung des Runtime Blueprints.
## Aktivierung
### Endpoint
POST /api/v1/activate
### Zweck
Der Endpoint autorisiert einen initialen Provisionierungsvorgang und registriert oder erkennt ein Gerät anhand seines Hardware-Fingerprints wieder.
### Request
```json
{
"activation_code": "LAB-2026-START",
"device_fingerprint": "<sha256>",
"hostname": "enterprise",
"machine_id": "<machine-id>",
"client_version": "0.1.0",
"hardware": {
"schema_version": 1,
"identity": {
"device_fingerprint": "<sha256>",
"system_uuid": "<uuid>",
"system_serial": null,
"board_serial": "<serial>",
"machine_id": "<machine-id>"
},
"system": {
"manufacturer": null,
"product_name": null,
"product_version": null,
"architecture": "x86_64",
"cpu": {
"model": "<cpu-model>",
"logical_count": 8
},
"memory_bytes": 33446432768
},
"mainboard": {
"vendor": "Intel Corporation",
"name": "DH87MC"
},
"firmware": {
"bios_vendor": "Intel Corp.",
"bios_version": "<bios-version>",
"boot_mode": "bios",
"secure_boot": "unsupported"
},
"security": {
"tpm_version": "none"
},
"network_interfaces": [
{
"name": "eno1",
"type": "ethernet",
"mac": "<mac-address>"
}
],
"storage_devices": [
{
"name": "sda",
"model": "<model>",
"serial": "<serial>",
"size_bytes": 512110190592,
"transport": "sata"
}
]
}
}
Der `hardware`-Block enthält den während der Provisionierung erfassten Hardwarezustand.
Der Provisioning-Server registriert oder erkennt das Gerät anhand des `device_fingerprint` und speichert den übertragenen Hardwarezustand als zeitbezogenen Hardware-Snapshot.
Bei einer erneuten erfolgreichen Aktivierung desselben Geräts bleibt die interne Geräte-ID erhalten. Für den aktuellen Aktivierungsvorgang wird ein neuer Hardware-Snapshot erzeugt.
### Response
Bei erfolgreicher Aktivierung antwortet der Provisioning-Server mit dem registrierten Gerät, der zugeordneten Organisation und den verfügbaren Provisioning-Profilen.
```json
{
"success": true,
"device": {
"id": "<device-uuid>",
"fingerprint": "<sha256>",
"hostname": "enterprise",
"created": false,
"hardware_snapshot_id": "<hardware-snapshot-uuid>"
},
"customer": {
"id": "default",
"organization_id": "<organization-uuid>",
"name": "Default Lab"
},
"profiles": [
{
"id": "fedora-workstation",
"label": "Fedora Workstation",
"distribution": "fedora",
"version": "40",
"description": "Standard-Workstation-Profil für Fedora.",
"ansible_repo": "<repository-url>",
"installer": {
"type": "kickstart",
"url": "<kickstart-url>"
}
}
]
}
```
`device.id` ist die interne, von Hardwaremerkmalen unabhängige Geräte-ID.
`device.created` gibt an, ob das Gerät während dieses Aktivierungsvorgangs neu registriert wurde.
`device.hardware_snapshot_id` referenziert den für diesen Aktivierungsvorgang erzeugten Hardware-Snapshot.
Der Aktivierungscode bestimmt die zugeordnete Organisation und die für den Provisionierungsvorgang verfügbaren Profile.
### Fehlerantwort
Ist der Aktivierungscode ungültig, antwortet der Provisioning-Server mit:
```json
{
"success": false,
"error": "invalid_activation_code",
"message": "Der Aktivierungscode ist ungültig."
}
```

View File

@ -0,0 +1,246 @@
# Tuxflotte Datenmodell v1
## Zweck
Das Datenmodell beschreibt die persistenten Kernobjekte der Tuxflotte-Plattform und ihre Beziehungen.
Die konkrete SQL-Implementierung und das Migrationssystem werden getrennt von diesem fachlichen Modell behandelt.
## Kernobjekte
- Organization
- Device
- Hardware Snapshot
- Network Interface
- Storage Device
- Workspace
- Backend
- Assignment
- Network Profile
- Secret Reference
## Organization
Eine Organization beschreibt eine organisatorische Einheit innerhalb der Tuxflotte-Plattform.
Eine Organization besitzt eigene Geräte, Workspaces, Netzwerkprofile und Richtlinien.
Attribute:
- id
- name
- created_at
- updated_at
Beziehungen:
- besitzt mehrere Devices
- besitzt mehrere Workspaces
- besitzt mehrere Network Profiles
- referenziert Secrets
## Device
Ein Device repräsentiert ein dauerhaft bekanntes physisches oder virtuelles Gerät.
Die interne Geräte-ID ist unabhängig von Hardwaremerkmalen.
Der Hardware-Fingerprint dient der Wiedererkennung während des Provisioning-Handshakes.
Attribute:
- id
- organization_id
- device_fingerprint
- hostname
- created_at
- last_seen
Beziehungen:
- gehört zu genau einer Organization
- besitzt mehrere Hardware Snapshots
- besitzt optional ein Assignment
## Hardware Snapshot
Ein Hardware Snapshot beschreibt den zu einem bestimmten Zeitpunkt erfassten Hardwarezustand eines Devices.
Hardware Snapshots sind zeitbezogene Inventardaten und nicht Bestandteil der stabilen Geräteidentität.
Attribute:
- id
- device_id
- collected_at
- architecture
- manufacturer
- product_name
- product_version
- system_uuid
- system_serial
- board_vendor
- board_name
- board_serial
- bios_vendor
- bios_version
- boot_mode
- secure_boot
- tpm_version
- cpu_model
- cpu_logical_count
- memory_bytes
Beziehungen:
- gehört zu genau einem Device
- besitzt mehrere Network Interfaces
- besitzt mehrere Storage Devices
## Network Interface
Ein Network Interface beschreibt eine zum Zeitpunkt des Hardware Snapshots vorhandene Netzwerkschnittstelle.
Attribute:
- id
- hardware_snapshot_id
- name
- type
- mac_address
Beziehungen:
- gehört zu genau einem Hardware Snapshot
## Storage Device
Ein Storage Device beschreibt einen zum Zeitpunkt des Hardware Snapshots vorhandenen Massenspeicher.
Attribute:
- id
- hardware_snapshot_id
- model
- serial
- size_bytes
- transport
- name
Beziehungen:
- gehört zu genau einem Hardware Snapshot
## Relationales Schema v1
### organizations
Spalten:
- id
- name
- created_at
- updated_at
### devices
Spalten:
- id
- organization_id
- device_fingerprint
- hostname
- created_at
- last_seen
Beziehungen:
- organization_id referenziert organizations.id
Constraints:
- device_fingerprint ist eindeutig
### hardware_snapshots
Spalten:
- id
- device_id
- collected_at
- architecture
- manufacturer
- product_name
- product_version
- system_uuid
- system_serial
- board_vendor
- board_name
- board_serial
- bios_vendor
- bios_version
- boot_mode
- secure_boot
- tpm_version
- cpu_model
- cpu_logical_count
- memory_bytes
Beziehungen:
- device_id referenziert devices.id
### network_interfaces
Spalten:
- id
- hardware_snapshot_id
- name
- type
- mac_address
Beziehungen:
- hardware_snapshot_id referenziert hardware_snapshots.id
### storage_devices
Spalten:
- id
- hardware_snapshot_id
- name
- model
- serial
- size_bytes
- transport
Beziehungen:
- hardware_snapshot_id referenziert hardware_snapshots.id
## Beziehungskonsequenzen
Wird eine Organization gelöscht, dürfen zugehörige Devices nicht implizit mitgelöscht werden.
Wird ein Device gelöscht, werden zugehörige Hardware Snapshots mitgelöscht.
Wird ein Hardware Snapshot gelöscht, werden zugehörige Network Interfaces und Storage Devices automatisch mitgelöscht.
Für die relationale Umsetzung gilt daher:
- devices.organization_id → ON DELETE RESTRICT
- hardware_snapshots.device_id → ON DELETE CASCADE
- network_interfaces.hardware_snapshot_id → ON DELETE CASCADE
- storage_devices.hardware_snapshot_id → ON DELETE CASCADE
## ID-Erzeugung
Persistente Plattformobjekte verwenden UUIDs als interne IDs.
UUIDs werden durch die Anwendung erzeugt.
Die Datenbank validiert und speichert die IDs, erzeugt sie jedoch nicht selbst.
Dadurch stehen Objekt-IDs bereits vor dem Datenbank-INSERT zur Verfügung und können innerhalb einer Transaktion für abhängige Datensätze verwendet werden.

View File

@ -39,7 +39,7 @@ Ziel: Netzwerkgestützter Installer.
### Registrierung
* [ ] Geräteaktivierung
* [x] Geräteaktivierung
* [ ] Benutzeranmeldung
* [ ] Auswahl von OS- und Konfigurationsprofilen