Files
DDI/docs/PROJECT_BRIEF.md

29 KiB
Raw Permalink Blame History

Projektauftrag: Eigene DDI-Suite (DNS, DHCP, IPAM) mit Management-Server und Agents

Arbeitstitel: ddi-suite (alle Namen, Pfade, Paket- und Dienstnamen zentral konfigurierbar halten, damit eine Umbenennung leicht ist). Repository: https://git.beugsiud.de/beug.k/DDI (Go-Modulpfad: git.beugsiud.de/beug.k/DDI). Lizenzserver: selbst gehostetes Keygen unter https://license.beugsiud.de. Dieses Dokument ist der vollständige Auftrag. Lies es komplett, bevor du Code schreibst. Lege es als docs/PROJECT_BRIEF.md im Repo ab.


0. Arbeitsweise (verbindlich)

  1. Erst planen, dann bauen. Schreibe zuerst docs/ARCHITECTURE.md und docs/adr/ (eine ADR pro Grundsatzentscheidung, kurz). Zeige mir den Plan nicht zur Freigabe, sondern lege los, sobald er steht. Frag nur nach, wenn eine Entscheidung nicht rückgängig zu machen ist und sich nicht aus diesem Dokument ableiten lässt. Sonst: sinnvollen Default wählen, in einer ADR festhalten, weitermachen.
  2. Arbeite in Meilensteinen (Abschnitt 12). Pro Meilenstein: lauffähig, getestet, dokumentiert, committed. Kein Meilenstein gilt als fertig, solange Tests rot sind oder TODO/Stubs in Kernfunktionen stecken.
  3. Git: Conventional Commits, kleine nachvollziehbare Commits, ein Tag pro Meilenstein (v0.1.0 …). Keine Secrets, Schlüssel oder Passwörter im Repo. .gitignore von Anfang an.
  4. Sprachen: Code, Kommentare, Commit-Messages, API-Felder und Logs auf Englisch. Dokumentation und Benutzeroberfläche auf Deutsch (Oberfläche i18n-fähig, Deutsch als Standard, Englisch als zweite Sprache).
  5. Prüfe Fakten gegen die offizielle Doku, bevor du dich auf Features von BIND oder Kea verlässt (insbesondere welche Kea-Hooks frei verfügbar sind). Verlasse dich nicht auf kostenpflichtige/„premium“ Hook-Bibliotheken. Wenn etwas nicht frei verfügbar ist, plane die Alternative und halte sie in einer ADR fest.
  6. Keine Annahmen über meine Infrastruktur. Alles Umgebungsspezifische (URLs, Hostnamen, Domains) kommt aus Konfiguration oder Installer-Parametern.

1. Ziel

Ein selbst gehostetes DDI-System im Stil von Nokia/Cygna VitalQIP:

  • Management-Server (zentral, kostenpflichtig lizenziert): Netze anlegen, alle Adressen/Clients in einer QIP-artigen Tabelle verwalten, DNS-/DHCP-Server und Cluster verwalten, Konfigurationen erzeugen und ausrollen.
  • Agents (auf den DNS-/DHCP-Servern, lizenzfrei und später auch einzeln ohne Management-Server nutzbar): holen die Konfiguration automatisch (Pull) oder auf Anforderung aus der Weboberfläche (Push), wenden sie sicher an und melden Zustand und Leases zurück.
  • Darunter laufende, bewährte Software: BIND 9 (DNS) und Kea DHCP (DHCP, siehe ADR-Vorgabe unten). Wir schreiben keine eigenen DNS-/DHCP-Engines.

Zielgröße der ersten Version: Homelab bis kleines Unternehmen (bis ca. 50 Agents, einige zehntausend Adressen). Der Entwurf darf nicht nach oben verbaut sein.


2. Festgelegte Entscheidungen

