Files
infrastructure/docs/GNAI-013-PLAN_Security-Closure-and-Repository-Restructure.md

19 KiB
Raw Permalink Blame History

Sicherheitsabschluss und Repository-Neustrukturierung

Dokumenten-ID: GNAI-013-PLAN
Stand: 2026-10-14 Status: Aktiver Arbeitsplan

1. Ziel

Dieser Plan führt die noch offenen Zugriffs- und Sicherheitsarbeiten bis zum Start des internen LLM-Vertical-Slice. Er ist zugleich die laufende Checkliste: Erledigte Punkte werden erst nach einem technischen Nachweis abgehakt.

2. Zielstruktur der Dokumentation

docs/
├── GNAI-000-DOC_Index.md
├── GNAI-001-PLAN_Project-Roadmap.md
├── GNAI-013-PLAN_Security-Closure-and-Repository-Restructure.md
└── platform/
    ├── GNAI-005-SEC_Access-Control.md
    ├── proxmox-server/
    │   ├── GNAI-011-SEC_LXC-SSH-Architecture.md
    │   └── lxc/
    │       ├── ct-100-dns/GNAI-012-PLAN_Pi-hole-DNS-Handoff.md
    │       ├── ct-103-reverse-proxy/GNAI-006-SEC_Reverse-Proxy.md
    │       └── ct-105-wireguard/GNAI-007-SEC_*.md
    └── llm-server/
        ├── host/GNAI-002-INFRA_BaseSystem.md
        ├── host/GNAI-003-INFRA_Users.md
        ├── ai/GNAI-004-INFRA_Architecture.md
        ├── ai/GNAI-008-PLAN_Ansible-Deployment.md
        ├── ai/GNAI-009-PLAN_Llama-Model-Evaluation.md
        ├── ai/GNAI-010-TECH_Llama-Serving.md
        └── encoding/GNENC-*.md

Die ausführbare Infrastruktur ist seit 14.10.2026 ebenfalls hostbezogen:

ghostnet.ai-infrastructure/
├── llm-server/ansible/                    # physischer KI-Server
├── proxmox/
│   ├── shared/scripts/                    # nur LXC-übergreifende PVE-Helfer
│   └── lxc/
│       ├── ct-100-dns/                    # Hostwurzel; Ansible-Import offen
│       ├── ct-102-keycloak/{ansible,scripts}/
│       ├── ct-103-reverse-proxy/          # Hostwurzel; Ansible-Import offen
│       ├── ct-104-keycloak/               # erhaltener Rückfall-/Referenzstand
│       └── ct-105-wireguard/
└── shared/ansible/                        # gemeinsam genutzte Rollen und Pins

Inventare und Playbooks liegen beim Zielhost. shared/ enthält keine hostbezogenen Playbooks oder Inventare.

3. Arbeitscheckliste

A. Dokumentation und lokale Geheimnisse

  • Projekt- und Live-Zustand von DNS, Reverse Proxy und WireGuard lesend inventarisiert.
  • Dokumentation in die geräteorientierte Zielstruktur verschieben.
  • Alle relativen lokalen Markdown-Links nach der Verschiebung validieren.
  • Zentrale Indizes und Architekturübersicht an die neue Struktur anpassen.
  • WireGuard-Profile aus dem Repository-Baum in einen privaten lokalen Konfigurationspfad verschieben; Verzeichnis 0700, Dateien 0600.
  • Sicherstellen, dass keine WireGuard-PrivateKeys oder PresharedKeys in versionierten Dateien oder der Git-Historie liegen.
  • Bereits offengelegte Altpeers über wg-easy rotieren oder widerrufen.
  • Wiederverwendbare LXC-Baseline als versionierten, idempotenten Proxmox-Post-install-Hook erstellen, auf CT 104 kontrolliert erproben und dokumentieren. Der Hook darf keine privaten Schlüssel enthalten und SSH nicht sperren, bevor individuelle Schlüsselzugänge geprüft wurden.

