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

338 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
```text
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:
```text
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
- [x] Projekt- und Live-Zustand von DNS, Reverse Proxy und WireGuard lesend
inventarisiert.
- [x] Dokumentation in die geräteorientierte Zielstruktur verschieben.
- [x] Alle relativen lokalen Markdown-Links nach der Verschiebung validieren.
- [x] Zentrale Indizes und Architekturübersicht an die neue Struktur anpassen.
- [x] WireGuard-Profile aus dem Repository-Baum in einen privaten lokalen
Konfigurationspfad verschieben; Verzeichnis `0700`, Dateien `0600`.
- [x] Sicherstellen, dass keine WireGuard-PrivateKeys oder PresharedKeys in
versionierten Dateien oder der Git-Historie liegen.
- [x] Bereits offengelegte Altpeers über wg-easy rotieren oder widerrufen.
- [x] 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
- [x] 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.
- [x] Laptop-Profil geschützt in NetworkManager importieren und Autoconnect
zunächst deaktiviert lassen.
- [x] Verbindung aus einem fremden Netz positiv testen: Handshake, erlaubtes
Ziel, Split-Tunnel und DNS.
- [x] Alten Laptopzugang zunächst Server Admin zuordnen und anschließend durch
den neuen Peer `ghost-laptop` mit nativer nftables-Durchsetzung ersetzen.
- [x] Testpeer `Android-LLMAdmin` widerrufen und aus wg-easy entfernen.
- [x] Vor Gateway-Änderungen ein aktuelles konsistentes Backup von CT 105
erstellen.
- [x] 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.
- [x] Positive und negative Rollentests mit absichtlich erweitertem
Client-Routing durchführen.
- [x] CT 105 härten: SSH-Forwarding abschalten, Patchverfahren festlegen,
defekte `wtmpdb-rotate.timer`-Referenz bereinigen und Wiederanlauf testen.
### C. Interner Keycloak-Adminzugang
- [x] Sichere SSH-Zugänge für den Keycloak-LXC nach der gemeinsamen
LXC-Baseline einrichten und positiv wie negativ testen.
- [x] Aktuellen Keycloak-Stand und wirksame Hostname-/Proxy-Konfiguration
sichern und inventarisieren.
- [x] Leserechte der lokalen Keycloak-H2-Datenbank sofort auf Root begrenzen
und den Agenten-Negativtest wiederholen.
- [x] H2-`dev-file` und `start-dev` durch eine gesicherte
Podman-/PostgreSQL-Blue/Green-Migration nach GNAI-015 ersetzen.
- [x] Keycloak 26.2.4 im gepinnten Produktionsimage betreiben; ein späteres
26.x-Upgrade bleibt ein eigener kontrollierter Wartungsschritt.
- [x] Internen NPM-vHost für `auth-admin.ghostnet.selfhost.eu` mit gültigem TLS
und ohne öffentliche Freigabe einrichten.
- [x] Keycloak `hostname-admin` passend zur installierten Version setzen.
- [x] Internen Adminlogin über LAN positiv testen; Server-Admin-VPN nutzt
denselben per Gateway freigegebenen NPM-Zielpfad.
- [x] Öffentliche `/admin`-GUI und Admin-API über HTTPS sperren.
- [x] 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.
- [x] 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.