Thema Entscheidung
DNS-Engine BIND 9 (aktuelle stabile/LTS-Linie, z. B. 9.18 oder neuer). Verwaltung über generierte named.conf-Includes, Zonendateien und rndc.
DHCP-Engine Kea DHCP (DHCPv4 zuerst, DHCPv6 später). Begründung in ADR: aktiv gepflegt, JSON-Konfiguration, Control-Socket/API, HA-Unterstützung, ISC DHCP ist abgekündigt. Alternativen kurz bewerten (dnsmasq, CoreDHCP). Nur frei verfügbare Kea-Bestandteile verwenden.
Sprache Backend/Agent Go (aktuelle stabile Version). Statisch gelinkte Binaries, CGO_ENABLED=0, wo möglich.
Datenbank Server PostgreSQL (14+). Migrationen versioniert (z. B. golang-migrate oder goose).
Agent-Zustand Lokal in Dateien/SQLite, keine Datenbank-Abhängigkeit auf dem Agent.
Frontend React + TypeScript + Vite, Tabellen mit TanStack Table, in das Server-Binary eingebettet (embed). Responsive, dunkles und helles Theme.
API REST/JSON mit OpenAPI-Spezifikation (Single Source of Truth, Client-Typen daraus generieren).
Server↔Agent gRPC über mTLS. Der Agent baut die Verbindung ausgehend zum Server auf (funktioniert hinter NAT/Firewall), bidirektionaler Stream für „jetzt anwenden“-Kommandos, Fallback auf Polling.
Zertifikate Server betreibt eine interne CA. Enrollment des Agents mit einmaligem Token → Agent sendet CSR → Server signiert. Zertifikats-Rotation und Sperrung vorsehen.
Lizenzierung Server Keygen (selbst gehostet, https://license.beugsiud.de) als primärer Lizenzanbieter, siehe Abschnitt 9.
Quellcode-Lizenz Agents: Apache-2.0. Server: proprietär, LICENSE mit Platzhalter, kein Open-Source-Text.
Git-Host git.beugsiud.de (Pfadschema beug.k/DDI deutet auf Gitea/Forgejo hin). Prüfe anhand der Repo-URL-Struktur und halte die Annahme in einer ADR fest. Release-Artefakte und CI daran ausrichten (Abschnitt 10 und M0). Ist es GitLab, die Pfade entsprechend anpassen.

3. Architektur

 Browser ──HTTPS──▶ Management-Server (Go, PostgreSQL)
                      │  REST API, Web-UI, Auth, Audit, Lizenz, Config-Generator, interne CA
                      │
                      │ gRPC/mTLS (Agent verbindet ausgehend)
          ┌───────────┴───────────────────────┐
          ▼                                   ▼
   DNS-Agent (Go) + BIND 9           DHCP-Agent (Go) + Kea DHCP
   - holt/wendet Config an           - holt/wendet Config an
   - prüft, rollt zurück             - prüft, rollt zurück
   - meldet Health                   - meldet Leases und Health

Repo-Struktur (Monorepo):

/proto            gRPC-Definitionen (protobuf)
/server           Management-Server (API, Domainlogik, Config-Generator, CA, Lizenz)
/agent            Agent-Code (gemeinsamer Kern, Rollen dns und dhcp)
/web              Frontend
/deploy           systemd-Units, Beispielkonfigurationen, Compose für Entwicklung/Tests
/scripts          install.sh, Build-/Release-Skripte
/tools            keygen-setup (Hilfsskript, das Product/Policy/Entitlements in Keygen anlegt, nicht Teil der Auslieferung)
/docs             ARCHITECTURE, SYSTEM-REQUIREMENTS, OPERATIONS, SECURITY, API, adr/
/test             Integrationstests (echte BIND-/Kea-Container)
Makefile          build, test, lint, release, dev

Agents laufen als eigene Binaries pro Rolle (ddi-agent-dns, ddi-agent-dhcp) oder als ein Binary mit Rollenparameter; entscheide per ADR, halte aber die Rolle sauber getrennt, damit sie später einzeln auslieferbar sind.


4. Datenmodell (Kern, PostgreSQL)

Entwirf ein sauberes Schema mit Fremdschlüsseln und Constraints. IPv6-fähig (inet/cidr), auch wenn DHCPv6 erst später kommt.

  • Network (Subnetz): CIDR, Name, VLAN, Gateway, Domain/Suchdomäne, DHCP-Parameter (Pools, Lease-Zeit, Optionen wie DNS-Server/NTP), zugeordnetes DHCP-Cluster, Beschreibung, Tags.
  • Address (ein Eintrag pro IP; das ist die QIP-Clienttabelle):
    • type (Enum): static, reserved, manual_dhcp (MAC-gebundene Reservierung), dynamic (Pool, ohne MAC-Bindung)
    • ip, mac (Pflicht bei manual_dhcp, per CHECK-Constraint), hostname, zone, fqdn, Beschreibung, Besitzer/Verantwortlicher, Tags, first_seen, last_seen, aktueller Lease-Status
    • Eindeutigkeit: IP je Netz, MAC je Netz (wo sinnvoll), Hostname je Zone.
  • Zone: Name, Typ (forward/reverse), Modus (managed = vollständig aus der DB generiert, dynamic = RFC-2136-Updates erlaubt, der Server überschreibt sie nie), TSIG-Schlüssel, Update-Zugriffsliste (z. B. IPs von Domain Controllern), Reverse-Zonen automatisch ableiten.
  • Record: Nicht-Adress-Records (CNAME, MX, TXT, SRV, NS …) in managed Zonen. A/PTR entstehen aus Address.
  • Cluster: Typ dns (Primary + Secondaries) oder dhcp (Kea-HA-Paar oder Einzelserver).
  • Server/Agent: Rolle, Cluster-Zugehörigkeit, Zertifikat, Version, Status, letzter Kontakt, Betriebsmodus (auto_pull | manual), Pull-Intervall, optionale Wartungsfenster.
  • ConfigRevision: unveränderliche, fortlaufende Revisionen pro Agent/Cluster (Inhalt als strukturierte Daten plus gerenderte Artefakte), mit Diff zur Vorgängerrevision.
  • Deployment: Auslieferungsversuch (Revision, Agent, ausgelöst durch Pull/Push/Benutzer, Ergebnis, Fehlertext, Zeitstempel, Rollback-Info).
  • User/Role/AuditLog: lokale Benutzer, Rollen (Admin, Operator, Viewer), vollständiges Audit-Log (wer, was, wann, vorher/nachher).
  • License: aktuell geladene Lizenz und Status.

5. Funktionale Anforderungen: Management-Server

5.1 Netze

Anlegen/Bearbeiten/Löschen von Netzen mit Validierung (keine Überlappungen, Gateway im Netz, Pools im Netz und ohne Überschneidung mit static/reserved). Übersicht mit Auslastung (genutzt/frei, Anteil Pool) und eine Adresskarte (Raster der IPs mit Farbe je Typ/Status).

5.2 Clients-/Adresstabelle (wie QIP)

  • Große, performante Tabelle (virtualisiert, serverseitig filtern/sortieren/paginieren), Spalten: IP, Typ, MAC, Hostname, FQDN, Netz, Lease-Status, zuletzt gesehen, Beschreibung, Tags.
  • Typ umschalten direkt in der Tabelle (static ↔ reserved ↔ manual_dhcp ↔ dynamic) mit Validierung (z. B. MAC erforderlich bei manual_dhcp) und Vorschau, welche Config-Änderung daraus folgt.
  • Semantik der Typen:
    • static: Eintrag + A/PTR, kein DHCP. Adresse außerhalb der Pools.
    • reserved: Adresse blockiert. Kein DHCP, kein DNS, aus Pools ausgeschlossen (Pools werden bei Bedarf automatisch aufgeteilt).
    • manual_dhcp: Kea-Host-Reservierung (MAC → IP) + A/PTR.
    • dynamic: Pool-Adresse. Wird von einem Client eine Adresse geleast, legt der Server automatisch einen Eintrag an (IP, MAC, Hostname aus der Lease, first_seen/last_seen). Aus so entdeckten Einträgen lässt sich per Klick manual_dhcp machen.
  • Optional pro Netz: DNS-Namen für dynamische Leases in eine separate dynamische Zone schreiben (kein Konflikt mit managed Zonen).
  • Massenbearbeitung, CSV-Import/-Export, Suche über IP/MAC/Hostname, gespeicherte Filter.

5.3 DNS/DHCP-Cluster

Cluster und Server anlegen, Rollen zuweisen, Status/Health, Revisionsverlauf mit Diff-Ansicht, Deployment-Status je Agent, Rollback auf frühere Revision.

5.4 Ausrollen: Pull und Push

  • Pro Agent einstellbar: auto_pull (Agent holt in Intervall X neue Revisionen und wendet sie an) oder manual (Agent wendet nur auf Anforderung an).
  • Push aus der Weboberfläche („Jetzt ausrollen“ für Agent, Cluster oder Auswahl): der Server sendet über den bestehenden ausgehenden Agent-Stream ein „apply revision N“-Kommando. Ergebnis (Erfolg/Fehler/Rollback) wird live angezeigt.
  • Änderungen werden zuerst als Entwurf gesammelt (ungeroutete Änderungen) und beim Ausrollen zu einer Revision zusammengefasst. Anzeige „X Änderungen warten auf Ausrollen“.
  • Fehlerfall: Agent behält die letzte funktionierende Konfiguration und läuft weiter.

5.4 Weiteres

  • Authentifizierung: lokale Benutzer (Argon2id) und OIDC (Authorization-Code mit PKCE), RBAC, Sitzungen mit sicheren Cookies, CSRF-Schutz, Rate-Limiting am Login, optional TOTP.
  • Vollständiges Audit-Log mit Export.
  • Health-Endpunkte (/healthz, /readyz), Prometheus-Metriken (/metrics), strukturierte Logs.

6. Funktionale Anforderungen: Agents

Gemeinsamer Kern (Enrollment, mTLS, Config-Abruf, Signaturprüfung, Anwenden, Health), darauf zwei Rollen.

6.1 Gemeinsam

  • Enrollment mit einmaligem Token (ddi-agent enroll --server https://… --token …), danach mTLS mit kurzlebigem Zertifikat und automatischer Erneuerung.
  • Signierte Konfigurationen: Der Server signiert jedes Config-Bundle (Ed25519). Der Agent verifiziert die Signatur gegen den bei Enrollment hinterlegten öffentlichen Schlüssel, bevor er etwas anwendet. Replay-Schutz über Revisionsnummern.
  • Sicheres Anwenden: Config in ein Staging-Verzeichnis schreiben → Syntaxprüfung (named-checkconf -z, named-checkzone, Kea-Config-Test kea-dhcp4 -t) → atomar aktivieren → Dienst per rndc reconfig/reload bzw. Kea-Control-Socket neu laden → Health-Check (Dienst antwortet, Testabfrage) → bei Fehler automatischer Rollback auf die vorige Revision und Fehlermeldung an den Server.
  • Modi laut Servereinstellung: auto_pull oder manual, plus Wartungsfenster.
  • Standalone-Modus (später umsetzen, jetzt mitdenken): Agent läuft ohne Server mit lokaler deklarativer Konfigurationsdatei (YAML). Der Kern muss so entworfen sein, dass die Config-Quelle austauschbar ist (ConfigSource-Interface: ServerSource, später FileSource). Dokumentiere das, implementiere die Schnittstelle, den Standalone-Modus selbst erst in einem späteren Meilenstein.

6.2 DNS-Agent (BIND)

  • Erzeugt named.conf-Include, Zonendateien für managed Zonen (Seriennummer aus der Revision, strikt monoton), Reverse-Zonen, Views nur falls nötig.
  • Dynamische Zonen (RFC 2136, z. B. für Active-Directory-DCs oder DHCP-Updates): Der Agent legt sie an und erlaubt Updates nur für konfigurierte Quellen (IP-Zugriffsliste und/oder TSIG). Er überschreibt deren Zonendatei/Journal nie. Records in dynamischen Zonen verwaltet der Agent höchstens per nsupdate. Dokumentiere den Active-Directory-Einsatz (SRV-Records, unsichere Updates nur von DC-IPs, GSS-TSIG ist nicht Teil der ersten Version).
  • Cluster: Primary + Secondaries mit NOTIFY und TSIG-gesichertem AXFR/IXFR. Secondaries erhalten nur Masters-Liste und Schlüssel.
  • Sicherheit: Rekursion standardmäßig aus (reiner autoritativer Betrieb), Optionen für Forwarder/Rekursion pro Server, rndc-Schlüssel automatisch erzeugt und mit restriktiven Rechten abgelegt.

6.3 DHCP-Agent (Kea)

  • Erzeugt die Kea-DHCPv4-Konfiguration: Subnets, Pools (um static/reserved-Adressen herum aufgeteilt), Host-Reservierungen, Optionen, Lease-Zeiten. Vor dem Anwenden Test mit kea-dhcp4 -t, Reload über den Control-Socket.
  • Lease-Meldung: meldet neue und geänderte Leases (IP, MAC, Hostname, Zustand, Ablauf) an den Server (Batch plus Änderungs-Events). Verwende nur freie Mittel (Memfile-CSV-Auswertung und/oder frei verfügbare Control-Befehle, vorher gegen die Doku prüfen).
  • High Availability: Kea-HA (Hot-Standby bzw. Load-Balancing), soweit die Kea-HA-Funktion in der freien Version verfügbar ist (prüfen!). Falls nicht: dokumentierte Alternative.
  • Relay/giaddr-Betrieb und mehrere Subnetze pro Server unterstützen.

7. Konfigurationserzeugung (kritisch)

  • Generierung als reine, deterministische Funktionen (gleiche Eingabe → gleiche Ausgabe), mit Golden-File-Tests.
  • Strikte Validierung und Escaping aller Werte vor dem Rendern (Hostnamen, FQDN, TXT-Inhalte, MAC, CIDR). Keine Template-Injection in Zonendateien oder JSON. Nutze Whitelists und typisierte Strukturen, keine String-Konkatenation mit Nutzereingaben.
  • Jede erzeugte Konfiguration wird in den Integrationstests von echtem BIND und echtem Kea geprüft (Container).

8. Sicherheit

  • Alles verschlüsselt (TLS 1.2+/mTLS), moderne Cipher, keine Klartext-Geheimnisse in Logs.
  • Geheimnisse in der Datenbank (TSIG-Schlüssel, OIDC-Secret, CA-Schlüssel) verschlüsselt (AES-256-GCM) mit einem Master-Key, der aus Datei/Umgebung kommt und nicht in der DB liegt.
  • Eingabevalidierung überall, parametrisierte SQL-Abfragen, Schutz vor XSS/CSRF/SSRF, Security-Header, Rate-Limiting.
  • Prinzip der minimalen Rechte: Agents laufen mit eigenem Systembenutzer, nur die nötigen Rechte auf BIND-/Kea-Verzeichnisse; systemd-Hardening (NoNewPrivileges, ProtectSystem, …).
  • docs/SECURITY.md: Bedrohungsmodell, Schlüsselverwaltung, Rotation, Härtungshinweise.
  • Abhängigkeiten pinnen, govulncheck und npm audit in der CI.

9. Lizenzierung des Management-Servers

  • Der Server erfordert eine Lizenz. Agents erfordern nie eine.
  • Anbieter: Keygen, selbst gehostet unter https://license.beugsiud.de. Implementiere eine austauschbare Schnittstelle LicenseProvider mit der Implementierung KeygenProvider als Standard.
  • Prüfe vor der Umsetzung gegen die Keygen-Doku und die tatsächlich laufende Instanz, welche Funktionen meine Keygen-Edition (Community Edition) bereitstellt: Lizenzvalidierung per API, Maschinen-Aktivierung, Heartbeat/Monitoring, Entitlements, Policy-Metadaten, signierte Antworten, Offline-Lizenzdateien. Baue nur auf vorhandene Funktionen und halte Abweichungen in einer ADR fest.
  • Ablauf: Der Administrator trägt in der Weboberfläche (oder per Installer-Parameter) den Lizenzschlüssel ein. Der Server validiert ihn gegen Keygen (Schlüssel + stabiler Maschinen-Fingerprint des Servers), aktiviert die Maschine und sendet regelmäßig Heartbeats. Konfigurierbar: KEYGEN_URL (Default https://license.beugsiud.de), KEYGEN_ACCOUNT_ID, KEYGEN_PRODUCT_ID (Arbeitsname des Produkts: ddi-management-server).
  • Lizenzumfang aus Keygen: max_agents und optional max_addresses sowie Feature-Flags kommen aus Entitlements bzw. Policy-/Lizenz-Metadaten. Die Server-Oberfläche zeigt Ablaufdatum, Limits und aktuelle Nutzung.
  • Antworten verifizieren: Wenn Keygen signierte Antworten liefert, prüfe die Signatur mit dem konfigurierten öffentlichen Schlüssel des Accounts, damit ein Man-in-the-Middle keine Lizenz „fälschen“ kann.
  • Offline-Toleranz: Der letzte erfolgreiche Validierungsstand wird (signiert/verschlüsselt) gecacht. Ist Keygen nicht erreichbar, läuft der Server mit dem Cache weiter, standardmäßig 14 Tage Karenzzeit (konfigurierbar). Optional, falls die Edition Offline-Lizenzdateien unterstützt: Import einer Keygen-Lizenzdatei als Alternative für isolierte Netze.
  • Ohne gültige Lizenz: 30 Tage Testbetrieb ab Erststart, danach schreibgeschützter Modus (ansehen/exportieren ja, Änderungen/Ausrollen nein), mit klarem Hinweis in der Oberfläche. Auch nach Ablauf der Karenzzeit oder bei abgelaufener Lizenz gilt dasselbe.
  • Grundsatz: Die Lizenz darf die Datenebene nie beeinträchtigen. Läuft die Lizenz ab, fehlt sie oder ist Keygen nicht erreichbar, laufen alle Agents mit ihrer letzten Konfiguration unverändert weiter. Nur Verwaltungsfunktionen des Servers werden eingeschränkt.
  • tools/keygen-setup und docs/LICENSING.md: Schritt-für-Schritt-Anleitung (und, soweit die API es erlaubt, ein Skript), um in Keygen Product, Policy (inkl. Maschinenlimit 1 pro Lizenz), Entitlements und Test-Lizenzen anzulegen. Admin-Tokens und Lizenzschlüssel gehören nicht ins Repo.
  • Dokumentiere ehrlich in docs/SECURITY.md, dass eine Lizenzprüfung in selbst gehosteter Software nur ein Soft-Control ist und keine technische Garantie gegen Umgehung.

10. Installer und Auslieferung

Ein Skript scripts/install.sh, das ich aus meinem Git herunterladen, prüfen und ausführen kann.

  • Rollen: server, agent-dns, agent-dhcp (Mehrfachauswahl möglich). Beispiel: sudo ./install.sh --role server.
  • Unterstützte Systeme: Debian 12/13, Ubuntu 22.04/24.04 LTS, RHEL-Familie 9 (Rocky/Alma). Erkennung über /etc/os-release, klare Fehlermeldung bei nicht unterstützten Systemen.
  • Vorabprüfung der Systemvoraussetzungen (CPU-Kerne, RAM, freier Plattenplatz, Ports, Zeitsynchronisation) mit Warnung oder Abbruch laut docs/SYSTEM-REQUIREMENTS.md.
  • Installiert Abhängigkeiten über den Paketmanager (PostgreSQL für den Server, BIND bzw. Kea für die Agents), legt Systembenutzer, Verzeichnisse und systemd-Units an, richtet Datenbank und initiale Konfiguration ein, erzeugt Master-Key und CA, gibt am Ende die URL und das einmalige Admin-Passwort bzw. Setup-Token aus.
  • Agents: --server URL --token TOKEN führt das Enrollment durch.
  • Lädt Binaries aus den Release-Artefakten von git.beugsiud.de. Standard-Basis-URL (Gitea/Forgejo-Schema, vor Verwendung gegen die Instanz prüfen): https://git.beugsiud.de/beug.k/DDI/releases/download/<TAG>/. Per DDI_RELEASE_BASE_URL überschreibbar. Das Skript selbst ist direkt aus dem Repo ladbar, z. B. https://git.beugsiud.de/beug.k/DDI/raw/branch/main/scripts/install.sh (dokumentiere die korrekte URL nach Test). Falls Releases oder Raw-Dateien Authentifizierung erfordern, unterstütze --token/DDI_GIT_TOKEN (Token nie in Logs ausgeben). Prüft SHA256-Summen und, wenn vorhanden, eine Signatur (SHA256SUMS + Signatur mit eingebettetem öffentlichem Schlüssel).
  • Server-Installation fragt nach dem Keygen-Lizenzschlüssel (optional, auch später in der Oberfläche eintragbar) und prüft vorab, dass https://license.beugsiud.de erreichbar ist (nur Warnung bei Fehler).
  • Idempotent (mehrfaches Ausführen ist sicher), mit --upgrade, --uninstall (Daten optional behalten), --dry-run, --non-interactive und --yes. Strenges Fehlerverhalten (set -euo pipefail), keine Reste bei Abbruch, nachvollziehbares Logfile.
  • Das Skript muss shellcheck-sauber sein. Dokumentiere den Weg „herunterladen → ansehen → ausführen“ und rate nicht zu curl | sudo bash als Standard.
  • Makefile-Ziel make release: baut Binaries für linux/amd64 und linux/arm64 (Raspberry Pi wird genutzt), erzeugt Tarballs, SHA256SUMS und (optional) .deb/.rpm mit nfpm.

11. Systemvoraussetzungen (Dokument docs/SYSTEM-REQUIREMENTS.md)

Schreibe das Dokument. Es muss enthalten:

  • Unterstützte Betriebssysteme und Architekturen, benötigte Software-Versionen (PostgreSQL, BIND, Kea), Browser-Unterstützung der Weboberfläche.
  • Richtwerte für CPU, RAM, Plattenplatz je Rolle und Größenklasse, mit erklärten Annahmen. Ausgangsbasis (aus Messungen verfeinern, nicht blind übernehmen):
Rolle Klein (bis ~5.000 Adressen, bis 10 Agents) Mittel (bis ~50.000 Adressen, bis 50 Agents)
Management-Server inkl. PostgreSQL 2 vCPU, 4 GB RAM, 20 GB SSD 4 vCPU, 8–16 GB RAM, 50+ GB SSD
DNS-Agent + BIND 1 vCPU, 1 GB RAM, 5 GB 2 vCPU, 2–4 GB RAM, 10 GB
DHCP-Agent + Kea 1 vCPU, 1 GB RAM, 5 GB 2 vCPU, 2 GB RAM, 10 GB
  • Messe selbst nach: Last- und Speicherverbrauchstests (perfdhcp für Kea, dnsperf für BIND, synthetische Adressmengen für den Server) und trage die gemessenen Werte samt Methode ins Dokument ein. Kennzeichne klar, was gemessen und was geschätzt ist.
  • Netzwerk: benötigte Ports und Richtungen (Agent → Server, Browser → Server, DNS 53, DHCP 67/68 und Relay, Zonentransfer), Zeitsynchronisation (NTP) als Pflicht, Hinweise zu Raspberry Pi (ARM64, SD-Karten-Verschleiß: empfohlene SSD).
  • Plattenplatz-Planung (Datenbankwachstum durch Audit-Log und Revisionen, Aufbewahrung konfigurierbar).
  • Betriebshinweise: Backup (PostgreSQL, Master-Key, CA), Wiederherstellung, Upgrade-Pfad.

12. Meilensteine

M0 Fundament: Repo-Struktur, Makefile, Lint/Format, CI-Konfiguration für Gitea/Forgejo Actions (.gitea/workflows/, GitHub-Actions-kompatible Syntax; Release-Job lädt Artefakte an das Release des Tags), Entwicklungs-Compose (PostgreSQL, BIND, Kea), ADRs, ARCHITECTURE.md. M1 Server-Kern: Datenbankschema und Migrationen, Auth (lokal + OIDC), RBAC, Audit-Log, Lizenzmodul mit KeygenProvider (gegen license.beugsiud.de, mit Cache, Karenzzeit und Lesemodus), REST-API mit OpenAPI, Netze und Adresstabelle (CRUD, Typen, Validierung) samt Web-UI-Grundgerüst. M2 Config-Generator: BIND- und Kea-Konfiguration aus dem Datenmodell, Golden-Tests, Integrationstests gegen echte BIND-/Kea-Container, Pool-Aufteilung um static/reserved. M3 Agent verwaltet: Enrollment, mTLS, signierte Configs, Anwenden mit Prüfung/Health-Check/Rollback, Lease-Meldung, Health-Anzeige im Server. Erste durchgängige Strecke: Adresse im UI ändern → Revision → Agent holt → BIND/Kea aktualisiert. M4 Pull und Push: Betriebsmodi pro Agent, ausgehender Stream, „Jetzt ausrollen“ aus dem UI, Entwürfe, Diff-Ansicht, Deployment-Status live, Rollback über das UI. M5 Cluster und Zonen: DNS-Primary/Secondary mit TSIG-AXFR, Kea-HA, Zonen- und Record-Verwaltung, dynamische Zonen inkl. Active-Directory-Beispiel, automatische Erfassung dynamischer Leases als Adressen. M6 Auslieferung: install.sh, Release-Build, optional Pakete, SYSTEM-REQUIREMENTS.md mit Messungen, OPERATIONS.md, SECURITY.md, Härtung, End-to-End-Test der Installation in sauberen VMs/Containern (Debian, Ubuntu, Rocky). M7 (später): Standalone-Agent ohne Server (FileSource), DHCPv6, DNSSEC-Signierung (optional), IPAM-Discovery.

Starte mit M0 bis M6. M7 nur als dokumentierte Schnittstellen vorbereiten.


13. Tests und Qualität

  • Unit-Tests (Domainlogik, Validierung, Config-Generator), Integrationstests mit echten Containern, End-to-End-Test der Strecke UI/API → Revision → Agent → Dienst.
  • Linting (golangci-lint, ESLint, shellcheck), Formatierung, go vet, Sicherheitsscans.
  • Testabdeckung für Kernpfade (Config-Generierung, Rollback, Lizenzprüfung, Auth) ausdrücklich nachweisen.
  • Jede Fehlermeldung an Nutzer verständlich auf Deutsch, Logs auf Englisch mit Korrelations-IDs.

14. Abnahmekriterien (Gesamtprojekt)

  1. Frische VM (Debian 12): ./install.sh --role server installiert den Server, Login funktioniert, ein Keygen-Lizenzschlüssel von license.beugsiud.de lässt sich eintragen und wird validiert (Limits und Ablauf werden angezeigt).
  2. Zwei weitere VMs: ./install.sh --role agent-dns --server … --token … bzw. agent-dhcp enrollen sich erfolgreich.
  3. Im UI: Netz anlegen, Pool definieren, Adresse als manual_dhcp anlegen, ausrollen → Kea liefert genau diese Adresse an die MAC, BIND löst A und PTR auf.
  4. Neues Gerät holt dynamisch eine Adresse → erscheint automatisch in der Adresstabelle mit MAC und Hostname → per Klick auf manual_dhcp umgestellt → nach dem Ausrollen fest reserviert.
  5. Agent im Modus manual: wendet nichts an, bis „Jetzt ausrollen“ im UI. Im Modus auto_pull: wendet innerhalb des Intervalls selbst an.
  6. Fehlerhafte Änderung (absichtlich kaputte Konfiguration) wird abgelehnt oder zurückgerollt, der Dienst läuft weiter.
  7. Lizenz in Keygen sperren/ablaufen lassen oder Keygen unerreichbar machen → nach Ablauf der Karenzzeit wird der Server schreibgeschützt, DNS und DHCP laufen unverändert weiter. Innerhalb der Karenzzeit bleibt alles voll nutzbar.
  8. Alle Tests und Linter grün, Dokumentation vollständig, SYSTEM-REQUIREMENTS.md mit Messwerten.

15. Dos und Don'ts

Do: bewährte Bibliotheken nutzen, kleine Schnittstellen, Konfiguration über Dateien/Umgebung, strukturierte Logs, Fehler mit Kontext zurückgeben, Rollback immer testen. Don't: eigene DNS-/DHCP-Engines schreiben, premium Kea-Hooks voraussetzen, Zonendateien dynamischer Zonen überschreiben, Nutzereingaben ungeprüft in Konfigurationen schreiben, Geheimnisse ins Repo, die Datenebene (DNS/DHCP) von Lizenz oder Server-Erreichbarkeit abhängig machen, Funktionen als „fertig“ melden, die nur als Stub existieren.

Beginne jetzt mit M0.