B. WireGuard-Arbeitsplatz und Gateway

  • NetworkManager-Unterstützung auf dem CachyOS-Arbeitsplatz prüfen; wireguard-tools ist für die verwendete native NetworkManager-Methode nicht erforderlich und bleibt bewusst uninstalliert.
  • Laptop-Profil geschützt in NetworkManager importieren und Autoconnect zunächst deaktiviert lassen.
  • Verbindung aus einem fremden Netz positiv testen: Handshake, erlaubtes Ziel, Split-Tunnel und DNS.
  • Alten Laptopzugang zunächst Server Admin zuordnen und anschließend durch den neuen Peer ghost-laptop mit nativer nftables-Durchsetzung ersetzen.
  • Testpeer Android-LLMAdmin widerrufen und aus wg-easy entfernen.
  • Vor Gateway-Änderungen ein aktuelles konsistentes Backup von CT 105 erstellen.
  • Native nftables-Zielpolicy und Gateway-INPUT-Rechte umsetzen; parallele wg-easy-iptables-legacy-Hooks und Laufzeitregeln entfernen und einen wg-easy-Neustart ohne Wiederkehr der Regeln prüfen.
  • Positive und negative Rollentests mit absichtlich erweitertem Client-Routing durchführen.
  • CT 105 härten: SSH-Forwarding abschalten, Patchverfahren festlegen, defekte wtmpdb-rotate.timer-Referenz bereinigen und Wiederanlauf testen.

C. Interner Keycloak-Adminzugang

  • Sichere SSH-Zugänge für den Keycloak-LXC nach der gemeinsamen LXC-Baseline einrichten und positiv wie negativ testen.
  • Aktuellen Keycloak-Stand und wirksame Hostname-/Proxy-Konfiguration sichern und inventarisieren.
  • Leserechte der lokalen Keycloak-H2-Datenbank sofort auf Root begrenzen und den Agenten-Negativtest wiederholen.
  • H2-dev-file und start-dev durch eine gesicherte Podman-/PostgreSQL-Blue/Green-Migration nach GNAI-015 ersetzen.
  • Keycloak 26.2.4 im gepinnten Produktionsimage betreiben; ein späteres 26.x-Upgrade bleibt ein eigener kontrollierter Wartungsschritt.
  • Internen NPM-vHost für auth-admin.ghostnet.selfhost.eu mit gültigem TLS und ohne öffentliche Freigabe einrichten.
  • Keycloak hostname-admin passend zur installierten Version setzen.
  • Internen Adminlogin über LAN positiv testen; Server-Admin-VPN nutzt denselben per Gateway freigegebenen NPM-Zielpfad.
  • Öffentliche /admin-GUI und Admin-API über HTTPS sperren.
  • Externe Negativtests sowie reale Vaultwarden-/OIDC-Regression durchführen.

D. Reverse Proxy, Fail2Ban und Recovery

  • Fail2Ban-Konfiguration, aktive Jails und Imagezustand prüfen.
  • Kontrollierten Ban/Unban für HTTP und HTTPS nachweisen.
  • Dienst- und LXC-Wiederanlauf einschließlich Jails und Regeln testen.
  • Praktischen FRITZ!Box-DNS-Rollback auf einem Testclient durchführen.
  • Hostunabhängige Backupkopien und mindestens einen Restore-Test planen beziehungsweise abnehmen.

E. Übergang zum LLM-Stack

  • KI-Server kontrolliert einschalten und Resolver auf den beschlossenen Pi-hole-Pfad abstimmen.
  • Lokale Ansible-.venv wegen des veralteten Repository-Pfads neu erstellen und alle Syntaxprüfungen regulär ausführen.
  • Lesenden Preflight sowie Host-/ROCm-Verifikation wiederholen.
  • Internes, nicht öffentliches llama.cpp-Testing-Vertical-Slice nach GNAI-010 implementieren und bei 64k abnehmen.

4. Arbeitsnachweise

