Ghost.net AI Struktur um Encoding erweitert.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
Dokumentation für die Infrastruktur eines privaten Homelabs mit öffentlich erreichbaren Webdiensten, einem WireGuard-Zugang und einem dedizierten KI-Server. Dieses Repository hält Architekturentscheidungen, den belegten Betriebsstand und Verfahren für Einrichtung, Betrieb und Sicherheitsabnahme fest.
|
||||
|
||||
> **Projektstand: 20.09.2026.** Die Dokumentationsrevisionen sind zusammengeführt. Mehrere Sicherheitsmaßnahmen und technische Endabnahmen stehen noch aus. Auf dem KI-Server sind die gemeinsame Host-Baseline und Podman eingerichtet; der LLM-Anwendungsstack ist noch nicht installiert.
|
||||
> **Projektstand: 20.09.2026.** Die Dokumentationsrevisionen sind zusammengeführt. Mehrere Sicherheitsmaßnahmen und technische Endabnahmen stehen noch aus. Auf dem KI-Server sind Host-Baseline, Podman und getrennte rootless Workload-Konten eingerichtet; LLM- und Encoding-Anwendungen sind noch nicht installiert.
|
||||
|
||||
## Überblick
|
||||
|
||||
@@ -26,7 +26,7 @@ Die drei vorgesehenen VPN-Netzwerkrollen sind **Familie** (gesamtes Heimnetz), *
|
||||
|
||||
| Bereich | Belegter Stand | Nächster Nachweis oder Schritt |
|
||||
| --- | --- | --- |
|
||||
| KI-Server | Debian-Basissystem, verifizierter Deployment-Zugang, minimale Host-Baseline und Podman 5.4.2 mit geprüftem Quadlet-Generator | Ausführungsmodell und Service-Accounts für Production und Testing festlegen; danach GPU-Laufzeit prüfen |
|
||||
| KI-Server | Debian-Basissystem, Deployment-Zugang, Host-Baseline, Podman 5.4.2 und drei getrennte rootless Workload-Konten | GPU-Zugriff für KI prüfen sowie Encoding-Zeitfenster und Ressourcenlimits festlegen |
|
||||
| VPN | wg-easy v15.4.0 auf CT 105 aktiv; ein externer Laptop-Teiltest liegt vor | Rollenrechte serverseitig umsetzen und mit erlaubten sowie gesperrten Zielen testen |
|
||||
| Reverse Proxy | NPM auf CT 103 dokumentiert; Fail2Ban laut Betreiber fest gepinnt und wieder in Betrieb | Effektive Jails, Sperren und Wiederanlauf prüfen |
|
||||
| Identität | Keycloak/OIDC laut Betreiber produktiv für Vaultwarden | Öffentlich erreichbare Keycloak-Administration sperren und den OIDC-Login erneut prüfen |
|
||||
@@ -38,21 +38,15 @@ Der [Dokumentationsindex](docs/GNAI-000-DOC_Index.md) enthält die datierten Que
|
||||
| Einstieg | Inhalt |
|
||||
| --- | --- |
|
||||
| [Dokumentationsindex und Projektstand](docs/GNAI-000-DOC_Index.md) | Dokumentenübersicht, bestätigte Entscheidungen und offene Befunde |
|
||||
| [Zielarchitektur](docs/GNAI-003-INFRA_Architecture.md) | Komponenten, Datenwege und geplante Sicherheitszonen |
|
||||
| [Zugriffsmodell](docs/GNAI-004-SEC_Access-Control.md) | Rollen, Zugriffsmatrix und Authentifizierung |
|
||||
| [Basissystem](docs/GNAI-001-INFRA_BaseSystem.md) und [Benutzer, Netz und SSH](docs/GNAI-002-INFRA_Users.md) | KI-Server-Basis und zugehörige Prüfungen |
|
||||
| [Reverse Proxy und Fail2Ban](docs/GNAI-005-SEC_Reverse-Proxy.md) | Konfiguration, Keycloak-Korrektur und ausstehende Abnahme |
|
||||
| [WireGuard-Gateway](docs/GNAI-006-SEC_VPN.md) | Gateway-Aufbau, Ist-Stand und Rollen-Firewall |
|
||||
| [Client-Verwaltung](docs/GNAI-006-SEC_VPN_Client-Management.md) | Profile ausgeben, ändern, widerrufen und Rollen prüfen |
|
||||
| [Windows 11](docs/GNAI-006-SEC_VPN_Clients_Windows11.md) und [Linux](docs/GNAI-006-SEC_VPN_Clients_Linux.md) | Einrichtung und Nutzung auf Endgeräten |
|
||||
| [WireGuard-Implementation-Log](docs/GNAI-006-SEC_VPN_Implementation-Log.md) | Historie, Tests und Korrekturen früherer Befunde |
|
||||
| [Ansible-Deployment-Planung](docs/GNAI-007-PLAN_Ansible-Deployment.md) | nicht finaler Arbeitsentwurf zur reproduzierbaren Bereitstellung, Gitea-Integration und geplanten Folgedokumentation |
|
||||
| [Ansible-Control-Projekt](ansible/README.md) | lokale Einrichtung, Preflight, Deployment-Account, Host-Baseline und Podman-Runtime |
|
||||
| [Plattform-Dokumentation](docs/platform/README.md) | Hostbasis, Zugriffsmodell, Reverse Proxy und VPN |
|
||||
| [KI-Dokumentation](docs/ai/README.md) | KI-Zielarchitektur und nicht finale Ansible-Deployment-Planung |
|
||||
| [Video-Encoding](docs/video-encoding/GNENC-000-DOC_Index.md) | getrennter Planungs- und späterer SOP-Bereich für den CPU-Encoding-Workload |
|
||||
| [Ansible-Control-Projekt](ansible/README.md) | lokale Einrichtung, Preflight, Deployment-Account, Host-Baseline, Podman und Workload-Konten |
|
||||
|
||||
## Arbeiten mit dem Repository
|
||||
|
||||
Dieses Repository enthält Dokumentation und ein Ansible-Control-Projekt. Es prüft Inventar, SSH-Zugang, Hostidentität, Betriebssystem und die dokumentierten GPUs. Gemeinsame Rollen verwalten die Konfigurations- und Datenwurzeln sowie Podman und Quadlet. Images, Container und der KI-Anwendungsstack sind noch nicht bereitgestellt. Vor einer Infrastrukturänderung den Ist-Stand am betroffenen Host prüfen, die passende Fachanleitung lesen und die dort genannten Abnahmeschritte dokumentieren.
|
||||
Dieses Repository enthält Dokumentation und ein Ansible-Control-Projekt. Es prüft Inventar, SSH-Zugang, Hostidentität, Betriebssystem und die dokumentierten GPUs. Gemeinsame Rollen verwalten Plattform, Podman und getrennte Workload-Identitäten. KI- und Encoding-Fachdokumentation bleiben in getrennten Bereichen; Images und Container sind noch nicht bereitgestellt. Vor einer Infrastrukturänderung den Ist-Stand am betroffenen Host prüfen, die passende Fachanleitung lesen und die dort genannten Abnahmeschritte dokumentieren.
|
||||
|
||||
WireGuard-Profile enthalten private Schlüssel. Sie gehören nicht in Git, Ausgaben oder freigegebene Dokumente. Das lokale Verzeichnis `docs/GNAI-006-profiles/` schließt Profil-Dateien über eine eigene `.gitignore` aus; es ist kein Verteiler- oder Backup-Ort für Zugangsdaten.
|
||||
WireGuard-Profile enthalten private Schlüssel. Sie gehören nicht in Git, Ausgaben oder freigegebene Dokumente. Das lokale Verzeichnis `docs/platform/GNAI-006-profiles/` schließt Profil-Dateien über eine eigene `.gitignore` aus; es ist kein Verteiler- oder Backup-Ort für Zugangsdaten.
|
||||
|
||||
Änderungen am Projektstand sollten zuerst im zuständigen Fachdokument mit Datum und Beleg erfasst werden. Anschließend den [Index](docs/GNAI-000-DOC_Index.md) und diese README aktualisieren, wenn sich eine übergreifende Aussage geändert hat.
|
||||
|
||||
+24
-7
@@ -106,13 +106,14 @@ unprivileged SSH identity and non-interactive escalation to effective UID 0.
|
||||
|
||||
## Shared host baseline
|
||||
|
||||
The host baseline is common to Production and Testing. It verifies the target
|
||||
identity and at least 100 GiB free on the root filesystem, then manages these
|
||||
root-owned directory roots:
|
||||
The host baseline is common to all workloads. It verifies the target identity
|
||||
and at least 100 GiB free on the root filesystem, then manages these root-owned
|
||||
parent and shared-data roots:
|
||||
|
||||
```text
|
||||
/etc/ghostnet-ai/{production,testing}
|
||||
/var/lib/ghostnet-ai/{production,testing,shared}
|
||||
/etc/ghostnet-ai
|
||||
/var/lib/ghostnet-ai
|
||||
/var/lib/ghostnet-ai/shared
|
||||
```
|
||||
|
||||
It does not install software or start services. Use the dedicated host
|
||||
@@ -147,7 +148,23 @@ overlay storage driver and exercises the installed Quadlet generator without
|
||||
creating a workload.
|
||||
|
||||
The role explicitly keeps the Podman API socket and automatic image-update
|
||||
timer disabled. It pulls no image and does not yet choose rootful or rootless
|
||||
execution for the two environments. Apply and check it through the same
|
||||
timer disabled. It pulls no image. Apply and check it through the same
|
||||
`playbooks/host.yml` commands shown above. The first run may install packages;
|
||||
an immediate second run must report `changed=0`.
|
||||
|
||||
## Workload accounts
|
||||
|
||||
The shared host play creates three locked service identities with deterministic
|
||||
UID/GID and subordinate-ID ranges:
|
||||
|
||||
| Account | UID/GID | Purpose | Rootless Podman graph root |
|
||||
| --- | --- | --- | --- |
|
||||
| `gnai-production` | 980 | stable AI Production | `/var/lib/ghostnet-ai/production/.local/share/containers/storage` |
|
||||
| `gnai-testing` | 981 | temporary AI Testing | `/var/lib/ghostnet-ai/testing/.local/share/containers/storage` |
|
||||
| `gn-encoding` | 982 | scheduled CPU video encoding | `/var/lib/ghostnet-encoding/.local/share/containers/storage` |
|
||||
|
||||
Each account has a persistent systemd user manager and a separate,
|
||||
administrator-managed directory below `/etc/containers/systemd/users/<UID>`.
|
||||
Configuration is root-owned and group-readable; workload data belongs to its
|
||||
service account. The role does not grant GPU access and creates no workload
|
||||
containers.
|
||||
|
||||
@@ -11,3 +11,4 @@
|
||||
roles:
|
||||
- role: host_baseline
|
||||
- role: podman_runtime
|
||||
- role: workload_accounts
|
||||
|
||||
@@ -8,8 +8,10 @@ Its first version deliberately has a narrow scope:
|
||||
- refuse changes when hostname, Debian major version or primary IPv4 address
|
||||
do not match the declared target;
|
||||
- require at least 100 GiB free on the root filesystem; and
|
||||
- create root-owned configuration and persistent-data directory roots for both
|
||||
environments and future shared data.
|
||||
- create root-owned parent directories and the future shared-data root.
|
||||
|
||||
Environment-specific directory ownership is managed by `workload_accounts` so
|
||||
the shared baseline and workload identities do not compete over permissions.
|
||||
|
||||
It does not install packages, drivers, Podman or applications and does not
|
||||
start or stop services. Ownership below the directory roots will be assigned
|
||||
|
||||
@@ -10,15 +10,7 @@ host_baseline_minimum_root_free_gib: 100
|
||||
host_baseline_directories:
|
||||
- path: /etc/ghostnet-ai
|
||||
mode: "0755"
|
||||
- path: /etc/ghostnet-ai/production
|
||||
mode: "0750"
|
||||
- path: /etc/ghostnet-ai/testing
|
||||
mode: "0750"
|
||||
- path: /var/lib/ghostnet-ai
|
||||
mode: "0755"
|
||||
- path: /var/lib/ghostnet-ai/production
|
||||
mode: "0750"
|
||||
- path: /var/lib/ghostnet-ai/testing
|
||||
mode: "0750"
|
||||
- path: /var/lib/ghostnet-ai/shared
|
||||
mode: "0755"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
# Workload accounts
|
||||
|
||||
The `workload_accounts` role creates separate locked service identities for AI
|
||||
Production, AI Testing and CPU-based video encoding. Each identity receives a
|
||||
stable UID/GID, a non-overlapping subordinate ID range, a private data root, an
|
||||
administrator-managed rootless Quadlet directory and a persistent systemd user
|
||||
manager.
|
||||
|
||||
Configuration remains owned by root and is readable by the corresponding
|
||||
service group. Workload data and the rootless Podman store belong to the
|
||||
service account. The role verifies that all three Podman stores are rootless
|
||||
and use distinct graph roots.
|
||||
|
||||
The role does not grant GPU device access and does not define containers,
|
||||
networks, schedules or resource limits. Those states belong to the AI and
|
||||
video-encoding workload roles.
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
workload_accounts:
|
||||
- name: gnai-production
|
||||
uid: 980
|
||||
gid: 980
|
||||
comment: Ghostnet AI Production workload
|
||||
home: /var/lib/ghostnet-ai/production
|
||||
config_directory: /etc/ghostnet-ai/production
|
||||
subid_start: 362144
|
||||
supplementary_groups: []
|
||||
- name: gnai-testing
|
||||
uid: 981
|
||||
gid: 981
|
||||
comment: Ghostnet AI Testing workload
|
||||
home: /var/lib/ghostnet-ai/testing
|
||||
config_directory: /etc/ghostnet-ai/testing
|
||||
subid_start: 427680
|
||||
supplementary_groups: []
|
||||
- name: gn-encoding
|
||||
uid: 982
|
||||
gid: 982
|
||||
comment: Ghostnet video encoding workload
|
||||
home: /var/lib/ghostnet-encoding
|
||||
config_directory: /etc/ghostnet-encoding
|
||||
subid_start: 493216
|
||||
supplementary_groups: []
|
||||
|
||||
workload_subid_count: 65536
|
||||
workload_quadlet_user_directory: /etc/containers/systemd/users
|
||||
|
||||
workload_data_directories:
|
||||
- path: /var/lib/ghostnet-encoding/input
|
||||
owner: 982
|
||||
group: 982
|
||||
mode: "0750"
|
||||
- path: /var/lib/ghostnet-encoding/output
|
||||
owner: 982
|
||||
group: 982
|
||||
mode: "0750"
|
||||
- path: /var/lib/ghostnet-encoding/work
|
||||
owner: 982
|
||||
group: 982
|
||||
mode: "0750"
|
||||
@@ -0,0 +1,207 @@
|
||||
---
|
||||
- name: Verify workload account declarations
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- workload_accounts | map(attribute="name") | unique | length == workload_accounts | length
|
||||
- workload_accounts | map(attribute="uid") | unique | length == workload_accounts | length
|
||||
- workload_accounts | map(attribute="gid") | unique | length == workload_accounts | length
|
||||
- >-
|
||||
workload_accounts | map(attribute="subid_start") | unique | length ==
|
||||
workload_accounts | length
|
||||
fail_msg: Workload account names and numeric IDs must be unique.
|
||||
|
||||
- name: Create dedicated workload groups
|
||||
ansible.builtin.group:
|
||||
name: "{{ workload_account.name }}"
|
||||
gid: "{{ workload_account.gid }}"
|
||||
system: true
|
||||
state: present
|
||||
loop: "{{ workload_accounts }}"
|
||||
loop_control:
|
||||
loop_var: workload_account
|
||||
label: "{{ workload_account.name }}"
|
||||
|
||||
- name: Create locked workload service accounts
|
||||
ansible.builtin.user:
|
||||
name: "{{ workload_account.name }}"
|
||||
uid: "{{ workload_account.uid }}"
|
||||
group: "{{ workload_account.name }}"
|
||||
comment: "{{ workload_account.comment }}"
|
||||
home: "{{ workload_account.home }}"
|
||||
shell: /usr/sbin/nologin
|
||||
groups: "{{ workload_account.supplementary_groups | join(',') }}"
|
||||
append: false
|
||||
create_home: true
|
||||
system: true
|
||||
password_lock: true
|
||||
state: present
|
||||
loop: "{{ workload_accounts }}"
|
||||
loop_control:
|
||||
loop_var: workload_account
|
||||
label: "{{ workload_account.name }}"
|
||||
|
||||
- name: Assign deterministic subordinate UID ranges
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/subuid
|
||||
regexp: "^{{ workload_account.name | regex_escape }}:"
|
||||
line: >-
|
||||
{{ workload_account.name }}:{{ workload_account.subid_start }}:{{ workload_subid_count }}
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
loop: "{{ workload_accounts }}"
|
||||
loop_control:
|
||||
loop_var: workload_account
|
||||
label: "{{ workload_account.name }}"
|
||||
|
||||
- name: Assign deterministic subordinate GID ranges
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/subgid
|
||||
regexp: "^{{ workload_account.name | regex_escape }}:"
|
||||
line: >-
|
||||
{{ workload_account.name }}:{{ workload_account.subid_start }}:{{ workload_subid_count }}
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
loop: "{{ workload_accounts }}"
|
||||
loop_control:
|
||||
loop_var: workload_account
|
||||
label: "{{ workload_account.name }}"
|
||||
|
||||
- name: Assign workload data roots to their service accounts
|
||||
ansible.builtin.file:
|
||||
path: "{{ workload_account.home }}"
|
||||
state: directory
|
||||
owner: "{{ workload_account.uid }}"
|
||||
group: "{{ workload_account.gid }}"
|
||||
mode: "0750"
|
||||
loop: "{{ workload_accounts }}"
|
||||
loop_control:
|
||||
loop_var: workload_account
|
||||
label: "{{ workload_account.home }}"
|
||||
|
||||
- name: Keep workload configuration root-managed
|
||||
ansible.builtin.file:
|
||||
path: "{{ workload_account.config_directory }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: "{{ workload_account.gid }}"
|
||||
mode: "0750"
|
||||
loop: "{{ workload_accounts }}"
|
||||
loop_control:
|
||||
loop_var: workload_account
|
||||
label: "{{ workload_account.config_directory }}"
|
||||
|
||||
- name: Create workload-specific data directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ workload_directory.path }}"
|
||||
state: directory
|
||||
owner: "{{ workload_directory.owner }}"
|
||||
group: "{{ workload_directory.group }}"
|
||||
mode: "{{ workload_directory.mode }}"
|
||||
loop: "{{ workload_data_directories }}"
|
||||
loop_control:
|
||||
loop_var: workload_directory
|
||||
label: "{{ workload_directory.path }}"
|
||||
|
||||
- name: Create the administrator-managed rootless Quadlet root
|
||||
ansible.builtin.file:
|
||||
path: "{{ workload_quadlet_user_directory }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
|
||||
- name: Create separate administrator-managed Quadlet directories
|
||||
ansible.builtin.file:
|
||||
path: "{{ workload_quadlet_user_directory }}/{{ workload_account.uid }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
loop: "{{ workload_accounts }}"
|
||||
loop_control:
|
||||
loop_var: workload_account
|
||||
label: "{{ workload_account.name }} (UID {{ workload_account.uid }})"
|
||||
|
||||
- name: Enable persistent user managers for rootless Quadlets
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- /usr/bin/loginctl
|
||||
- enable-linger
|
||||
- "{{ workload_account.name }}"
|
||||
creates: "/var/lib/systemd/linger/{{ workload_account.name }}"
|
||||
loop: "{{ workload_accounts }}"
|
||||
loop_control:
|
||||
loop_var: workload_account
|
||||
label: "{{ workload_account.name }}"
|
||||
|
||||
- name: Wait for persistent user managers
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- /usr/bin/systemctl
|
||||
- is-active
|
||||
- "user@{{ workload_account.uid }}.service"
|
||||
changed_when: false
|
||||
register: workload_user_manager_status
|
||||
retries: 5
|
||||
delay: 1
|
||||
until: workload_user_manager_status.stdout == "active"
|
||||
loop: "{{ workload_accounts }}"
|
||||
loop_control:
|
||||
loop_var: workload_account
|
||||
label: "{{ workload_account.name }}"
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: Initialize and inspect each rootless Podman store
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- /usr/sbin/runuser
|
||||
- --user
|
||||
- "{{ workload_account.name }}"
|
||||
- --
|
||||
- /usr/bin/env
|
||||
- "HOME={{ workload_account.home }}"
|
||||
- "XDG_RUNTIME_DIR=/run/user/{{ workload_account.uid }}"
|
||||
- /usr/bin/podman
|
||||
- info
|
||||
- --format=json
|
||||
chdir: "{{ workload_account.home }}"
|
||||
changed_when: false
|
||||
register: workload_podman_info_commands
|
||||
loop: "{{ workload_accounts }}"
|
||||
loop_control:
|
||||
loop_var: workload_account
|
||||
label: "{{ workload_account.name }}"
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: Parse rootless Podman information
|
||||
ansible.builtin.set_fact:
|
||||
workload_podman_infos: >-
|
||||
{{ workload_podman_info_commands.results
|
||||
| map(attribute="stdout")
|
||||
| map("from_json")
|
||||
| list }}
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: Verify isolated rootless Podman stores
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- >-
|
||||
workload_podman_infos | map(attribute="host.security.rootless")
|
||||
| select("equalto", true) | list | length == workload_accounts | length
|
||||
- >-
|
||||
workload_podman_infos | map(attribute="store.graphRoot")
|
||||
| unique | list | length == workload_accounts | length
|
||||
fail_msg: Workload accounts do not have separate rootless Podman stores.
|
||||
success_msg: All workload accounts use separate rootless Podman stores.
|
||||
when: not ansible_check_mode
|
||||
|
||||
- name: Report workload account isolation
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
accounts: "{{ workload_accounts | map(attribute='name') | list }}"
|
||||
uids: "{{ workload_accounts | map(attribute='uid') | list }}"
|
||||
graph_roots: >-
|
||||
{{ workload_podman_infos | map(attribute="store.graphRoot") | list }}
|
||||
when: not ansible_check_mode
|
||||
+47
-21
@@ -5,20 +5,35 @@
|
||||
|
||||
## 1. Dokumente und Zielgruppen
|
||||
|
||||
### Plattform und Host
|
||||
|
||||
| Dokument | Zweck / Zielgruppe |
|
||||
| --- | --- |
|
||||
| [GNAI-001-INFRA_BaseSystem.md](GNAI-001-INFRA_BaseSystem.md) | Hardware und Debian-Installation; Intermediate IT |
|
||||
| [GNAI-002-INFRA_Users.md](GNAI-002-INFRA_Users.md) | Benutzer, statisches Hostnetz, Resolver und SSH; Intermediate IT |
|
||||
| [GNAI-003-INFRA_Architecture.md](GNAI-003-INFRA_Architecture.md) | Gesamtzielarchitektur und Inventar; Intermediate IT |
|
||||
| [GNAI-004-SEC_Access-Control.md](GNAI-004-SEC_Access-Control.md) | verbindliches Rollen- und Zugriffsziel; Intermediate IT |
|
||||
| [GNAI-005-SEC_Reverse-Proxy.md](GNAI-005-SEC_Reverse-Proxy.md) | NPM/Fail2Ban und Keycloak-Korrekturverfahren; Intermediate IT |
|
||||
| [GNAI-006-SEC_VPN.md](GNAI-006-SEC_VPN.md) | wg-easy-Installation/Konfiguration in Proxmox LXC; Intermediate IT |
|
||||
| [GNAI-006-SEC_VPN_Client-Management.md](GNAI-006-SEC_VPN_Client-Management.md) | neue eigenständige GUI-SOP für Ausgabe, Änderungen und Widerruf; Intermediate IT |
|
||||
| [GNAI-006-SEC_VPN_Clients_Windows11.md](GNAI-006-SEC_VPN_Clients_Windows11.md) | offizieller Windows-Client, Import und Verwendung; Junior IT |
|
||||
| [GNAI-006-SEC_VPN_Clients_Linux.md](GNAI-006-SEC_VPN_Clients_Linux.md) | Debian, Arch/CachyOS, Fedora/Kinoite; Junior IT |
|
||||
| [GNAI-006-SEC_VPN_Implementation-Log.md](GNAI-006-SEC_VPN_Implementation-Log.md) | historische v14/v15-Umsetzung und Evidenzkorrekturen; Intermediate IT |
|
||||
| [GNAI-007-PLAN_Ansible-Deployment.md](GNAI-007-PLAN_Ansible-Deployment.md) | nicht finaler Arbeitsentwurf zum Ansible-/Gitea-Deployment und zur geplanten Folgedokumentation; Infrastrukturadministratoren und Mitwirkende |
|
||||
| [Ansible-Control-Projekt](../ansible/README.md) | Control-Node, Preflight, Deployment-Account, Host-Baseline und Podman-Runtime; Intermediate IT |
|
||||
| [Bereichsindex](platform/README.md) | Einstieg in die Plattform- und Hostdokumentation |
|
||||
| [GNAI-001-INFRA_BaseSystem.md](platform/GNAI-001-INFRA_BaseSystem.md) | Hardware und Debian-Installation; Intermediate IT |
|
||||
| [GNAI-002-INFRA_Users.md](platform/GNAI-002-INFRA_Users.md) | Benutzer, statisches Hostnetz, Resolver und SSH; Intermediate IT |
|
||||
| [GNAI-004-SEC_Access-Control.md](platform/GNAI-004-SEC_Access-Control.md) | verbindliches Rollen- und Zugriffsziel; Intermediate IT |
|
||||
| [GNAI-005-SEC_Reverse-Proxy.md](platform/GNAI-005-SEC_Reverse-Proxy.md) | NPM/Fail2Ban und Keycloak-Korrekturverfahren; Intermediate IT |
|
||||
| [GNAI-006-SEC_VPN.md](platform/GNAI-006-SEC_VPN.md) | wg-easy-Installation/Konfiguration in Proxmox LXC; Intermediate IT |
|
||||
| [GNAI-006-SEC_VPN_Client-Management.md](platform/GNAI-006-SEC_VPN_Client-Management.md) | eigenständige GUI-SOP für Ausgabe, Änderungen und Widerruf; Intermediate IT |
|
||||
| [GNAI-006-SEC_VPN_Clients_Windows11.md](platform/GNAI-006-SEC_VPN_Clients_Windows11.md) | offizieller Windows-Client, Import und Verwendung; Junior IT |
|
||||
| [GNAI-006-SEC_VPN_Clients_Linux.md](platform/GNAI-006-SEC_VPN_Clients_Linux.md) | Debian, Arch/CachyOS, Fedora/Kinoite; Junior IT |
|
||||
| [GNAI-006-SEC_VPN_Implementation-Log.md](platform/GNAI-006-SEC_VPN_Implementation-Log.md) | historische v14/v15-Umsetzung und Evidenzkorrekturen; Intermediate IT |
|
||||
|
||||
### KI
|
||||
|
||||
| Dokument | Zweck / Zielgruppe |
|
||||
| --- | --- |
|
||||
| [Bereichsindex](ai/README.md) | Einstieg in die KI-spezifische Dokumentation |
|
||||
| [GNAI-003-INFRA_Architecture.md](ai/GNAI-003-INFRA_Architecture.md) | Gesamtzielarchitektur und Inventar des KI-Stacks; Intermediate IT |
|
||||
| [GNAI-007-PLAN_Ansible-Deployment.md](ai/GNAI-007-PLAN_Ansible-Deployment.md) | nicht finaler Arbeitsentwurf zum Ansible-/Gitea-Deployment und zur geplanten Folgedokumentation; Infrastrukturadministratoren und Mitwirkende |
|
||||
|
||||
### Video-Encoding und Automatisierung
|
||||
|
||||
| Dokument | Zweck / Zielgruppe |
|
||||
| --- | --- |
|
||||
| [Video-Encoding-Dokumentation](video-encoding/GNENC-000-DOC_Index.md) | getrennter Index für Architektur und spätere Nutzer-SOPs des CPU-Encoding-Workloads |
|
||||
| [Ansible-Control-Projekt](../ansible/README.md) | Control-Node, Preflight, Deployment-Account, Host-Baseline, Podman und Workload-Konten; Intermediate IT |
|
||||
|
||||
## 2. Verbindliche, bestätigte Entscheidungen
|
||||
|
||||
@@ -26,32 +41,34 @@ NPM ist `.10`, WireGuard `.15`, Proxmox `.2`, KI-Server `.90`, Fritzbox `.1`, je
|
||||
|
||||
Familie darf das gesamte Heimnetz erreichen; Server Admins Proxmox, Service-LXCs und KI-Server; LLM Admins ausschließlich KI-Server. Profile werden durch Administratoren pro Gerät erstellt und geschützt verteilt. Serverseitige Firewall Allowed IPs sollen die Rechte erzwingen. Per-Client Firewall ist aber derzeit deaktiviert. wg-easy-GUI-Zugriff ist für Familie und Server Admin vorgesehen; HTTPS ist ein offener Umsetzungsvorschlag.
|
||||
|
||||
wg-easy läuft rootful in CT 105 als Podman-Quadlet mit v15.4.0 und host-Netz im LXC. Ein lesender SSH-Abgleich am 18.09.2026 bestätigte aktives `wg-easy`/`nftables`, IPv4-Forwarding, eine breite VPN→LAN-Regel und MASQUERADE in `iptables-legacy`; Details und Grenzen stehen im [Implementation-Log](GNAI-006-SEC_VPN_Implementation-Log.md). MASQUERADE wird mangels Rückroute gebraucht. Ein nftables-Reload mit `flush ruleset` kann dynamische Regeln entfernen; Wiederanlauf muss abgenommen werden.
|
||||
wg-easy läuft rootful in CT 105 als Podman-Quadlet mit v15.4.0 und host-Netz im LXC. Ein lesender SSH-Abgleich am 18.09.2026 bestätigte aktives `wg-easy`/`nftables`, IPv4-Forwarding, eine breite VPN→LAN-Regel und MASQUERADE in `iptables-legacy`; Details und Grenzen stehen im [Implementation-Log](platform/GNAI-006-SEC_VPN_Implementation-Log.md). MASQUERADE wird mangels Rückroute gebraucht. Ein nftables-Reload mit `flush ruleset` kann dynamische Regeln entfernen; Wiederanlauf muss abgenommen werden.
|
||||
|
||||
Der KI-Server heißt laut lesendem SSH-Abgleich vom 18.09.2026 `ghostnet-ki`; die Konten sind `ghost`, `debugofen` und das neu angelegte `ghost-agent`. `admin` existiert auf diesem Host nicht; der WireGuard-LXC verwendet separat `admin`. `ghostnet.ki` mit Punkt ist höchstens ein lokal angelegter SSH-Alias. OIDC ist laut Betreiber produktiv nur für Vaultwarden; weitere Dienste sind geplant.
|
||||
Der KI-Server heißt laut lesendem SSH-Abgleich vom 18.09.2026 `ghostnet-ki`; damals bestanden die persönlichen Konten `ghost`, `debugofen` und das Agentenkonto `ghost-agent`. Inzwischen ergänzen `ansible-deploy` sowie die gesperrten Workload-Konten `gnai-production`, `gnai-testing` und `gn-encoding` diesen Bestand. `admin` existiert auf diesem Host nicht; der WireGuard-LXC verwendet separat `admin`. `ghostnet.ki` mit Punkt ist höchstens ein lokal angelegter SSH-Alias. OIDC ist laut Betreiber produktiv nur für Vaultwarden; weitere Dienste sind geplant.
|
||||
|
||||
Die getrennten Schlüsselzugänge für `ghost` und `ghost-agent` wurden am 19.09.2026 erfolgreich getestet. Der persönliche Login wurde vom Betreiber interaktiv bestätigt; der Agentenlogin wurde technisch gegen Benutzername und Hostname geprüft.
|
||||
|
||||
Der KI-Server wurde als frisches Debian-Basissystem begonnen. Inzwischen sind die dokumentierten Ansible-Zugänge, die minimale Host-Baseline und Podman eingerichtet. Die LLM-Anwendungen sind weiterhin nicht installiert; GNAI-003 und GNAI-004 beschreiben für sie ein Zielbild.
|
||||
|
||||
Der [Ansible-Deployment-Entwurf](GNAI-007-PLAN_Ansible-Deployment.md) persistiert den seit dem 19.09.2026 fortgeschriebenen Planungs- und Implementierungsstand. Er ist ausdrücklich keine verbindliche Spezifikation und kein Nachweis einer vollständig eingerichteten Deploymentkette. Die dort genannten Runner-, Freigabe- und Secret-Verfahren sind bis zu ihrer Prüfung und formalen Übernahme vorläufig.
|
||||
Der [Ansible-Deployment-Entwurf](ai/GNAI-007-PLAN_Ansible-Deployment.md) persistiert den seit dem 19.09.2026 fortgeschriebenen Planungs- und Implementierungsstand. Er ist ausdrücklich keine verbindliche Spezifikation und kein Nachweis einer vollständig eingerichteten Deploymentkette. Die dort genannten Runner-, Freigabe- und Secret-Verfahren sind bis zu ihrer Prüfung und formalen Übernahme vorläufig.
|
||||
|
||||
Das erste Ansible-Control-Projekt mit Testing-Inventar und lesendem Preflight wurde am 19.09.2026 angelegt. Der Live-Lauf über `ghost-agent` bestätigte Hostidentität, Debian 13.6, IPv4-Adresse, Python, CPU, RAM und zwei Navi-21-Geräte mit `changed=0`, `unreachable=0` und `failed=0`. Dieser Nachweis umfasst weder privilegierten Zugriff noch eine eingerichtete Production-/Testing-Laufzeitumgebung.
|
||||
|
||||
Der separate Ed25519-Schlüssel mit Fingerprint `SHA256:IKEInbIo8VVI1USg5+a3ypGK8H8FweJiQu+v7KvhQDU` und das Bootstrap-Playbook wurden am 19.09.2026 verwendet, um `ansible-deploy` einzurichten. Der private Schlüssel liegt ausschließlich außerhalb des Repositories. Der Account besitzt ein gesperrtes Passwort, einen auf LAN- und WireGuard-Quellnetze beschränkten Public Key und eine mit `visudo` validierte Regel `NOPASSWD: ALL`. Ein getrenntes Prüfplaybook bestätigte anschließend Anmeldung, Modulausführung und effektive UID 0 über sudo mit `ok=5 changed=0 unreachable=0 failed=0`.
|
||||
|
||||
Die erste schreibende Rolle `host_baseline` wurde am 19.09.2026 nach erfolgreichem Syntax- und Check-Modus-Lauf angewendet. Sie prüft Hostname, Debian-Hauptversion, Standard-IPv4 sowie mindestens 100 GiB freien Speicher und verwaltet ausschließlich `/etc/ghostnet-ai/{production,testing}` und `/var/lib/ghostnet-ai/{production,testing,shared}` mit Root-Eigentum. Der erste reale Lauf meldete `ok=6 changed=1 unreachable=0 failed=0`; der unmittelbar folgende identische Lauf belegte Idempotenz mit `ok=6 changed=0 unreachable=0 failed=0`. Pakete, Dienste und Anwendungen wurden dabei nicht verändert.
|
||||
Die erste schreibende Rolle `host_baseline` wurde am 19.09.2026 nach erfolgreichem Syntax- und Check-Modus-Lauf angewendet. Sie prüft Hostname, Debian-Hauptversion, Standard-IPv4 sowie mindestens 100 GiB freien Speicher. Die zunächst dort angelegten Umgebungsverzeichnisse werden seit Einführung der Servicekonten durch `workload_accounts` verwaltet; `host_baseline` besitzt nur noch die gemeinsamen Eltern und `/var/lib/ghostnet-ai/shared`. Der erste reale Lauf meldete `ok=6 changed=1 unreachable=0 failed=0`; der unmittelbar folgende identische Lauf belegte Idempotenz mit `ok=6 changed=0 unreachable=0 failed=0`.
|
||||
|
||||
Die Rolle `podman_runtime` wurde am 20.09.2026 angewendet. Sie installierte Podman 5.4.2 aus Debian 13 einschließlich expliziter DNS- und rootless Netzwerkvoraussetzungen, prüfte systemd, cgroup v2, Overlay-Storage und den Quadlet-Generator und legte `/etc/containers/systemd` an. `podman.socket` und `podman-auto-update.timer` werden deaktiviert und gestoppt gehalten. Der abschließende Gesamtlauf meldete `ok=20 changed=0 unreachable=0 failed=0`; eine getrennte Prüfung bestätigte leere Image- und Containerlisten sowie beide Units als `disabled` und `inactive`.
|
||||
|
||||
Die Rolle `workload_accounts` richtete am 20.09.2026 die gesperrten Konten `gnai-production` (UID/GID 980), `gnai-testing` (981) und `gn-encoding` (982) mit festen, getrennten SubID-Bereichen ein. Konfiguration bleibt rootverwaltet; Daten, rootless Podman-Stores und persistente systemd-User-Manager sind pro Workload getrennt. Der korrigierte Gesamtlauf meldete `ok=36 changed=0 unreachable=0 failed=0` und bestätigte drei unterschiedliche rootless Graph Roots. Images und Container wurden nicht angelegt.
|
||||
|
||||
## 3. Sicherheitsbefunde mit Priorität
|
||||
|
||||
| Befund | dokumentiertes Verfahren / Status |
|
||||
| --- | --- |
|
||||
| Keycloak-Administration öffentlich erreichbar, externe Anmeldung möglich | [GNAI-005](GNAI-005-SEC_Reverse-Proxy.md): Adminpfad-Schutz, interner Adminzugang, externe Sperrtests und Vaultwarden-OIDC-Prüfung; noch nicht angewendet |
|
||||
| VPN-Zielrechte nur im lokalen Profil | [GNAI-006](GNAI-006-SEC_VPN.md) und [GUI-SOP](GNAI-006-SEC_VPN_Client-Management.md): Per-Client Firewall, Gateway-INPUT-Regeln und negative Tests; noch nicht angewendet |
|
||||
| Fail2Ban-Image auf `1.1.0-r2-ls43` fest gepinnt; Container läuft wieder | [GNAI-005](GNAI-005-SEC_Reverse-Proxy.md): Pin umgesetzt; effektives Image, Jails, kontrollierte Bans sowie Dienst-/LXC-Wiederanlauf noch abzunehmen |
|
||||
| HTTP-Client-User-Agents werden bewusst gebannt | [GNAI-005](GNAI-005-SEC_Reverse-Proxy.md): mögliche legitime Treffer und rollen-/routingabhängiger VPN-Ausweichweg dokumentiert |
|
||||
| Keycloak-Administration öffentlich erreichbar, externe Anmeldung möglich | [GNAI-005](platform/GNAI-005-SEC_Reverse-Proxy.md): Adminpfad-Schutz, interner Adminzugang, externe Sperrtests und Vaultwarden-OIDC-Prüfung; noch nicht angewendet |
|
||||
| VPN-Zielrechte nur im lokalen Profil | [GNAI-006](platform/GNAI-006-SEC_VPN.md) und [GUI-SOP](platform/GNAI-006-SEC_VPN_Client-Management.md): Per-Client Firewall, Gateway-INPUT-Regeln und negative Tests; noch nicht angewendet |
|
||||
| Fail2Ban-Image auf `1.1.0-r2-ls43` fest gepinnt; Container läuft wieder | [GNAI-005](platform/GNAI-005-SEC_Reverse-Proxy.md): Pin umgesetzt; effektives Image, Jails, kontrollierte Bans sowie Dienst-/LXC-Wiederanlauf noch abzunehmen |
|
||||
| HTTP-Client-User-Agents werden bewusst gebannt | [GNAI-005](platform/GNAI-005-SEC_Reverse-Proxy.md): mögliche legitime Treffer und rollen-/routingabhängiger VPN-Ausweichweg dokumentiert |
|
||||
|
||||
## 4. Noch erforderliche Angaben
|
||||
|
||||
@@ -69,7 +86,7 @@ Es werden keine Werte für diese offenen Angaben angenommen. Die betreffenden Ve
|
||||
|
||||
Bei der Dokumentationskonsolidierung wurden keine Serverkonfigurationen geändert, keine VPN-Praxisprüfungen nachgeholt und keine Keycloak-Sperre live bestätigt. Aussagen zum Ist-Stand beruhen auf den protokollierten Betreiberangaben und Tests; sie sind keine neue Live-Inventur.
|
||||
|
||||
Am 18.09.2026 wurden WireGuard-LXC und KI-Server ergänzend lesend per SSH geprüft. Der KI-Server-Teilabgleich bestätigt Hostname, Konten, Netzkonfiguration, Debian-Version, CPU, RAM, zwei Navi-21-GPUs und SSD-Partitionierung; BIOS, ROCm und die Anwendungsdienste wurden dabei nicht abgenommen. Details stehen in [GNAI-001](GNAI-001-INFRA_BaseSystem.md) und [GNAI-002](GNAI-002-INFRA_Users.md).
|
||||
Am 18.09.2026 wurden WireGuard-LXC und KI-Server ergänzend lesend per SSH geprüft. Der KI-Server-Teilabgleich bestätigt Hostname, Konten, Netzkonfiguration, Debian-Version, CPU, RAM, zwei Navi-21-GPUs und SSD-Partitionierung; BIOS, ROCm und die Anwendungsdienste wurden dabei nicht abgenommen. Details stehen in [GNAI-001](platform/GNAI-001-INFRA_BaseSystem.md) und [GNAI-002](platform/GNAI-002-INFRA_Users.md).
|
||||
|
||||
Am 19.09.2026 bestätigte ein erster reproduzierbarer Ansible-Preflight über das unprivilegierte Konto `ghost-agent` erneut `ghostnet-ki`, Debian 13.6, `10.0.0.90`, 14 vCPUs, 64.123 MiB RAM, Remote-Python 3.13.5 und zwei PCI-Geräte `1002:73bf`. Der Play Recap lautete `ok=5 changed=0 unreachable=0 failed=0`. Das Playbook verwendete kein `sudo` und nahm keine Serverkonfiguration vor.
|
||||
|
||||
@@ -79,4 +96,13 @@ Für die gemeinsame Host-Baseline bestätigte ein vorgelagerter Check-Modus gena
|
||||
|
||||
Am 20.09.2026 sagte der Podman-Check-Modus 38 neue Debian-Pakete und das Quadlet-Verzeichnis voraus. Der reale Lauf installierte diese Pakete; seine erste Nachprüfung bewertete den Debian-Symlink des Quadlet-Generators irrtümlich nicht als reguläre Datei. Nach Korrektur der Ansible-`stat`-Prüfung auf das aufgelöste Ziel bestanden Podman 5.4.2, cgroup v2, Overlay-Storage und der Generator-Dry-Run. Der finale Gesamtlauf war mit `changed=0` idempotent. Es wurden weder Images geladen noch Container oder Anwendungsdienste angelegt.
|
||||
|
||||
Der anschließende Workload-Account-Lauf richtete drei Konten, feste
|
||||
SubUID-/SubGID-Bereiche, rootverwaltete Quadlet-Pfade und persistente
|
||||
systemd-User-Manager ein. Zwei reine Abschlussprüfungen deckten zunächst den
|
||||
nicht erlaubten direkten sudo-Benutzerwechsel sowie konkurrierende
|
||||
Verzeichniseigentümer zwischen Rollen auf. Nach Umstellung der Prüfung auf
|
||||
rootseitiges `runuser` und eindeutiger Eigentümerzuständigkeit endete der
|
||||
Gesamtlauf mit `ok=36 changed=0 unreachable=0 failed=0`. Die drei rootless
|
||||
Podman-Stores sind voneinander getrennt und noch leer.
|
||||
|
||||
Die WireGuard-Evidenz bleibt der Teiltest vom 12.09.2026: CachyOS-Laptop von WAN, Handshake, Ping auf Gateway/Proxmox und direkter IPv4-Internetpfad bestanden; KI-Server war ausgeschaltet. Neue Rollen, weitere Clientvarianten, Gateway-GUI-Zugriff, WAN-/IPv6-Isolation, Neustart und Restore sind noch nicht abgenommen. GNAI-006 ist erst nach Klärung der offenen Werte, Umsetzung und dokumentierter Abnahme technisch abgeschlossen.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
**Dokumenten-ID:** GNAI-003-INFRA
|
||||
**Titel:** Homelab / LLM-Infrastruktur – Zielarchitektur
|
||||
**Status:** Zielarchitektur; bestätigter Teilstand und offene Umsetzung separat ausgewiesen
|
||||
**Vorgänger / Referenzen:** [Basisinstallation](GNAI-001-INFRA_BaseSystem.md), [Benutzer/SSH](GNAI-002-INFRA_Users.md), [Zugriffskonzept](GNAI-004-SEC_Access-Control.md), [Reverse Proxy](GNAI-005-SEC_Reverse-Proxy.md), [WireGuard](GNAI-006-SEC_VPN.md)
|
||||
**Vorgänger / Referenzen:** [Basisinstallation](../platform/GNAI-001-INFRA_BaseSystem.md), [Benutzer/SSH](../platform/GNAI-002-INFRA_Users.md), [Zugriffskonzept](../platform/GNAI-004-SEC_Access-Control.md), [Reverse Proxy](../platform/GNAI-005-SEC_Reverse-Proxy.md), [WireGuard](../platform/GNAI-006-SEC_VPN.md)
|
||||
|
||||
---
|
||||
|
||||
@@ -338,4 +338,4 @@ Die Architektur gilt als korrekt umgesetzt, wenn mindestens folgende Eigenschaft
|
||||
|
||||
## 14. Umsetzungsstand
|
||||
|
||||
Die Architektur-Abnahmekriterien in Abschnitt 13 sind Sollkriterien und keine bestätigte Abnahme. Der aktuelle Projektstand und die priorisierten Befunde stehen im [Dokumentationsindex](GNAI-000-DOC_Index.md); technische Nachweise und offene Prüfungen werden in GNAI-005 und GNAI-006 geführt. Backendisolation und lokale Netzwerksegmentierung sind ebenfalls noch nachzuweisen.
|
||||
Die Architektur-Abnahmekriterien in Abschnitt 13 sind Sollkriterien und keine bestätigte Abnahme. Der aktuelle Projektstand und die priorisierten Befunde stehen im [Dokumentationsindex](../GNAI-000-DOC_Index.md); technische Nachweise und offene Prüfungen werden in GNAI-005 und GNAI-006 geführt. Backendisolation und lokale Netzwerksegmentierung sind ebenfalls noch nachzuweisen.
|
||||
+81
-41
@@ -4,7 +4,7 @@
|
||||
**Titel:** Ansible-Deployment für den KI-Server – Planungsstand
|
||||
**Stand:** 2026-09-20
|
||||
**Status:** Nicht finaler Arbeitsentwurf zur Persistierung des aktuellen Planungsstands
|
||||
**Referenzen:** [Projektstand](GNAI-000-DOC_Index.md), [Zielarchitektur](GNAI-003-INFRA_Architecture.md), [Zugriffskonzept](GNAI-004-SEC_Access-Control.md)
|
||||
**Referenzen:** [Projektstand](../GNAI-000-DOC_Index.md), [Zielarchitektur](GNAI-003-INFRA_Architecture.md), [Zugriffskonzept](../platform/GNAI-004-SEC_Access-Control.md)
|
||||
|
||||
> **Abgrenzung:** Dieses Dokument hält die Ergebnisse der am 19.09.2026
|
||||
> begonnenen und am 20.09.2026 fortgeschriebenen Planungssession fest. Es ist
|
||||
@@ -27,6 +27,7 @@
|
||||
| 2026-09-19 | 0.6 | spektr / Codex | `ansible-deploy` auf dem KI-Server eingerichtet und SSH-/sudo-Zugriff unabhängig erfolgreich verifiziert |
|
||||
| 2026-09-19 | 0.7 | spektr / Codex | minimale gemeinsame Host-Baseline mit Schutzprüfungen und getrennten Verzeichniswurzeln implementiert, angewendet und auf Idempotenz geprüft |
|
||||
| 2026-09-20 | 0.8 | spektr / Codex | gemeinsame Podman-/Quadlet-Runtime implementiert, installiert und ohne Images oder Container verifiziert |
|
||||
| 2026-09-20 | 0.9 | spektr / Codex | getrennte rootless Konten für AI Production, AI Testing und CPU-Encoding eingerichtet; Parallelitäts- und Repository-Grenzen ergänzt |
|
||||
|
||||
---
|
||||
|
||||
@@ -73,6 +74,11 @@ ein Production-Inventar existieren noch nicht. Der Preflight selbst nahm keine
|
||||
Änderungen vor; die bislang angewendeten Rollen bleiben auf die nachfolgend
|
||||
dokumentierten Zugangs-, Verzeichnis- und Runtime-Zustände begrenzt.
|
||||
|
||||
Ein fachlich vom LLM-Stack getrennter CPU-Encoding-Workload wird auf demselben
|
||||
Host vorgesehen. Sein Ansible-Sollzustand bleibt wegen des gemeinsamen Hosts im
|
||||
Infrastructure-Repository; Architektur und spätere Nutzer-SOPs werden unter
|
||||
[`docs/video-encoding/`](../video-encoding/GNENC-000-DOC_Index.md) getrennt geführt.
|
||||
|
||||
---
|
||||
|
||||
## 3. Vorläufiges Zielbild
|
||||
@@ -114,7 +120,7 @@ Planungsrichtung und noch nicht bestätigten Implementierungsdetails.
|
||||
|
||||
| Thema | Aktueller Planungsstand | Verbindlichkeit / Nachweis |
|
||||
| --- | --- | --- |
|
||||
| Konfigurationsmanagement | Ansible beschreibt Basissystem, Laufzeitumgebung, Dienste und Konfiguration | Control-Projekt, Preflight, `host_baseline` und `podman_runtime` vorhanden und angewendet; GPU- und Anwendungsrollen fehlen noch |
|
||||
| Konfigurationsmanagement | Ansible beschreibt Basissystem, Laufzeitumgebung, Dienste und Konfiguration | Control-Projekt, Preflight, `host_baseline`, `podman_runtime` und `workload_accounts` vorhanden und angewendet; GPU- und Anwendungsrollen fehlen noch |
|
||||
| Quell- und Freigabeverfahren | Änderungen über Gitea-Branches und Pull Requests; kein regulärer Direkt-Push auf `main` | vorgesehen; Branch-Schutz noch nicht geprüft oder eingerichtet |
|
||||
| CI | Pull Requests erhalten Lint-, YAML- und Ansible-Syntaxprüfungen ohne produktive Zugangsdaten | vorgesehen; Workflow noch nicht vorhanden |
|
||||
| Produktionsausführung | Gitea Actions startet Ansible über eine dedizierte Production-Berechtigungsstufe | bevorzugte Lösung; Gitea-Version, Runner-Trennung und Actions-Funktion noch zu prüfen |
|
||||
@@ -125,13 +131,14 @@ Planungsrichtung und noch nicht bestätigten Implementierungsdetails.
|
||||
| Zielzugang | eigener technischer SSH-Account `ansible-deploy` mit separatem, quellnetzbeschränktem Schlüssel und validiertem `NOPASSWD: ALL` | auf dem KI-Server eingerichtet und unabhängig verifiziert; spätere Runner-Übernahme und Rotation offen |
|
||||
| Geheimnisse | verschlüsselte Ansible-Variablen plus getrennt gespeichertes Vault-Passwort und Runner-Zugangsdaten | Richtung angenommen; konkreter Secret-Workflow noch offen |
|
||||
| Artefaktversionen | Pakete, Collections und Container-Images werden auf konkrete Versionen, nach Möglichkeit Digests, festgelegt | vorgesehen |
|
||||
| Repository-Zuschnitt | vorerst ausschließlich das bestehende Repository `infrastructure`; weitere Quellcode-Repositories erst bei tatsächlich eigenständig entwickelten Anwendungen oder MCP-Komponenten | als aktuelle Planungsentscheidung angenommen |
|
||||
| Repository-Zuschnitt | `infrastructure` bleibt alleinige Quelle für alle Ansible-Zustände des Hosts; KI- und Encoding-Dokumentation werden getrennt geführt; weitere Quellcode-Repositories erst bei eigenständig entwickelten Anwendungen | als aktuelle Planungsentscheidung angenommen |
|
||||
| Anwendungsupdates | Upstream-Artefakte werden im Infrastruktur-Repository auf eine geprüfte Version festgelegt; eigene Build-Repositories sind vorerst nicht Bestandteil des Projekts | vorgesehen; Registry- und Buildverfahren bei späterem Eigenentwicklungsbedarf neu bewerten |
|
||||
| Automatische Updates | kein unbeaufsichtigtes Produktionsupdate über `latest` oder Watchtower | vorläufige Sicherheitsentscheidung |
|
||||
| Laufzeitumgebungen | Production und Testing werden als getrennte Stacks auf demselben physischen KI-Server betrieben | als aktuelle Planungsentscheidung angenommen |
|
||||
| Production | stabiler, extern nutzbarer Stand mit bewusst freigegebenen Versionen | Zielbild; Dienste noch nicht eingerichtet |
|
||||
| Testing | interner, kurzlebiger oder zurücksetzbarer Stand für kontrollierte Tests vor dem Merge nach `main`; nutzt während eines Wartungsfensters die vollständige Hardware exklusiv | Zielbild; Dienste, Zugriffsweg und Umschaltverfahren noch nicht eingerichtet |
|
||||
| Ressourcenbetrieb | keine feste physische Aufteilung; Production und Testing laufen nicht gleichzeitig und werden über einen exklusiven Umschaltvorgang zeitlich gestaffelt | als aktuelle Planungsentscheidung angenommen |
|
||||
| Testing | interner, kurzlebiger oder zurücksetzbarer Stand für kontrollierte Tests vor dem Merge nach `main`; nutzt während eines Wartungsfensters beide GPUs exklusiv gegenüber Production | Zielbild; Dienste, Zugriffsweg und Umschaltverfahren noch nicht eingerichtet |
|
||||
| Ressourcenbetrieb | AI Production und AI Testing laufen nicht gleichzeitig; der getrennte CPU-Encoding-Workload darf nachts parallel zur jeweils aktiven KI-Umgebung laufen | als aktuelle Planungsentscheidung angenommen; Grenzwerte und Lasttest offen |
|
||||
| Workload-Konten | `gnai-production`, `gnai-testing` und `gn-encoding` verwenden getrennte rootless Podman-Stores und systemd-User-Manager | eingerichtet und mit `changed=0` verifiziert |
|
||||
| Betriebsnachweis | erfolgreicher Lauf dokumentiert Git-Commit, Zielhost, Zeitpunkt, Prüfungen und Ergebnis | vorgesehen |
|
||||
| Rollback | Konfigurationsänderung über Revert und erneute Freigabe; persistente Daten zusätzlich über getestete Backups wiederherstellen | Grundprinzip; konkrete SOP noch zu erstellen |
|
||||
|
||||
@@ -223,9 +230,11 @@ Umgebung läuft.
|
||||
Production und Testing laufen zunächst auf demselben physischen KI-Server.
|
||||
Damit können Anwendungscontainer, Konfigurationen und Daten sauber logisch
|
||||
getrennt werden. Die Hardware kann wegen des hohen Leistungsbedarfs nicht
|
||||
dauerhaft zwischen beiden Umgebungen aufgeteilt werden. Stattdessen erhält die
|
||||
jeweils aktive Umgebung CPU, RAM und beide GPUs exklusiv. Es entstehen dennoch
|
||||
keine getrennten Fehlerdomänen:
|
||||
dauerhaft zwischen beiden KI-Umgebungen aufgeteilt werden. Stattdessen erhält
|
||||
die jeweils aktive KI-Umgebung beide GPUs exklusiv gegenüber der anderen
|
||||
KI-Umgebung. Ein fachlich getrennter CPU-Encoding-Workload darf außerhalb der
|
||||
Stoßzeiten parallel laufen. Es entstehen dennoch keine getrennten
|
||||
Fehlerdomänen:
|
||||
|
||||
- Kernel, AMD-Treiber beziehungsweise ROCm, Podman und systemd werden gemeinsam
|
||||
verwendet;
|
||||
@@ -256,19 +265,27 @@ geplante Unterbrechung von Production.
|
||||
| Persistente Daten | eigene Volumes mit Backup- und Restore-Verfahren | eigene zurücksetzbare Volumes; keine Production-Datenkopie ohne Bereinigung und Freigabe |
|
||||
| Secrets und API-Keys | ausschließlich Production-Credentials | eigene eingeschränkte Test-Credentials |
|
||||
| Ports und Hostnamen | stabile freigegebene Endpunkte | getrennte interne Ports und noch festzulegende Testhostnamen |
|
||||
| Ressourcen | erhält im Normalbetrieb die vollständige Hardware exklusiv | erhält ausschließlich im freigegebenen Testfenster die vollständige Hardware exklusiv |
|
||||
| Ressourcen | erhält im Normalbetrieb beide GPUs und das festzulegende KI-Ressourcenbudget | erhält im Testfenster beide GPUs und das festzulegende KI-Ressourcenbudget |
|
||||
| GPU | beide GPUs, solange Production aktiv ist | beide GPUs, nachdem Production vollständig beendet wurde |
|
||||
| Ausführungszustand | standardmäßig aktiv | standardmäßig gestoppt |
|
||||
| Verfügbarkeit | stabiler Betriebsstand außerhalb angekündigter Wartungsfenster | best effort; wird nach jedem Testlauf wieder vollständig gestoppt |
|
||||
|
||||
Eine gleichzeitige Inferenzlast beider Umgebungen ist nicht vorgesehen. Vor dem
|
||||
Eine gleichzeitige Inferenzlast beider KI-Umgebungen ist nicht vorgesehen. Vor dem
|
||||
Start von Testing muss nachweisbar sein, dass Production beendet wurde und
|
||||
keine zugehörigen Prozesse mehr CPU-, RAM- oder GPU-Ressourcen halten. Vor dem
|
||||
Wiederanlauf von Production muss Testing entsprechend vollständig beendet und
|
||||
sein temporärer Zustand bereinigt sein. Speicherplatz- und Prozessgrenzen
|
||||
bleiben auch bei exklusiver Rechenleistung sinnvoll, damit ein Test nicht den
|
||||
bleiben auch bei exklusiver GPU-Nutzung sinnvoll, damit ein Test nicht den
|
||||
gemeinsamen Datenträger füllt oder den Host dauerhaft beeinträchtigt.
|
||||
|
||||
Der CPU-basierte Encoding-Workload ist nicht Teil dieser KI-Umschaltung. Er darf
|
||||
nachts parallel zu Production oder Testing laufen, erhält keinen GPU-Zugriff
|
||||
und muss über CPU-, Speicher- und I/O-Grenzen die Reaktionsfähigkeit der
|
||||
KI-Dienste schützen. Die Betreiberfestlegung „CPU-basiert“ und die geplante
|
||||
Parallelität sind noch durch einen repräsentativen gemeinsamen Lasttest zu
|
||||
bestätigen. Zeitfenster und Grenzwerte werden ausschließlich im getrennten
|
||||
[Encoding-Plan](../video-encoding/GNENC-001-PLAN_Architecture.md) spezifiziert.
|
||||
|
||||
Große schreibgeschützte Modelldateien können später aus einem gemeinsamen,
|
||||
nur lesbar eingebundenen Modellspeicher bereitgestellt werden. Datenbanken,
|
||||
Uploads, Caches mit Schreibzugriff, Benutzerkonten und Anwendungsschlüssel
|
||||
@@ -290,7 +307,7 @@ Production. Der vorläufige Ablauf lautet:
|
||||
geordnet beenden;
|
||||
5. prüfen, dass alle Production-Units, -Container und GPU-Prozesse beendet
|
||||
sind;
|
||||
6. einen hostweiten exklusiven Deployment-Lock setzen;
|
||||
6. einen exklusiven Lock für den KI-Umgebungswechsel setzen;
|
||||
7. Testing für den festgelegten Commit ausrollen und mit der vollständigen
|
||||
Hardware starten;
|
||||
8. Health Checks und fachliche Tests ausführen und Ergebnisse dem Pull Request
|
||||
@@ -318,7 +335,8 @@ Verfügung.
|
||||
|
||||
Production und Testing dürfen niemals gleichzeitig als aktiv markiert sein.
|
||||
Jeder Start prüft den Gegenstatus und bricht bei einem widersprüchlichen oder
|
||||
unklaren Zustand ab.
|
||||
unklaren Zustand ab. Der Encoding-Workload bleibt von diesem KI-Lock unabhängig;
|
||||
ein allgemeines Hostwartungsfenster kann weiterhin alle Workloads stoppen.
|
||||
|
||||
### 7.4 Vorgesehene Ansible-Abbildung
|
||||
|
||||
@@ -327,37 +345,38 @@ getrennt:
|
||||
|
||||
```text
|
||||
ansible/
|
||||
├── inventories/
|
||||
│ ├── production/
|
||||
│ │ ├── hosts.yml
|
||||
│ │ ├── group_vars/
|
||||
│ │ └── host_vars/
|
||||
│ └── testing/
|
||||
│ ├── hosts.yml
|
||||
│ ├── group_vars/
|
||||
│ └── host_vars/
|
||||
├── playbooks/
|
||||
│ ├── host.yml
|
||||
│ ├── environment.yml
|
||||
│ └── verify.yml
|
||||
│ ├── ai.yml
|
||||
│ ├── video-encoding.yml
|
||||
│ └── site.yml
|
||||
└── roles/
|
||||
├── host_baseline/
|
||||
└── environment_stack/
|
||||
├── podman_runtime/
|
||||
├── workload_accounts/
|
||||
├── ai_stack/
|
||||
├── ai_environment_switch/
|
||||
└── video_encoding/
|
||||
```
|
||||
|
||||
Beide Inventare zeigen auf `ghostnet-ki`, enthalten aber ausschließlich die
|
||||
für ihre Umgebung zulässigen Variablen und Secrets. `host.yml` verwaltet
|
||||
gemeinsame Pakete, Treiber, Benutzer und Runtime-Komponenten einmalig.
|
||||
`environment.yml` muss genau eine explizit gewählte Umgebung verwalten und vor
|
||||
Änderungen prüfen, ob Namen, Pfade, Ports und Zielvariablen zur Auswahl passen.
|
||||
Hoständerungen dürfen nicht beiläufig durch einen Testing-Lauf erfolgen.
|
||||
`host.yml` verwaltet gemeinsame Pakete, Treiber, Benutzer und
|
||||
Runtime-Komponenten einmalig. `ai.yml` verwaltet ausschließlich den LLM-Stack
|
||||
und genau eine explizit gewählte KI-Umgebung. `video-encoding.yml` verwaltet nur
|
||||
Encoding-Pfade, Images, Quadlets, Timer und Prüfungen. `site.yml` kann den
|
||||
unterstützten Gesamtzustand in definierter Reihenfolge herstellen. Hoständerungen
|
||||
dürfen nicht beiläufig durch einen Workload-Lauf erfolgen.
|
||||
|
||||
Für den ersten umgesetzten Baseline-Stand gelten getrennte Konfigurationsbäume
|
||||
unter `/etc/ghostnet-ai/{production,testing}` und getrennte persistente
|
||||
Datenbäume unter `/var/lib/ghostnet-ai/{production,testing}`. Der Pfad
|
||||
`/var/lib/ghostnet-ai/shared` ist für später ausdrücklich freigegebene
|
||||
gemeinsame Daten reserviert. Konkrete Unterverzeichnisse, Eigentümer sowie
|
||||
Unit- und Container-Namen werden mit den jeweiligen Fachrollen festgelegt.
|
||||
Unit- und Container-Namen werden mit den jeweiligen Fachrollen festgelegt. Die
|
||||
Konten `gnai-production` und `gnai-testing` besitzen inzwischen ihre
|
||||
Datenwurzeln und getrennten rootless Podman-Stores; Konfiguration bleibt
|
||||
rootverwaltet und für die jeweilige Gruppe lesbar. Der Encoding-Workload
|
||||
verwendet entsprechend `/etc/ghostnet-encoding` und
|
||||
`/var/lib/ghostnet-encoding`.
|
||||
|
||||
---
|
||||
|
||||
@@ -534,8 +553,8 @@ nicht als Nachweis einer erfolgreichen Einrichtung.
|
||||
|
||||
### Phase D – KI-Laufzeit
|
||||
|
||||
- Podman- und Quadlet-Grundruntime eingerichtet und geprüft; konkretes
|
||||
rootful/rootless Ausführungsmodell noch festzulegen;
|
||||
- Podman- und Quadlet-Grundruntime sowie getrennte rootless Workload-Konten
|
||||
eingerichtet und geprüft;
|
||||
- AMD-GPU-/ROCm- oder alternative Laufzeit nach technischer Prüfung;
|
||||
- `llama.cpp` und lokaler Funktionstest;
|
||||
- Wiederanlauf nach geplantem Reboot prüfen.
|
||||
@@ -585,9 +604,9 @@ Vor der technischen Spezifikation sind mindestens folgende Punkte zu klären:
|
||||
Wiederanlauf von Production sicher, wenn Runner oder Testing ausfallen?
|
||||
15. Welche internen Hostnamen und Ports erhält Testing, und welche LAN-/VPN-
|
||||
Rollen dürfen darauf zugreifen?
|
||||
16. Können Production und Testing mit getrennten unprivilegierten Accounts
|
||||
verwaltet werden, oder erfordert die gewählte Podman-/systemd-Architektur
|
||||
einen stärker privilegierten gemeinsamen Deploymentpfad?
|
||||
16. Funktioniert der benötigte AMD-GPU-Zugriff zuverlässig aus den getrennten
|
||||
rootless Konten, und welche Gruppen-, Device- und Containeroptionen sind
|
||||
dafür minimal erforderlich?
|
||||
17. Wie wird ein Testing-Deployment eines Pull-Request-Commits in der
|
||||
eingesetzten Gitea-Version autorisiert, ohne Production-Secrets oder
|
||||
Production-Runner für veränderbaren PR-Code verfügbar zu machen?
|
||||
@@ -715,13 +734,33 @@ Eine getrennte Prüfung bestätigte außerdem leere Image- und Containerlisten
|
||||
sowie `podman.socket` und `podman-auto-update.timer` jeweils als `disabled` und
|
||||
`inactive`.
|
||||
|
||||
Die Rolle `workload_accounts` wurde anschließend in `host.yml` aufgenommen. Sie
|
||||
verwaltet feste IDs, gesperrte Passwörter, `/usr/sbin/nologin`, getrennte
|
||||
SubUID-/SubGID-Bereiche, Daten- und Konfigurationsrechte, rootverwaltete
|
||||
Quadlet-Verzeichnisse und Linger für `gnai-production` (UID/GID 980),
|
||||
`gnai-testing` (981) und `gn-encoding` (982). Die Datenwurzeln gehören dem
|
||||
jeweiligen Konto; Konfiguration gehört root und ist für die jeweilige Gruppe
|
||||
lesbar.
|
||||
|
||||
Beim ersten realen Lauf scheiterte nur die Abschlussprüfung, weil die
|
||||
sudoers-Regel von `ansible-deploy` den direkten Ansible-Wechsel zu den
|
||||
Servicekonten nicht erlaubt. Die Prüfung wurde auf einen rootseitigen Aufruf
|
||||
über `runuser` umgestellt, ohne die sudoers-Regel zu erweitern. Ein weiterer
|
||||
Lauf deckte eine konkurrierende Eigentümerverwaltung durch `host_baseline` auf;
|
||||
die umgebungsspezifischen Pfade wurden daraufhin vollständig an
|
||||
`workload_accounts` übertragen. Der korrigierte Gesamtlauf endete mit
|
||||
`ok=36 changed=0 unreachable=0 failed=0` und bestätigte drei aktive
|
||||
systemd-User-Manager sowie drei getrennte rootless Podman Graph Roots. Es
|
||||
wurden keine Images oder Workload-Container angelegt.
|
||||
|
||||
---
|
||||
|
||||
## 15. Abschlussgrenze dieses Entwurfs
|
||||
|
||||
Mit Version 0.8 sind der aktuelle Planungsstand, der ausdrücklich begrenzte
|
||||
Mit Version 0.9 sind der aktuelle Planungsstand, der ausdrücklich begrenzte
|
||||
Ansible-Preflight, der verifizierte Deployment-Account und die angewendete
|
||||
minimale Host-Baseline sowie die Podman-/Quadlet-Grundruntime persistiert.
|
||||
minimale Host-Baseline, die Podman-/Quadlet-Grundruntime und die getrennten
|
||||
Workload-Konten persistiert.
|
||||
Insbesondere wurden noch nicht:
|
||||
|
||||
- ein Gitea Runner angelegt,
|
||||
@@ -733,5 +772,6 @@ Insbesondere wurden noch nicht:
|
||||
- Backups oder Rollbacks praktisch getestet oder
|
||||
- die geplante Deploymentkette technisch abgenommen.
|
||||
|
||||
Der nächste Dokumentationsschritt ist die Ist-Aufnahme aus Phase A. Auf deren
|
||||
Ergebnissen baut die verbindliche technische Spezifikation auf.
|
||||
Die nächsten technischen Schritte sind der begrenzte GPU-Zugriffstest für die
|
||||
beiden KI-Konten und die Festlegung von Zeitfenster sowie Ressourcenlimits im
|
||||
getrennten Encoding-Plan. Darauf bauen die jeweiligen Fachrollen und SOPs auf.
|
||||
@@ -0,0 +1,15 @@
|
||||
# KI-Dokumentation
|
||||
|
||||
Dieser Bereich enthält die fachliche Zielarchitektur und Deployment-Planung für
|
||||
den KI-Stack. Gemeinsame Host-, Netzwerk- und Sicherheitsgrundlagen liegen in
|
||||
der [Plattformdokumentation](../platform/README.md). Der CPU-basierte
|
||||
Video-Encoding-Workload besitzt einen
|
||||
[eigenen Dokumentationsbereich](../video-encoding/GNENC-000-DOC_Index.md).
|
||||
|
||||
| Dokument | Inhalt |
|
||||
| --- | --- |
|
||||
| [GNAI-003](GNAI-003-INFRA_Architecture.md) | Zielarchitektur, Komponenten und Datenwege des KI-Stacks |
|
||||
| [GNAI-007](GNAI-007-PLAN_Ansible-Deployment.md) | nicht finaler Arbeitsentwurf für Ansible- und Gitea-Deployment |
|
||||
|
||||
Der übergreifende Projektstand steht im
|
||||
[zentralen Dokumentationsindex](../GNAI-000-DOC_Index.md).
|
||||
@@ -15,12 +15,13 @@
|
||||
| 2026-09-16 | 1.2 | spektr | Tatsächliche Konten, Gruppen, Netz- und SSH-Konfiguration sowie Grenzen des Login-Tests dokumentiert. |
|
||||
| 2026-09-18 | 1.3 | spektr | Workstation-spezifische Schlüsselpfade und Host-Fingerprint in den lokalen Arbeitskontext verlagert. |
|
||||
| 2026-09-19 | 1.4 | spektr | Persönlichen Login `ghost` und Agentenlogin `ghost-agent` als erfolgreich getestet dokumentiert. |
|
||||
| 2026-09-20 | 1.5 | spektr / Codex | Deployment- und getrennte rootless Workload-Konten mit festen IDs und Zuständigkeiten ergänzt. |
|
||||
|
||||
---
|
||||
|
||||
## 1. Zweck und Geltungsbereich
|
||||
|
||||
Dieses Dokument beschreibt Benutzer, statische IP und SSH des KI-Servers. Der lesend geprüfte Kontenbestand am 18.09.2026 lautet `ghost`, `debugofen`, `ghost-agent`; `admin` existiert auf diesem Host nicht. Die folgenden Befehle sind für Neuinstallation oder gezielte Änderung gedacht und ersetzen keine Prüfung des vorhandenen Systems. Der WireGuard-LXC besitzt ein separates Konto `admin`.
|
||||
Dieses Dokument beschreibt Benutzer, statische IP und SSH des KI-Servers. Der ursprüngliche lesende Kontenabgleich vom 18.09.2026 umfasste `ghost`, `debugofen` und `ghost-agent`; `admin` existiert auf diesem Host nicht. Am 19. und 20.09.2026 kamen der Ansible-Deployment-Account sowie drei gesperrte Workload-Konten hinzu. Die folgenden Befehle sind für Neuinstallation oder gezielte Änderung gedacht und ersetzen keine Prüfung des vorhandenen Systems. Der WireGuard-LXC besitzt ein separates Konto `admin`.
|
||||
|
||||
---
|
||||
|
||||
@@ -59,6 +60,22 @@ sudo usermod -aG sudo ghost
|
||||
|
||||
Weitere Konten nur nach Rollenentscheidung anlegen. Die sudo-Gruppenmitgliedschaft ist pro Konto ausdrücklich festzulegen; auf dem bestehenden Host keine bereits vorhandenen Konten erneut anlegen.
|
||||
|
||||
Die folgenden technischen Konten werden ausschließlich durch das
|
||||
Ansible-Projekt verwaltet:
|
||||
|
||||
| Konto | UID/GID | Zweck | interaktiver Login / sudo |
|
||||
| --- | --- | --- | --- |
|
||||
| `ansible-deploy` | 1003 | privilegierte Ansible-Ausführung | SSH-Key, gesperrtes Passwort, `NOPASSWD` gemäß eigener sudoers-Regel |
|
||||
| `gnai-production` | 980 | rootless AI Production | gesperrtes Passwort, `/usr/sbin/nologin`, kein sudo |
|
||||
| `gnai-testing` | 981 | rootless AI Testing | gesperrtes Passwort, `/usr/sbin/nologin`, kein sudo |
|
||||
| `gn-encoding` | 982 | rootless CPU-Encoding | gesperrtes Passwort, `/usr/sbin/nologin`, kein sudo |
|
||||
|
||||
Die drei Workload-Konten besitzen nicht überlappende SubUID-/SubGID-Bereiche,
|
||||
eigene Daten- und Podman-Stores sowie persistente systemd-User-Manager. Ihre
|
||||
rootverwalteten Quadlet-Verzeichnisse liegen unter
|
||||
`/etc/containers/systemd/users/<UID>`. Direkte SSH-Schlüssel werden dort nicht
|
||||
hinterlegt.
|
||||
|
||||
---
|
||||
|
||||
### 3.2 Statische Netzwerkkonfiguration (Server-Seite)
|
||||
@@ -170,6 +187,7 @@ sudo systemctl restart ssh
|
||||
## 4. Abnahmekriterien (Checkliste für den Junior-Admin)
|
||||
|
||||
* [ ] **Benutzerprüfung:** `ghost` und `debugofen` können ihre vorgesehenen sudo-Rechte nutzen; `ghost-agent` bleibt ohne sudo-Zuweisung.
|
||||
* [x] **Workload-Konten:** `gnai-production`, `gnai-testing` und `gn-encoding` besitzen getrennte rootless Podman-Stores und aktive persistente User-Manager; geprüft am 20.09.2026.
|
||||
* [ ] **Netzwerk:** Server ist unter der statischen IP `10.0.0.90` erreichbar. Ausgehender Datenverkehr funktioniert (`ping google.com`).
|
||||
* [x] **SSH-Aliase:** `ghostnet-ai-ghost` meldet `ghost`, `ghostnet-ai-agent` meldet `ghost-agent`. Beide Zugänge wurden am 19.09.2026 bestätigt. Die Passphrase des persönlichen Schlüssels ist keine Server-Passwortanmeldung.
|
||||
* [ ] **Root-Sperre:** Direct-Login als Root per SSH wird abgelehnt (`ssh root@10.0.0.90` -> *Permission denied*).
|
||||
@@ -3,7 +3,7 @@
|
||||
**Dokumenten-ID:** GNAI-004-SEC
|
||||
**Titel:** Homelab / LLM-Infrastruktur – Sicherheits-, Authentifizierungs- und Zugriffskonzept
|
||||
**Status:** Verbindliches Zielmodell; technische Durchsetzung teilweise offen
|
||||
**Vorgänger / Referenzen:** [Architektur](GNAI-003-INFRA_Architecture.md), [Gateway](GNAI-006-SEC_VPN.md), [GUI-SOP](GNAI-006-SEC_VPN_Client-Management.md), [Reverse Proxy](GNAI-005-SEC_Reverse-Proxy.md)
|
||||
**Vorgänger / Referenzen:** [Architektur](../ai/GNAI-003-INFRA_Architecture.md), [Gateway](GNAI-006-SEC_VPN.md), [GUI-SOP](GNAI-006-SEC_VPN_Client-Management.md), [Reverse Proxy](GNAI-005-SEC_Reverse-Proxy.md)
|
||||
|
||||
---
|
||||
|
||||
@@ -297,4 +297,4 @@ Das Sicherheitsmodell basiert damit nicht auf einem einzelnen „Security-Progra
|
||||
|
||||
## 11. Umsetzungsnachweise
|
||||
|
||||
Dieses Dokument definiert die Zugriffsziele. Der [Dokumentationsindex](GNAI-000-DOC_Index.md) bündelt den aktuellen Projektstand. Konkrete Gateway-Regeln und Rollentests stehen in [GNAI-006](GNAI-006-SEC_VPN.md), der Keycloak-Adminpfad und Fail2Ban in [GNAI-005](GNAI-005-SEC_Reverse-Proxy.md). Offene Zielrechte gelten bis zu ihrer technischen Abnahme nicht als durchgesetzt.
|
||||
Dieses Dokument definiert die Zugriffsziele. Der [Dokumentationsindex](../GNAI-000-DOC_Index.md) bündelt den aktuellen Projektstand. Konkrete Gateway-Regeln und Rollentests stehen in [GNAI-006](GNAI-006-SEC_VPN.md), der Keycloak-Adminpfad und Fail2Ban in [GNAI-005](GNAI-005-SEC_Reverse-Proxy.md). Offene Zielrechte gelten bis zu ihrer technischen Abnahme nicht als durchgesetzt.
|
||||
@@ -3,7 +3,7 @@
|
||||
**Dokumenten-ID:** GNAI-005-SEC
|
||||
**Titel:** Reverse Proxy und Fail2Ban – Konfiguration, Betrieb und Sicherheitsabnahme
|
||||
**Status:** NPM aktiv; Fail2Ban laut Betreiber fest gepinnt und wieder in Betrieb; Keycloak-Admin-Exposure bestätigt, Korrektur offen
|
||||
**Vorgänger / Referenzen:** [Architektur](GNAI-003-INFRA_Architecture.md), [Zugriffskonzept](GNAI-004-SEC_Access-Control.md), [WireGuard](GNAI-006-SEC_VPN.md)
|
||||
**Vorgänger / Referenzen:** [Architektur](../ai/GNAI-003-INFRA_Architecture.md), [Zugriffskonzept](GNAI-004-SEC_Access-Control.md), [WireGuard](GNAI-006-SEC_VPN.md)
|
||||
|
||||
---
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
**Dokumenten-ID:** GNAI-006-SEC
|
||||
**Status:** Dokumentation bereinigt; technische Umsetzung und Abnahme teilweise offen
|
||||
**Referenzen:** [Zielarchitektur](GNAI-003-INFRA_Architecture.md), [Zugriffskonzept](GNAI-004-SEC_Access-Control.md), [GUI-SOP](GNAI-006-SEC_VPN_Client-Management.md), [Implementation-Log](GNAI-006-SEC_VPN_Implementation-Log.md)
|
||||
**Referenzen:** [Zielarchitektur](../ai/GNAI-003-INFRA_Architecture.md), [Zugriffskonzept](GNAI-004-SEC_Access-Control.md), [GUI-SOP](GNAI-006-SEC_VPN_Client-Management.md), [Implementation-Log](GNAI-006-SEC_VPN_Implementation-Log.md)
|
||||
|
||||
|
||||
## Änderungsverlauf
|
||||
+2
-2
@@ -50,7 +50,7 @@ Der aktuelle Quadlet-Pin `15.4.0` ist durch den Betreiber bestätigt. v15 verwen
|
||||
| Laptop-FullAdmin | `10.8.0.2` | 1 | neue Rolle Familie oder Server Admin noch ausdrücklich zuordnen |
|
||||
| Android-LLMAdmin | `10.8.0.3` | 2 | Altbestand; Android außerhalb des neuen SOP-Umfangs, keine Praxisabnahme |
|
||||
|
||||
Profile wurden laut Log manuell aus der SQLite-Datenbank generiert und gegen die Serverkonfiguration geprüft. Das ist ein historischer Vorgang, kein künftiges SOP-Verfahren. Neue Profile werden über die GUI exportiert. Der Pfad `docs/GNAI-006-profiles/` wurde als gitignored genannt; Profile bleiben unabhängig von Git-Ausschlüssen Geheimnisse.
|
||||
Profile wurden laut Log manuell aus der SQLite-Datenbank generiert und gegen die Serverkonfiguration geprüft. Das ist ein historischer Vorgang, kein künftiges SOP-Verfahren. Neue Profile werden über die GUI exportiert. Der Pfad `docs/platform/GNAI-006-profiles/` wurde als gitignored genannt; Profile bleiben unabhängig von Git-Ausschlüssen Geheimnisse.
|
||||
|
||||
Der Laptop wurde von außerhalb des Heimnetzes über EasyCable mit damaliger Außen-IPv4 `80.187.120.60` getestet. Diese und die damalige Heimnetz-WAN-IP sind zeitgebundene Messwerte, keine DNS-Sollwerte.
|
||||
|
||||
@@ -135,4 +135,4 @@ Diese Beobachtungen bestätigen den breiten Netzpfad und die NAT-Abhängigkeit.
|
||||
| O8 | Reboot, Firewall-Reload und Restore | offen |
|
||||
| O9 | wg-easy-GUI-HTTPS und lokales Gruppenmodell | geplant; Werte noch festzulegen |
|
||||
|
||||
Andere Sicherheitsbefunde werden im [Dokumentationsindex](GNAI-000-DOC_Index.md) geführt. Dieses Log hält nur WireGuard-Umsetzung und zugehörige Tests fest.
|
||||
Andere Sicherheitsbefunde werden im [Dokumentationsindex](../GNAI-000-DOC_Index.md) geführt. Dieses Log hält nur WireGuard-Umsetzung und zugehörige Tests fest.
|
||||
@@ -0,0 +1,21 @@
|
||||
# Plattform- und Hostdokumentation
|
||||
|
||||
Dieser Bereich enthält die gemeinsame Infrastruktur, auf der KI- und
|
||||
Encoding-Workloads aufbauen. Dazu gehören Hostinstallation, Benutzer und SSH,
|
||||
das übergreifende Zugriffsmodell, Reverse Proxy und VPN. Workload-spezifische
|
||||
Architektur und Nutzerverfahren liegen in den jeweiligen Nachbarverzeichnissen.
|
||||
|
||||
| Dokument | Inhalt |
|
||||
| --- | --- |
|
||||
| [GNAI-001](GNAI-001-INFRA_BaseSystem.md) | Hardware und Debian-Basisinstallation des KI-Servers |
|
||||
| [GNAI-002](GNAI-002-INFRA_Users.md) | Hostbenutzer, Netzwerk, Resolver und SSH |
|
||||
| [GNAI-004](GNAI-004-SEC_Access-Control.md) | Rollen- und Zugriffsziel für die Infrastruktur |
|
||||
| [GNAI-005](GNAI-005-SEC_Reverse-Proxy.md) | Reverse Proxy, Keycloak-Adminpfad und Fail2Ban |
|
||||
| [GNAI-006](GNAI-006-SEC_VPN.md) | WireGuard-Gateway und Rollen-Firewall |
|
||||
| [VPN-Client-Verwaltung](GNAI-006-SEC_VPN_Client-Management.md) | Profile ausgeben, ändern und widerrufen |
|
||||
| [Windows 11](GNAI-006-SEC_VPN_Clients_Windows11.md) | WireGuard-Client unter Windows 11 |
|
||||
| [Linux](GNAI-006-SEC_VPN_Clients_Linux.md) | WireGuard-Client unter unterstützten Linux-Varianten |
|
||||
| [VPN-Implementation-Log](GNAI-006-SEC_VPN_Implementation-Log.md) | historische Umsetzung, Tests und Evidenzkorrekturen |
|
||||
|
||||
Der übergreifende Projektstand steht im
|
||||
[zentralen Dokumentationsindex](../GNAI-000-DOC_Index.md).
|
||||
@@ -0,0 +1,32 @@
|
||||
# Video-Encoding – Dokumentationsindex und Projektstand
|
||||
|
||||
**Dokumenten-ID:** GNENC-000-DOC
|
||||
**Stand:** 2026-09-20
|
||||
**Status:** Nicht finaler Arbeitsstand; Encoding-Workload noch nicht installiert
|
||||
|
||||
## Dokumente
|
||||
|
||||
| Dokument | Zweck / Zielgruppe |
|
||||
| --- | --- |
|
||||
| [GNENC-001-PLAN_Architecture.md](GNENC-001-PLAN_Architecture.md) | vorläufige Architektur, Repository-Grenzen, Ressourcenmodell und offene Entscheidungen; Infrastrukturadministratoren |
|
||||
|
||||
## Bestätigter Stand
|
||||
|
||||
- Das gemeinsame Infrastructure-Repository bleibt die einzige Quelle für den
|
||||
Ansible-Sollzustand des physischen Servers.
|
||||
- Encoding-Dokumentation verwendet den getrennten Bereich `docs/video-encoding/`
|
||||
und die Dokumentenkennung `GNENC`.
|
||||
- Encoding ist nach Betreiberfestlegung CPU-basiert und darf parallel zur
|
||||
jeweils aktiven KI-Umgebung laufen.
|
||||
- Encoding soll ausschließlich außerhalb der Stoßzeiten, zunächst nachts,
|
||||
automatisch ausgeführt werden.
|
||||
- Das gesperrte Servicekonto `gn-encoding` mit UID/GID 982 und eigenem
|
||||
rootless Podman-Store ist eingerichtet und verifiziert.
|
||||
- Es sind noch kein Encoding-Image, kein Container, keine Quadlet-Unit und kein
|
||||
Timer eingerichtet.
|
||||
|
||||
## Nächste Festlegungen
|
||||
|
||||
Vor einer Encoding-Implementierung müssen insbesondere Encoder und
|
||||
Container-Image, Ein- und Ausgabeverfahren, genaue Zeitfenster, CPU-/I/O-Grenzen,
|
||||
Abbruchverhalten am Ende des Zeitfensters und Aufbewahrung festgelegt werden.
|
||||
@@ -0,0 +1,142 @@
|
||||
# Arbeitsentwurf
|
||||
|
||||
**Dokumenten-ID:** GNENC-001-PLAN
|
||||
**Titel:** CPU-basiertes Video-Encoding auf dem KI-Server
|
||||
**Stand:** 2026-09-20
|
||||
**Status:** Nicht finaler Arbeitsentwurf zur Persistierung der Planungsentscheidung
|
||||
|
||||
## 1. Zweck und Abgrenzung
|
||||
|
||||
Der physische Server `ghostnet-ki` soll neben den KI-Workloads einen getrennten
|
||||
Workload zum Encoding von Videodateien ausführen. Der Encoding-Workload gehört
|
||||
nicht zum LLM-Stack. Seine fachliche Architektur, Bedienung und späteren SOPs
|
||||
werden deshalb in diesem eigenen Dokumentationsbereich geführt.
|
||||
|
||||
Ansible, Podman, Betriebssystem und hostweite Ressourcenregeln bleiben
|
||||
gemeinsame Plattformbestandteile. Sie werden weiterhin ausschließlich im
|
||||
Infrastructure-Repository verwaltet, damit nicht mehrere Repositories
|
||||
unabhängig konkurrierende Sollzustände auf denselben Host anwenden.
|
||||
|
||||
## 2. Bestätigte Entscheidungen
|
||||
|
||||
| Thema | Entscheidung | Nachweisgrenze |
|
||||
| --- | --- | --- |
|
||||
| Repository | Host- und Deployment-Ansible bleibt im bestehenden Infrastructure-Repository | angenommen |
|
||||
| Dokumentation | Encoding erhält `docs/video-encoding/` und die Kennung `GNENC` | umgesetzt |
|
||||
| Ausführungsidentität | eigenes gesperrtes Konto `gn-encoding`, UID/GID 982 | eingerichtet und mit rootless Podman geprüft |
|
||||
| Containertrennung | eigener rootless Podman-Store und eigener rootverwalteter Quadlet-Pfad | eingerichtet; noch keine Workload definiert |
|
||||
| Rechenressource | Encoding ist nach Betreiberfestlegung rein CPU-basiert und erhält keinen GPU-Zugriff | Planungsentscheidung; reale Last noch nicht gemessen |
|
||||
| Parallelität | darf parallel zu AI Production oder AI Testing laufen | Planungsentscheidung |
|
||||
| Zeitsteuerung | automatische Ausführung ausschließlich außerhalb der Stoßzeiten, zunächst nachts | Richtung festgelegt; konkrete Uhrzeiten fehlen |
|
||||
| Anwendungen | konkrete Encoder, Images, Profile und Queue sind noch nicht gewählt | offen |
|
||||
|
||||
## 3. Zielbild
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
HOST[ghostnet-ki]
|
||||
PROD[gnai-production\nrootless Podman]
|
||||
TEST[gnai-testing\nrootless Podman]
|
||||
ENC[gn-encoding\nrootless Podman]
|
||||
GPU[beide GPUs]
|
||||
CPU[CPU / I-O Budget]
|
||||
TIMER[nächtliche systemd-Zeitsteuerung]
|
||||
|
||||
HOST --> PROD
|
||||
HOST --> TEST
|
||||
HOST --> ENC
|
||||
PROD --> GPU
|
||||
TEST --> GPU
|
||||
ENC --> CPU
|
||||
TIMER --> ENC
|
||||
```
|
||||
|
||||
AI Production und AI Testing bleiben untereinander exklusiv. Der
|
||||
Encoding-Workload ist von dieser KI-Umschaltung unabhängig und darf parallel
|
||||
zur jeweils aktiven KI-Umgebung laufen. Hostwartung kann weiterhin einen Stopp
|
||||
aller Workloads erfordern.
|
||||
|
||||
## 4. Ressourcen- und Zeitsteuerung
|
||||
|
||||
Die nächtliche Einplanung allein schützt Production nicht vollständig: Ein
|
||||
Encoding-Lauf kann länger dauern als sein Startfenster, und Inferenz benötigt
|
||||
trotz GPU-Schwerpunkt CPU für Tokenisierung, Netzwerk und Begleitdienste. Die
|
||||
spätere Encoding-Unit soll deshalb mindestens verwalten:
|
||||
|
||||
- ein eindeutig definiertes Zeitfenster mit Zeitzone;
|
||||
- Verhalten bei verpasstem Start, Neustart und überlangem Lauf;
|
||||
- maximale CPU-Nutzung oder CPU-Gewichtung;
|
||||
- niedrigere Scheduling-Priorität gegenüber interaktiven Diensten;
|
||||
- I/O-Gewichtung und freien Speicher;
|
||||
- geordneten Abbruch beziehungsweise Abschluss am Ende des erlaubten Fensters;
|
||||
- Begrenzung auf genau einen gleichzeitigen Encoding-Job.
|
||||
|
||||
Konkrete Grenzwerte werden erst nach einem repräsentativen Encoding-Test unter
|
||||
gleichzeitiger Inferenzlast festgelegt. `gn-encoding` erhält keine Mitgliedschaft
|
||||
in GPU-Gruppen und keine `/dev/kfd`- oder `/dev/dri`-Weitergabe.
|
||||
|
||||
## 5. Repository-Grenzen
|
||||
|
||||
Vorgesehene Ansible-Struktur:
|
||||
|
||||
```text
|
||||
ansible/
|
||||
├── playbooks/
|
||||
│ ├── host.yml
|
||||
│ ├── ai.yml
|
||||
│ ├── video-encoding.yml
|
||||
│ └── site.yml
|
||||
└── roles/
|
||||
├── host_baseline/
|
||||
├── podman_runtime/
|
||||
├── workload_accounts/
|
||||
├── ai_stack/
|
||||
├── ai_environment_switch/
|
||||
└── video_encoding/
|
||||
```
|
||||
|
||||
`host.yml` verwaltet ausschließlich gemeinsame Plattformzustände.
|
||||
`ai.yml` darf nur KI-Zustände verändern. `video-encoding.yml` verwaltet nur das
|
||||
Konto `gn-encoding`, seine Pfade, Images, Quadlets, Timer und Health Checks. Ein
|
||||
späteres `site.yml` kann die unterstützte Gesamtkonfiguration in definierter
|
||||
Reihenfolge anwenden.
|
||||
|
||||
Ein separates Quellcode-Repository wird erst benötigt, wenn eigene
|
||||
Encoding-Software, eine Oberfläche oder ein Queue-Dienst entwickelt wird. Ein
|
||||
solches Repository erzeugt ein versioniertes Artefakt oder Image; ausschließlich
|
||||
das Infrastructure-Repository legt fest, welche Version auf dem Server läuft.
|
||||
|
||||
## 6. Aktueller Implementierungsstand
|
||||
|
||||
Die gemeinsame Rolle `workload_accounts` hat am 20.09.2026 eingerichtet:
|
||||
|
||||
```text
|
||||
Konto: gn-encoding (UID/GID 982)
|
||||
Konfiguration: /etc/ghostnet-encoding
|
||||
Daten: /var/lib/ghostnet-encoding
|
||||
Eingang: /var/lib/ghostnet-encoding/input
|
||||
Ausgang: /var/lib/ghostnet-encoding/output
|
||||
Arbeitsdaten: /var/lib/ghostnet-encoding/work
|
||||
Quadlets: /etc/containers/systemd/users/982
|
||||
Podman-Store: /var/lib/ghostnet-encoding/.local/share/containers/storage
|
||||
```
|
||||
|
||||
Passwort und interaktive Shell sind gesperrt. Der systemd-User-Manager läuft
|
||||
dank Linger unabhängig von einer Anmeldung. Der Podman-Store wurde als
|
||||
rootless und getrennt von beiden KI-Stores geprüft. Es wurden noch keine Images
|
||||
oder Container angelegt.
|
||||
|
||||
## 7. Offene Entscheidungen
|
||||
|
||||
1. Welcher Encoder und welches fest versionierte Container-Image werden genutzt?
|
||||
2. Welche Codecs, Qualitätsprofile und Hardwarekompatibilitäten sind erforderlich?
|
||||
3. Woher kommen Eingabedateien, und wie werden fertige Dateien abgeholt?
|
||||
4. Welches konkrete nächtliche Zeitfenster und welche Zeitzone gelten?
|
||||
5. Darf ein laufender Job das Zeitfenster überschreiten oder wird er gestoppt?
|
||||
6. Welche CPU-, Speicher- und I/O-Grenzen schützen die KI-Dienste?
|
||||
7. Wie werden Warteschlange, Wiederholung, Teilresultate und Fehler behandelt?
|
||||
8. Welche Aufbewahrungs-, Backup- und Löschregeln gelten für Video- und
|
||||
Arbeitsdateien?
|
||||
9. Welche Statusanzeige oder Benachrichtigung benötigen Nutzer?
|
||||
|
||||
Diese Werte werden nicht vorab in Playbooks angenommen.
|
||||
Reference in New Issue
Block a user