05.10.2026 – Struktur, Geheimnisse und lokaler VPN-Client

  • Dokumente geräteorientiert verschoben; lokaler Linkvalidator meldet broken_local_links=0, alte Pfadverweise wurden nicht mehr gefunden.
  • Profile liegen in ~/.config/ghostnet/wireguard/; beide Dateinamen sind als Linux-Interface-Namen gültig. Elternverzeichnisse sind 0700, Dateien 0600.
  • Aktueller Arbeitsbaum und vollständige Git-Historie enthalten keine WireGuard-Schlüsselzuweisung im Format eines Base64-Schlüssels. Zwei Treffer in einer alten Anleitung sind keine Schlüsselwerte, sondern erklärender Beispieltext beziehungsweise Satzzeichen.
  • NetworkManager 1.58.1 hat gnai-laptop nativ importiert. Autoconnect ist aus, die Verbindung ist auf ghost beschränkt und wieder inaktiv; im Heimnetz ist keine WireGuard-Route verblieben.
  • wireguard-tools ist nicht installiert und für die gewählte native NetworkManager-Methode nicht erforderlich. Es wird nur bei späterem Bedarf an wg, wg-quick oder entsprechender CLI-Diagnose ergänzt.
  • Betreiberentscheidung: Laptop = Server Admin; der reine Android-Testpeer wird widerrufen.
  • Vor dem Peer-Widerruf wurde ein stop-konsistentes, rootgeschütztes wg-easy-Anwendungsbackup erstellt; Archiv- und Datenbankintegrität sowie der Dienstwiederanlauf wurden bestätigt. Ein vollständiges Proxmox-LXC-Backup ist dadurch nicht ersetzt.
  • Das lokale Android-Profil ist entfernt. Die endgültige serverseitige Löschung erfolgte über eine authentifizierte wg-easy-Administratorsitzung. Danach enthielten Datenbank und aktives wg0 jeweils genau den verbleibenden Laptop-Peer; SQLite-Integritätsprüfung und Dienststatus waren fehlerfrei.
  • Der Altpeer routet noch das gesamte LAN und verwendet 10.0.0.1 als DNS. Der neue Peer gnai-ghost-laptop mit 10.8.0.3 ersetzt ihn mit neuen Schlüsseln; seine explizite Client-Routenliste und der Profilimport stehen noch aus. Für Server Admin wurden einzelne dokumentierte Server-/32 einschließlich Pi-hole 10.0.0.14 beschlossen; Pi-hole ist zugleich der DNS-Server für Split-DNS. Die wg-easy-Per-Client-Firewall bleibt bewusst aus.
  • Native nftables-Sets und natives MASQUERADE sind mit den alten und neuen Laptop-Peer-IPs aktiv. Syntaxprüfung, gesicherter Rollout, neue SSH-Verbindung, Dienste, wg0, Netavark-Erhalt und Persistenzdatei wurden geprüft. Die wg-easy-Legacy-Hooks und ihre vier Laufzeitregeln wurden nach gesondertem Backup entfernt; nach kontrolliertem wg-easy-Neustart blieben Legacy-Regelzahl null, native Policy, NAT, Netavark, zwei Peers und GUI aktiv.
  • Das neue Profil ghost-laptop.conf wurde mit .3/32, Pi-hole-DNS und den elf Serverzielen validiert, geschützt nach ~/.config/ghostnet/wireguard/ verschoben und in NetworkManager manuell/inaktiv für ghost importiert. Der alte lokale Eintrag und die alte Profildatei sind entfernt.
  • Fremdnetzabnahme über Smartphone-Hotspot 10.62.63.0/24: aktueller Handshake und Transfer, Pi-hole-/Split-DNS, Proxmox, Keycloak, NPM, Pi-hole, wg-easy und Gateway-SSH bestanden. Die öffentliche IPv4 blieb vor, während und nach Aktivierung gleich. Mit absichtlich um 10.0.0.1/32 erweitertem Testprofil blieb Proxmox erreichbar, während die aktive FRITZ!Box per ICMP und HTTP gesperrt war; nftables-Zähler belegten vier erlaubte neue Verbindungen und drei Drops. Testverbindung und temporäres Profil wurden anschließend entfernt.
  • Nach bestandener Abnahme wurde Laptop-FullAdmin .2 über wg-easy gelöscht. Datenbank und wg0 enthalten nur noch ghost-laptop .3; .2 wurde auch aus der persistenten nftables-Rollenmenge entfernt. DNS, Proxmox und wg-easy funktionierten danach weiter, Legacy-Regelzahl blieb null und das VPN wurde kontrolliert getrennt.
  • Der Betreiber erstellte anschließend ein vollständiges Proxmox-Backup von CT 105 im Modus Stop. Der dadurch ausgelöste Wiederanlauf um 17:19 Uhr wurde live abgenommen: SSH, nftables und wg-easy waren aktiv, die persistente nftables-Datei bestand die Syntaxprüfung, Rollen- und Zielsets sowie natives NAT waren vorhanden, iptables-legacy enthielt keine wg-easy-Regeln, genau ein WireGuard-Peer war aktiv, SQLite meldete integrity_check=ok und die lokale wg-easy-GUI antwortete mit HTTP 302.
  • Die SSH-Baseline von CT 105 deaktiviert nun TCP-, Agent-, StreamLocal-, X11- und Tunnel-Forwarding. Ein Remote-Forwarding-Negativtest wurde vom Server abgelehnt. Der verwaiste wtmpdb-rotate.timer-Symlink wurde entfernt und ein kontrollierter LXC-Neustart um 17:38 Uhr bestätigte die Persistenz der SSH-, Firewall- und wg-easy-Konfiguration ohne fehlgeschlagene Units. Systemupdates erfolgen künftig kontrolliert manuell nach Simulation und mit dokumentiertem Health-Check; unbeaufsichtigte Upgrades bleiben deaktiviert.
  • Die Keycloak-Vorprüfung bestätigt Split-DNS zum internen Adminnamen, aber noch keinen passenden NPM-TLS-vHost. Der öffentliche /admin-Pfad bleibt erreichbar; Backendtests mit beiden Hostnamen erzwingen weiterhin den öffentlichen Frontendnamen und die Master-Realm-Discovery nennt den öffentlichen Issuer. Version und startwirksame KC_HOSTNAME*-Parameter müssen als Nächstes direkt im Keycloak-LXC inventarisiert werden.
  • CT 102 wurde über den unabhängig bestätigten ED25519-Hostschlüssel in die gemeinsame SSH-Architektur aufgenommen. ghost-agent besitzt weder Zusatzgruppen noch sudo; ghost verwendet einen eigenen passphrasegeschützten Schlüssel und passwortgeschütztes sudo. Root-, Passwort- und Forwarding-Zugriffe wurden nach dem Dienstneustart extern abgelehnt, beide Schlüsselzugänge positiv geprüft. Der vollständige LXC-Wiederanlauf folgt erst nach einem aktuellen Stop-Backup.
  • Beim Bootstrap zeigte sich eine bestehende numerische Eigentümerschaft von 464 Keycloak-Einträgen unter UID 1001/GID 118. Das zunächst mit UID 1001 angelegte Administratorkonto wurde nach Prüfung freier IDs auf UID/GID 1101 verschoben. Danach konnte ghost weder Programm noch Konfiguration schreiben; Agenten- und persönlicher Zugang, sudo, Passwortsperre sowie Keycloak und SSH wurden erneut erfolgreich geprüft. Die historischen Eigentümer werden erst nach Backup und gesonderter Betriebsprüfung bewertet.
  • Der neue Lesekanal bestätigt Keycloak 26.2.4 als nativen, rootgeführten systemd-Dienst aus /opt/keycloak. Der Dienst verwendet derzeit kc.sh start-dev, HTTP auf Port 8080, proxy=edge, proxy-headers=xforwarded, den festen öffentlichen Hostnamen und noch kein hostname-admin. Prüfsummen von Unit und Konfiguration wurden erfasst. Der Entwicklungsstart wird als eigener Härtungspunkt behandelt und nicht unkontrolliert mit der Adminpfad-Änderung vermischt.
  • Ein vollständiges Proxmox-Backup von CT 102 wurde im Modus Stop erstellt. Der LXC startete um 19:37 Uhr mit unveränderten Konfigurationsprüfsummen, UID-Trennung und Listenern. Keycloak und beide SSH-Units waren aktiv und aktiviert; Agenten- und persönlicher Schlüsselzugang, passwortgeschütztes sudo sowie Root-, Passwort- und Forwarding-Negativtests bestanden erneut.
  • Die Anwendung verwendet ausschließlich die lokale H2-dev-file-Datenbank; eigene Provider oder Themes wurden nicht gefunden. Daten- und H2-Verzeichnis sowie Datenbank- und Trace-Datei sind 0755 beziehungsweise 0644; ghost-agent konnte die Identitätsdatenbank lesen. Dieser unmittelbare Rechtebefund wird vor weiteren Keycloak-Arbeiten geschlossen.
  • GNAI-015 legt die Migration als Blue/Green-Verfahren in CT 104 mit 10.0.0.16 fest. CT-ID und IP wurden bei der Erstellung auf Kollisionen geprüft. Import auf gleicher Version, PostgreSQL-Meilenstein, separates Versionsupgrade, Adminpfad-Trennung, NPM-Cutover, 14-tägiger Rückfallstand und Restore-Test besitzen eigene Abnahmeschranken.
  • Die H2-Verzeichnisse sind nun 0700, die Datenbankdateien 0600 und systemd setzt für Keycloak UMask=0077. ghost-agent konnte das Datenverzeichnis danach weder traversieren noch die Datenbank lesen. Keycloak, SSH, lokale und öffentliche Discovery blieben funktionsfähig. Die zuvor irrtümlich dokumentierte CT-ID 106 wurde auf die tatsächlich verwendete CT-ID 104 korrigiert; die Ziel-IP bleibt 10.0.0.16.
  • CT 104 wurde am 06.10.2026 über das Community-Script als unprivilegierter Debian-13-LXC mit 12 GB Datenträger, zwei CPU-Kernen, 4096 MiB RAM und vorinstalliertem Podman erstellt. IPv4, Internet- und DNS-Zugriff waren laut Installationsprotokoll erfolgreich; IPv6 war wie vorgesehen nicht verbunden. Podman 5.4.2, die UID-Map 0 -> 100000 und ein fehlerfreier systemd-Zustand wurden anschließend bestätigt. Der ED25519-Hostschlüssel SHA256:AmLKE4H/ulGBQqC/J7mGO7rcu5U/xHtyKk45hhBuNRw stimmte zwischen Proxmox-Konsole und unabhängiger Messung vom Admin-Laptop überein.
  • Das erste Stop-Baseline-Backup von CT 104 wurde erfolgreich als /media/datenhdd2/dump/vzdump-lxc-104-2026_10_06-14_49_53.tar.zst erstellt; der LXC war nach 16 Sekunden wieder online. Vor der Benutzeranlage wurde die Swap-Größe von 512 auf 1024 MiB angehoben. Der folgende Neustart bestätigte aktive SSH-Units, Podman 5.4.2 und keine fehlgeschlagenen systemd-Units. Hostname keycloak und die vorhandenen Community-Script-Tags bleiben auf Betreiberwunsch unverändert; CT 102 und CT 104 werden deshalb in Zugängen und Dokumentation stets über CT-ID und IP unterschieden. Für UID/GID 1000, 1001 und 1101 wurden keine vorhandenen Konten, Gruppen oder Dateieigentümer gefunden.
  • ghost-agent wurde auf CT 104 als UID/GID 1000 mit gesperrtem Passwort, eigener Primärgruppe und ohne Zusatzgruppen eingerichtet. Der dedizierte Schlüssel besitzt den Fingerprint SHA256:GCCeciGznhKQjb8xRWm6qbqKNdsuIJAQ1+cgNzcKPmM; Rechte, strikte Hostschlüsselbindung und der lokale Alias ghostnet-ct104-agent wurden praktisch geprüft. Eine Kontrollverbindung zu CT 102 bestätigte, dass dessen bestehender Agentenschlüssel mit Fingerprint SHA256:PXJ0yuEyVoaW2CI5IVax5DYjM8u26Qfyyx/pIrmIkx0 durch den kurzzeitigen Bedienfehler nicht verändert wurde.
  • ghost wurde auf CT 104 als UID/GID 1001 mit eigenem passphrasegeschütztem Schlüssel und passwortgeschütztem sudo eingerichtet; Schlüsselfingerprint SHA256:4OgAGXgf6M/uQFnGdDTcZ+5qturtdWDTUHb5FCjdz+8. Das SSH-Drop-in 99-security.conf erlaubt nur ghost-agent und ghost, verlangt Public Key und sperrt Root-, Passwort-, X11-, Agent-, TCP-, StreamLocal- und Tunnel-Forwarding. Positivtests beider Rollen, sudo, Root-/Passwort- und Forwarding-Negativtests sowie ein vollständiger LXC-Neustart mit aktiven SSH-Units, Podman 5.4.2 und ohne fehlgeschlagene systemd-Units wurden erfolgreich abgenommen.
  • Der secretfreie Post-install-Hook proxmox/shared/scripts/ghostnet-lxc-baseline.sh wurde mit Modus 0750 als /usr/local/sbin/ghostnet-lxc-baseline.sh auf Proxmox installiert. Seine geprüfte SHA-256 lautet a0ee32a8fc2854c29a83b17b4e0cdb5ad55cde36de92d562f6bd890dc93ae89e. Der idempotente Lauf gegen CT 104 übersprang die bereits vorhandenen Pakete, validierte beide Konten samt Passwortzustand und bewahrte die vorhandenen Schlüsseldateien. Anschließende Positiv- und Negativtests bestätigten den Agentenzugang sowie die fortbestehenden Root-, Passwort- und Forwarding-Sperren.
  • Auf CT 104 wurde eine eigene nftables-Tabelle inet ghostnet_filter mit INPUT- und FORWARD-Drop eingerichtet. Ein systemd-Override ersetzt das distributionsseitige vollständige flush ruleset beim Stoppen durch das Entfernen ausschließlich der Ghostnet-Tabelle. Die persistent neu geladene Konfiguration erlaubte SSH und ICMP, verwarf TCP 8080 vom Admin-Laptop und ließ denselben geschlossenen Port von CT 103 bis zum erwarteten sofortigen TCP-Reset passieren. IPv4-Forwarding ist für das geplante Podman-Netz aktiv, IPv6-Forwarding bleibt aus. Die abschließende Prüfung mit einem digest-gepinnten BusyBox-Quadlet belegte Aardvark-DNS, die feste Containeradresse 10.89.0.20, Netavark-DNAT und den Quellfilter: CT 103 erhielt vor und nach einem vollständigen LXC-Neustart unmittelbar eine HTTP-Antwort, der Admin-Laptop lief jeweils in einen Timeout. nftables, Podman-Netz, Testcontainer und der gehärtete SSH-Zugang kamen nach dem Neustart automatisch und fehlerfrei wieder.

5. Aktuell bestätigte Blocker

  • Der öffentliche Keycloak-Adminpfad ist gesperrt; interner Adminzugang und Vaultwarden-OIDC sind abgenommen.
  • Die native WireGuard-Rollenpolicy ist aktiv und die Legacy-Regeln sind bereinigt; Fremdnetz-, Positiv-, Negativ- und Wiederanlauftests sind abgeschlossen.
  • Fail2Ban läuft, seine aktuelle funktionale Ban-Wirkung ist aber nicht abgenommen.
  • Der KI-Server ist bewusst ausgeschaltet und wird für die Punkte A bis D nicht benötigt.
  • CT 102 befindet sich in der 14-tägigen Stabilisierungsphase; der praktische NPM-Rückfall auf den ausgeschalteten CT 104 bleibt offen.

6. Pflege

Nach jedem Arbeitsschritt werden hier Status und Nachweis aktualisiert. Ein Punkt gilt nicht allein aufgrund einer gespeicherten Konfiguration als erledigt, sondern erst nach dem zugehörigen Positiv- oder Negativtest.