CT-101 Samba: Ansible-Migration (GNAI-017/018/019) mit PVE-Skripten, Runbooks und Fresh-State-Rebuild aufgenommen

- Ansible-Projekt proxmox/lxc/ct-101-samba/ansible: 7 Playbooks, 6 Rollen,
  3 Inventories (agent/bootstrap/production), 11 fail-closed Platzhalter
- Design GNAI-019: Samba nativ (templated smb.conf mit testparm-Gate),
  NFS-Ganesha als rootful Quadlet mit Host-Networking und leerem
  lxc.seccomp.profile, NFSv4-only, gn-media GID 970, passdb-Erhalt
- PVE-Skripte: upgrade-ct101-to-debian13.sh (Adoption),
  provision-ct101-samba.sh (Fresh-State-Rebuild), sha256-gepinnt
- Runbooks: Adoption (15 Schritte) und Fresh-State-Rebuild (9 Schritte)
- Dokumentation: GNAI-019 (DEC), GNAI-017 aktualisiert, Index-Einträge;
  Befund Dist-Upgrade 21.10.2026: smb.conf-Verlust aus vzdump-Backup
  wiederhergestellt und verifiziert
- Secrets (SMB-Passwörter, passdb, private Schlüssel) nicht im Repository

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
2026-10-26 19:20:36 +01:00
parent 26fb86781f
commit 220d921e09
67 changed files with 6210 additions and 4 deletions
+12 -4
View File
@@ -1,6 +1,6 @@
# Ghostnet.AI – Dokumentationsindex und Projektstand
**Stand:** 2026-10-14
**Stand:** 2026-10-21
**Status:** Plattformgrundlage vorhanden; Sicherheitsabschluss und LLM-Serving offen
@@ -38,6 +38,9 @@ jeweiligen Fachdokumenten. Die priorisierte weitere Umsetzung beschreibt der
| [VPN-Client-Verwaltung](platform/proxmox-server/lxc/ct-105-wireguard/GNAI-007-SEC_VPN_Client-Management.md) | Ausgabe, Änderung und Widerruf von Geräteprofilen |
| [Windows 11](platform/proxmox-server/lxc/ct-105-wireguard/GNAI-007-SEC_VPN_Clients_Windows11.md) / [Linux](platform/proxmox-server/lxc/ct-105-wireguard/GNAI-007-SEC_VPN_Clients_Linux.md) | Client-SOPs |
| [VPN-Implementation-Log](platform/proxmox-server/lxc/ct-105-wireguard/GNAI-007-SEC_VPN_Implementation-Log.md) | historische Umsetzung und datierte Evidenz |
| [CT 101 / GNAI-017](platform/proxmox-server/lxc/ct-101-samba/GNAI-017-PLAN_Samba-NFS-Export.md) | Samba-Dateiserver `10.0.0.9`: Aufnahme ins Repository, NFS-Export und Encoding-Shares |
| [CT 101 / GNAI-018](platform/proxmox-server/lxc/ct-101-samba/GNAI-018-REQ_Encoding-Pipeline-Integration.md) | Requirements der Encoding-Pipeline an CT 101 — Übergabe an den Ansible-Rebuild |
| [CT 101 / GNAI-019](platform/proxmox-server/lxc/ct-101-samba/GNAI-019-DEC_Ansible-Migration.md) | Entwurfsentscheidungen der CT-101-Ansible-Migration: natives Samba, NFS-Ganesha als Quadlet, Fresh-State-Rebuild |
### KI und Deployment
@@ -51,13 +54,17 @@ jeweiligen Fachdokumenten. Die priorisierte weitere Umsetzung beschreibt der
| [LLM-Server-Host-Ansible](../llm-server/host/ansible/README.md) | ausführbare Host-/ROCm-Playbooks und Rollen für `10.0.0.90` |
| [Encoding-Ansible](../llm-server/encoding/ansible/README.md) | ausführbares Ansible-Projekt für den CPU-Encoding-Workload auf `10.0.0.90` |
| [Keycloak-Ansible](../proxmox/lxc/ct-102-keycloak/ansible/README.md) | ausführbare Provisionierungs-, Restore- und Prüfautomation für CT 102 |
| [Samba-Ansible](../proxmox/lxc/ct-101-samba/ansible/README.md) | ausführbare Provisionierungs-, Backup- und Prüfautomation für CT 101 |
### Video-Encoding
### Video-Encoding und Monitoring
| Dokument | Verbindlicher Inhalt |
| --- | --- |
| [GNENC-000](platform/llm-server/encoding/GNENC-000-DOC_Index.md) | Bereichsstatus und offene Festlegungen |
| [GNENC-001](platform/llm-server/encoding/GNENC-001-PLAN_Architecture.md) | vorläufige Architektur des CPU-Encoding-Workloads |
| [GNENC-001](platform/llm-server/encoding/GNENC-001-PLAN_Architecture.md) | finale Architektur des CPU-Encoding-Workloads |
| [GNENC-002](platform/llm-server/encoding/GNENC-002-PLAN_Pipeline.md) | operative Encoding-Pipeline: Komponenten, Verzeichnislayout, Validierung, Statusmodell |
| [GNMON-000](platform/llm-server/monitoring/GNMON-000-DOC_Index.md) | Monitoring-Bereichsstatus (Metriken, Dashboard) |
| [GNMON-001](platform/llm-server/monitoring/GNMON-001-PLAN_Architecture.md) | Host-Monitoring: Metrics-Collector, Dashboard, Anbindung Encoding |
Die Dokumente wurden am 21.09.2026 neu geordnet: Die Roadmap belegt
`GNAI-001`; die zuvor bestehenden Dokumente `GNAI-001` bis `GNAI-009` wurden
@@ -84,7 +91,8 @@ die Dokumentation folgt derselben Dreiteilung.
| DNS / Pi-hole | CT 100 unter `10.0.0.14` mit digest-gepinntem Pi-hole 2026.09.0 als Podman-Quadlet; SSH/nftables, UDP/TCP-DNS, Split-DNS, Blocking/Allowlist, FRITZ!Box-Cutover, LXC-Reboot und Stop-Mode-Backup am 01.10.2026 abgenommen | vollständige App-/OIDC-Regression, praktischer FRITZ!Box-Rollback, mobile DuckDuckGo-/IPv6-Strategie, WireGuard-Profile und hostunabhängiger Restore-Test |
| Reverse Proxy | CT-103-Zugänge, SSH-/Firewall-Baseline, Reboot und lokales Backup abgenommen; NPM 2.15.1 routet öffentlichen OIDC- und internen Admin-vHost getrennt; öffentliche Keycloak-Administration liefert 403 | Fail2Ban-Jails/Bans und Wiederanlauf; hostunabhängige Backupkopie/Restore-Test |
| Keycloak | CT 102 unter `10.0.0.4` reproduzierbar per Ansible aufgebaut; gepinntes Keycloak 26.2.4 und PostgreSQL 16.15, Restore von CT 104, Container-/DB-Härtung, NPM-Cutover, interner Adminzugang, öffentliche Admin-Sperre, realer Vaultwarden-OIDC-Login und LXC-Neustart abgenommen | 14-tägige Stabilisierungsphase, praktischer NPM-Rückfall auf CT 104, Betriebs-/Backup-/Restore-SOP und anschließende Rückfallbereinigung |
| Encoding | Konto, Pfade, eigener rootless Store und CPU-Isolation per Ansible verwaltet und verifiziert | Workload, Zeitsteuerung, Ressourcenlimits und Lasttest |
| Encoding | Konto, Pfade, eigener rootless Store und CPU-Isolation per Ansible verwaltet und verifiziert; Planungsabschluss 19.10.2026 (Pipeline GNENC-002, Monitoring GNMON-001, Speicher auf CT-101) | Implementierung (NFS-Mount, Images, Quadlets, Skripte, Worker, Dashboard, Collector); Lasttest und Limit-Feintuning |
| Samba (CT 101) | Share-Bestand in GNAI-017 dokumentiert; Ansible-Projekt nach GNAI-019 gebaut und lokal verifiziert; Runbooks vorhanden; In-Place-Upgrade auf Debian 13 am 21.10.2026; smb.conf-Verlust beim Upgrade aus vzdump-Backup wiederhergestellt, Media-Shares und Workstation-Mounts verifiziert | produktive Adoption (Platzhalter, Schlüssel, Convergence, Verifikation), NFS-Export und Encoding-Shares produktiv, UID/GID-Abgleich produktiv, Backup-/Restore-Test |
Ein Zielbild, eine Betreiberangabe oder ein erfolgreicher Teiltest gilt nicht als
vollständige Abnahme. Datierte Details stehen im zuständigen Fachdokument.
+4
View File
@@ -14,6 +14,10 @@ Hypervisors selbst.
| [CT-104-Rückfallartefakte](../../../proxmox/lxc/ct-104-keycloak/README.md) | erhaltene Blue/Green-Referenz unter `10.0.0.16` |
| [GNAI-006 / CT 103](lxc/ct-103-reverse-proxy/GNAI-006-SEC_Reverse-Proxy.md) | `10.0.0.10`: Reverse Proxy, Keycloak-Adminpfad und Fail2Ban |
| [GNAI-007 / CT 105](lxc/ct-105-wireguard/GNAI-007-SEC_VPN.md) | `10.0.0.15`: WireGuard-Gateway, Rollen-Firewall und Clientverfahren |
| [GNAI-017 / CT 101](lxc/ct-101-samba/GNAI-017-PLAN_Samba-NFS-Export.md) | `10.0.0.9`: Samba-Dateiserver, NFS-Export und Encoding-Shares |
| [GNAI-018 / CT 101](lxc/ct-101-samba/GNAI-018-REQ_Encoding-Pipeline-Integration.md) | Requirements der Encoding-Pipeline an CT 101 für den Ansible-Rebuild (Übergabe) |
| [GNAI-019 / CT 101](lxc/ct-101-samba/GNAI-019-DEC_Ansible-Migration.md) | Entwurfsentscheidungen der Ansible-Migration: natives Samba, NFS-Ganesha als Quadlet, Fresh-State-Rebuild |
| [CT-101-Automation](../../../proxmox/lxc/ct-101-samba/README.md) | produktives Samba-Ansible-Projekt und CT-spezifische PVE-Helfer |
Die versionierte Quelle für den optionalen, secretfreien
Community-Scripts-Post-install-Hook liegt unter
@@ -0,0 +1,186 @@
# CT 101 – Samba-Dateiserver
**Dokumenten-ID:** GNAI-017-PLAN
**Titel:** CT 101 Samba: Aufnahme ins Repository, NFS-Export und Shares für die Encoding-Pipeline
**Stand:** 2026-10-21
**Status:** Plan; bestehende Shares produktiv und bislang manuell verwaltet; Ansible-Projekt gebaut (GNAI-019), Adoption des produktiven LXC ausstehend
**Referenzen:** [GNENC-001](../../../llm-server/encoding/GNENC-001-PLAN_Architecture.md), [GNENC-002](../../../llm-server/encoding/GNENC-002-PLAN_Pipeline.md), [GNMON-001](../../../llm-server/monitoring/GNMON-001-PLAN_Architecture.md), [GNAI-011](../../GNAI-011-SEC_LXC-SSH-Architecture.md), [GNAI-018](GNAI-018-REQ_Encoding-Pipeline-Integration.md), [GNAI-019](GNAI-019-DEC_Ansible-Migration.md)
## 1. Zweck und Geltungsbereich
CT 101 (`10.0.0.9`) ist der Samba-Dateiserver des Proxmox-Kontexts und trägt
den Medienspeicher (Filme, Serien, Anime, Musik, Software, Downloads) auf
mehreren Platten (`/media/daten1`, `/media/daten2`, `/media/daten3`,
`/media/datenhdd2`, `/media/datenhdd3`). Bislang ist die LXC nicht im
Infrastructure-Repository verwaltet; am 19.10.2026 wurde beschlossen, sie
aufzunehmen (Betreiberentscheidung).
Dieses Dokument hält den aktuellen Share-Bestand, die geplanten Änderungen für
die Encoding-Pipeline (NFS-Export, zwei Shares, Gruppen-Abgleich) und die
offenen Punkte fest. Bestehende Shares bleiben unberührt.
## 2. System-Baseline
| Parameter | Wert |
| --- | --- |
| Container-ID | CT 101 |
| IPv4 | 10.0.0.9 |
| Samba-Rolle | standalone server, Workgroup `Ghost.net` (aus `smb.conf`) |
| SMB-Benutzer | `ghost`, `daidalaw`, `debugofen` |
| Betriebssystem | Debian 13 (trixie) seit In-Place-Upgrade durch den Betreiber am 21.10.2026 (manuell; nicht via `scripts/upgrade-ct101-to-debian13.sh`) |
| Hostname | nicht erfasst — `preflight.yml` meldet ihn vor der Adoption (Inventory-Platzhalter `samba_expected_hostname`) |
## 3. Bestand: Shares (aus `smb.conf`, Stand 19.10.2026)
| Share | Pfad | Zugriff | Besonderheiten |
| --- | --- | --- | --- |
| `[homes]` | Home-Verzeichnisse | read-only, `valid users = %S` | Debian-Standard |
| `[printers]` | `/var/tmp` | printable, read-only | **Abschnitt doppelt vorhanden** (siehe Abschnitt 6) |
| `[print$]` | `/var/lib/samba/printers` | read-only | Druckertreiber |
| `[Dokumente]` | `/media/daten1/Dokumente` | RO, nur `ghost` | — |
| `[Filme]` | `/media/daten1/Filme` | RO, `ghost`/`daidalaw`/`debugofen`, write `ghost` | — |
| `[Filme2]` | `/media/datenhdd3/Filme` | wie `[Filme]` | — |
| `[Serien]` | `/media/daten2/Serien` | RO, alle drei, write `ghost` | `force user/group = root` |
| `[Serien2]` | `/media/daten3/Serien` | wie `[Serien]` | — |
| `[Animation]` | `/media/daten1/Animation` | RO, alle drei, write `ghost` | — |
| `[Anime]` | `/media/daten3/Anime` | RO, alle drei, write `ghost` | — |
| `[Extern]` | `/media/datenhdd2/extern` | RW, nur `ghost` | — |
| `[Musik]` | `/media/daten1/Musik` | RO, alle drei, write `ghost` | — |
| `[Audiobooks]` | `/media/daten1/Audiobooks` | RO, alle drei, write `ghost` | — |
| `[Software]` | `/media/datenhdd3/Software` | RO, alle drei, write `ghost`/`daidalaw` | — |
| `[Downloads]` | `/media/datenhdd3/Downloads` | RW, alle drei | bleibt unberührt; `.dlc`-Drop läuft künftig über `[Encode-In]` |
Globale Einstellungen (Auszug): `map to guest = bad user`, `usershare allow
guests = yes`, `obey pam restrictions = yes`.
## 4. Geplante Änderungen für die Encoding-Pipeline
### 4.1 NFS-Export
Ursprünglich war `nfs-kernel-server` mit `/etc/exports` geplant. **Überholt
durch GNAI-019 Entscheidung 2 und 3:** Der Kernel-NFS-Server ist in einem
unprivileged LXC nicht betreibbar; der Export läuft stattdessen als
**NFS-Ganesha** in einem rootful Podman-Quadlet-Container
(`ghostnet-samba-nfs.service`, Host-Networking, NFSv4-only). Dafür wird in
`/etc/pve/lxc/101.conf` ein leerer `lxc.seccomp.profile:`-Eintrag gesetzt
(Ganesha braucht `open_by_handle_at`). Umsetzung: Rolle `samba_nfs` plus die
PVE-Skripte `scripts/upgrade-ct101-to-debian13.sh` (Adoption) und
`scripts/provision-ct101-samba.sh` (Fresh-State-Rebuild).
- Export ausschließlich für `ghostnet-ki` (10.0.0.90), NFSv4.2-only (TCP+UDP),
`SecType = sys`, Standard-Squash bleibt aktiv (`Squash = rootid`): Die
rootless Container schreiben als UID 982/983, nicht als root. Kein NFSv3,
kein mountd/rpcbind — `showmount` gilt nicht; Abnahme ist ein realer
NFSv4.2-Mount von `ghostnet-ki` (GNAI-018 Abschnitt 4 Punkt 2, angepasst).
- Mount auf `ghostnet-ki`: `/var/lib/ghostnet-encoding` (NFSv4.2, `hard`,
`_netdev`, `noatime`) — verwaltet vom Encoding-Ansible (GNENC-001 Abschnitt 6).
- Vorab wird nur das Export-Verzeichnis `/media/datenhdd3/Encoding` angelegt
(`root:gn-media 2775` — Abweichung von root:root 0755: Die Pipeline erzeugt
die Top-Level-Verzeichnisse via NFS als UID 982/983 und braucht group-write
plus setgid auf dem Export-Root); die Pipeline-Unterverzeichnisse werden via
NFS von `ghostnet-ki` durch die Ansible-Rolle angelegt (Owner/Group gemäß
GNENC-002 Abschnitt 4).
### 4.2 Gruppen- und UID-Abgleich
- Gruppe `gn-media` mit **GID 970** auf CT-101 anlegen (identisch zu
`ghostnet-ki`).
- Benutzer `ghost` in `gn-media` aufnehmen: Schreib-/Löschrecht auf den
Pipeline-Verzeichnissen, damit die Abholung per `mv` aus `[Encode]`
funktioniert. `daidalaw`/`debugofen` optional für reinen Lesezugriff.
- Die Platte `datenhdd3` erscheint im Monitoring über den NFS-Mount auf
`ghostnet-ki` (Disk-Metrik des NFS-Exports, GNMON-001).
### 4.3 Shares
```ini
[Encode]
comment = Encoding-Pipeline: fertige Encodes (Abholung per mv)
path = /media/datenhdd3/Encoding/output
public = no
writeable = yes
valid users = ghost, daidalaw, debugofen
admin users = ghost
write list = ghost
force group = gn-media
create mask = 0664
directory mask = 0775
[Encode-In]
comment = Encoding-Pipeline: .dlc-Drop (input)
path = /media/datenhdd3/Encoding/input
public = no
writeable = yes
valid users = ghost
admin users = ghost
write list = ghost
force group = gn-media
create mask = 0664
directory mask = 0775
```
- `[Encode]`: RW für `ghost` — die Entnahme per `mv` in die Bibliotheks-Shares
(Filme/Serien/Anime, teils andere Platten → Kopie+Verschieben auf CT-101)
räumt `output/` auf. `force group` stellt sicher, dass auch über SMB
angelegte Dateien der Gruppe `gn-media` angehören.
- `[Encode-In]`: RW für `ghost` — `.dlc`-Dateien werden in
`Encode-In\<Profilname>\` abgelegt (Profil = Preset-Name); jDownloader2
räumt sie nach der Verarbeitung nach `jd/dlc_done/` bzw. `jd/failed/` auf.
- Vor Produktivsetzung: `testparm` laufen lassen (siehe Abschnitt 6).
### 4.4 Verzeichnisstruktur
`/media/datenhdd3/Encoding` ist die Pipeline-Wurzel (vollständiges Layout in
GNENC-002 Abschnitt 4): `input/`, `jd/`, `queue/`, `work/`, `output/`,
`state/`. Anlage und Rechte erfolgen via NFS durch die Ansible-Rolle
`video_encoding` auf `ghostnet-ki`.
## 5. Abholung und Clean-Job
- Abholung: Entnahme per `mv` aus `[Encode]`; das `mv` räumt `output/` auf.
- Optionaler Clean-Job (Worker-Housekeeping auf `ghostnet-ki`, GNENC-002
Abschnitt 6): löscht Dateien in `output/` älter als 30 Tage.
## 6. Bekannte Befunde und offene Punkte
1. **Ansible-Rebuild inkl. Pipeline-Anbindung** — erledigt: Das Projekt
`proxmox/lxc/ct-101-samba/` ist gebaut (Design in
[GNAI-019](GNAI-019-DEC_Ansible-Migration.md), Requirements in
[GNAI-018](GNAI-018-REQ_Encoding-Pipeline-Integration.md)) und lokal
verifiziert (Syntax-Checks, Check-Mode-Smoke). **Ausstehend:** Adoption des
produktiven LXC gemäß Runbook in `ansible/README.md` (Dist-Upgrade auf
Debian 13, elf Inventory-Platzhalter, Schlüssel, Convergence, Verifikation).
2. **`[printers]` doppelt** in der `smb.conf` — erledigt: Das Duplikat (inkl.
Kommentarblöcke) ist im templated `smb.conf` bereinigt; `testparm` ist als
`validate:`-Gate im Rollen-Flow verankert (GNAI-019 Entscheidung 7).
3. **`usershare allow guests = yes`** — entschieden: beibehalten und im
Template dokumentiert; Änderung nur nach Betreiberentscheidung (GNAI-018 R4,
GNAI-019 Entscheidung 7).
4. **Backup** — entschieden: `backup.yml` (one-shot) sichert `/etc/samba` und
`/var/lib/samba` nach `/var/backups/ghostnet/samba/` vor der ersten
Convergence; alle fünf Medien-Mounts tragen `backup=no`; das Upgrade-Skript
fährt vor dem Dist-Upgrade einen `vzdump --mode stop` (GNAI-019 Entscheidung
6). **Offen:** hostunabhängiger Restore-Test (GNAI-000 Abschnitt 4 Punkt 4).
5. **System-Baseline** — erfasst: OS-Version (Debian 13 nach Upgrade, GNAI-019
Entscheidung 10), Hostname und Ressourcen-Mindestwerte über die
preflight-Platzhalter im Inventory (`samba_expected_hostname`,
`samba_expected_processor_vcpus`, `samba_minimum_memory_mb`,
`samba_minimum_root_size_bytes`, `samba_minimum_root_available_bytes`).
Plattengrößen/Kapazität siehe Punkt 6.
6. **Kapazitäts-Monitoring** der daten-Platten auf CT-101 — offen: heute nur
indirekt über den NFS-Mount auf ghostnet-ki sichtbar (GNMON-001); eigener
CT-101-Collector später.
7. **smb.conf-Verlust beim Dist-Upgrade (21.10.2026)** — erledigt: Beim
manuellen In-Place-Upgrade auf Debian 13 wurde die produktive `smb.conf`
durch die Paket-Default ersetzt; die 12 Media-Shares fehlten vorübergehend
(`smbclient -L` zeigte nur `homes`/`printers`/`print$`; die Media-Shares
antworteten `NT_STATUS_BAD_NETWORK_NAME`). Die passdb blieb intakt. Der
Betreiber stellte die produktive `smb.conf` am 21.10.2026 aus dem
vzdump-Backup vor dem Upgrade wieder her. Verifiziert am 21.10.2026: alle 12
Media-Shares antworten, die 10 CIFS-Mounts der Admin-Workstation
(`/etc/fstab`, `//10.0.0.9/…`) sind gehängt und lesbar, keine failed
`mnt-*.mount`-Units. Das bereitgestellte
`scripts/upgrade-ct101-to-debian13.sh` verwendet `--force-confold` und hätte
den Verlust verhindert. Bei der kommenden Ansible-Adoption wird die
`smb.conf` planmäßig durch das Template ersetzt (zusätzlich
`[Encode]`/`[Encode-In]`, `[printers]` bereinigt).
@@ -0,0 +1,186 @@
# Übergabe: Requirements CT 101 (Samba/NFS) für die Encoding-Pipeline
**Dokumenten-ID:** GNAI-018-REQ
**Titel:** Requirements der LLM-Server-Encoding-Pipeline an CT 101 — Spezifikation für den Ansible-Rebuild
**Stand:** 2026-10-19
**Status:** Übergabedokument; verbindliche Anforderungsliste für den ausführenden Agenten
**Adressat:** Ansible-Rebuild CT 101 (ausführendes Projekt: `proxmox/lxc/ct-101-samba/ansible/`)
**Quellen:** [GNAI-017](GNAI-017-PLAN_Samba-NFS-Export.md), [GNENC-001](../../../llm-server/encoding/GNENC-001-PLAN_Architecture.md), [GNENC-002](../../../llm-server/encoding/GNENC-002-PLAN_Pipeline.md), [GNMON-001](../../../llm-server/monitoring/GNMON-001-PLAN_Architecture.md)
## 1. Zweck und Adressat
CT 101 (`10.0.0.9`) ist der Samba-Dateiserver mit der Medienbibliothek und wird
derzeit manuell verwaltet. Betreiberentscheidung 19.10.2026: Die Umstellung auf
ein reproduzierbares Ansible-Projekt und die Anbindung der Encoding-Pipeline
werden **in einem Schritt** durchgeführt.
Dieses Dokument ist die verbindliche Requirements-Liste aus Sicht der
Encoding-Pipeline auf `ghostnet-ki` (`10.0.0.90`, Spezifikation GNENC-002). Der
ausführende Agent baut das Ansible-Projekt und setzt die Pipeline-Anbindung um.
Die Pipeline selbst (Mount, Container, Worker auf `ghostnet-ki`) ist **nicht**
Bestandteil dieses Auftrags.
**Sequenzhinweis:** Dieser Rebuild ist Voraussetzung für die
Encoding-Implementierung auf `ghostnet-ki`. Die gemeinsame Verifikation der
Pipeline erfolgt nach Fertigstellung durch den Betreiber.
## 2. Kontext
- Die Encoding-Pipeline arbeitet vollständig auf einem NFS-Mount:
`/var/lib/ghostnet-encoding` auf `ghostnet-ki` ← Export
`/media/datenhdd3/Encoding` von CT-101.
- Verzeichnislayout auf dem Export (GNENC-002 Abschnitt 4): `input/<Profil>/`,
`jd/`, `queue/<Profil>/<Release>/`, `work/`, `output/` (inkl. `_failed/`),
`state/`.
- Die Pipeline schreibt via NFS als UID 982 (`gn-encoding`) bzw. UID 983
(`gn-download`); Dateien entstehen mit umask 022 (0644/0755, Verzeichnisse
2770/2750 mit setgid, Gruppe `gn-media`).
- Abholung: Benutzer `ghost` entnimmt fertige Encodes per `mv` aus dem Share
`[Encode]` (räumt `output/` auf) und legt `.dlc`-Dateien in `[Encode-In]` ab.
## 3. Anforderungen (Muss)
### R1 – NFS-Export für `ghostnet-ki`
- Paket `nfs-kernel-server` installieren, Dienst aktivieren und starten.
- `/etc/exports` (genau diese Zeile, Export nur für `ghostnet-ki`):
```text
/media/datenhdd3/Encoding 10.0.0.90(rw,sync,no_subtree_check)
```
- Export-Root `/media/datenhdd3/Encoding` anlegen (root:root, 0755).
**Die Pipeline-Unterverzeichnisse werden nicht hier angelegt** — sie
entstehen via NFS durch die Ansible-Rolle `video_encoding` auf
`ghostnet-ki`.
- Kein `no_root_squash` erforderlich (rootless Container schreiben als
UID 982/983, nicht als root); Standard-Squash bleibt.
- `exportfs -ra` ausführen; Persistenz über Dienst-Unit sicherstellen.
### R2 – Samba-Shares für die Pipeline
Zwei neue Shares, exakt wie folgt (bestehende Shares unberührt):
```ini
[Encode]
comment = Encoding-Pipeline: fertige Encodes (Abholung per mv)
path = /media/datenhdd3/Encoding/output
public = no
writeable = yes
valid users = ghost, daidalaw, debugofen
admin users = ghost
write list = ghost
force group = gn-media
create mask = 0664
directory mask = 0775
[Encode-In]
comment = Encoding-Pipeline: .dlc-Drop (input)
path = /media/datenhdd3/Encoding/input
public = no
writeable = yes
valid users = ghost
admin users = ghost
write list = ghost
force group = gn-media
create mask = 0664
directory mask = 0775
```
### R3 – Gruppe und Benutzer-Abgleich
- Gruppe `gn-media` mit **GID 970** anlegen (identisch zu `ghostnet-ki`,
siehe GNAI-017 Abschnitt 4.2).
- Benutzer `ghost` in `gn-media` aufnehmen — erforderlich für das Löschen
(mv-Abholung) in `output/` und das Anlegen/Rename in `input/`, da die
Pipeline-Verzeichnisse Gruppe `gn-media` mit Mode 2770 tragen.
- `daidalaw`/`debugofen` benötigen keine Gruppenmitgliedschaft (reiner
Lesezugriff über world-read der Dateien).
### R4 – Bestandserhalt
- Alle bestehenden Shares bleiben funktionsgleich erhalten: `[homes]`,
`[printers]`, `[print$]`, `[Dokumente]`, `[Filme]`, `[Filme2]`, `[Serien]`,
`[Serien2]`, `[Animation]`, `[Anime]`, `[Extern]`, `[Musik]`, `[Audiobooks]`,
`[Software]`, `[Downloads]` (Bestandsliste in GNAI-017 Abschnitt 3).
- Vor der Umstellung `smb.conf` und den Samba-State (`/var/lib/samba`,
insb. `private/passdb.tdb`) sichern (Backup-Pfad dokumentieren).
- Das doppelte `[printers]`-Abschnitt in der bestehenden `smb.conf` bereinigen.
- `usershare allow guests = yes` dokumentieren; Änderung nur nach
Betreiberentscheidung (offen, siehe Abschnitt 7).
### R5 – Samba-Benutzer und Secrets
- Bestehende SMB-Benutzer `ghost`, `daidalaw`, `debugofen` samt Passwörtern
dürfen nicht verloren gehen (kein Lockout der produktiven Nutzung).
- passdb-Strategie festlegen: Erhalt des bestehenden passdb (Backup/Restore)
oder Neuvergabe mit server-lokal generierten Secrets. **Secrets werden auf
dem Ziel generiert und nie über Inventory oder git übergeben** (Konvention
analog CT-102-Ansible-Projekt).
### R6 – Idempotentes Ansible-Projekt
- Projekt unter `proxmox/lxc/ct-101-samba/ansible/`, analog
`proxmox/lxc/ct-102-keycloak/ansible/`: `ansible.cfg`,
`inventories/<env>/hosts.yml`, `playbooks/`, `roles/`, `files/`.
- Repo-weites Control-Venv (`shared/ansible/requirements-control.txt`) nutzen.
- Deploy-Zugang nach GNAI-011 (SSH-Key, z. B.
`~/.ssh/id_ed25519_ghostnet_ct101_ansible_deploy`); Key liegt nicht im Repo.
- Check-Mode (`--check --diff`) muss für das Site-Playbook funktionieren;
zwei aufeinanderfolgende Läufe müssen `changed=0` melden (Idempotenz).
- `testparm` als Verifikationsschritt im Rollen-Flow (fail bei Fehlern).
- Die `smb.conf` wird als Template gepflegt (vollständige Datei, nicht
snippets appended) — der Sollzustand ist reproduzierbar.
### R7 – Netzwerk und Firewall
- NFS (2049/tcp+udp) nur von `10.0.0.90` erreichbar; SMB (139/445) wie bisher
aus dem LAN. Ist-Zustand der Firewall dokumentieren, Sollzustand herstellen.
- CT-101 muss nach dem Rebuild booten und Dienste starten (Reboot-Test).
## 4. Abnahmekriterien
Der Rebuild gilt als abgenommen, wenn alles Folgende nachgewiesen ist
(datierte Nachweise in GNAI-017):
1. `testparm` fehlerfrei (inkl. bereinigtem `[printers]`-Duplikat).
2. `showmount -e localhost` zeigt `/media/datenhdd3/Encoding`.
3. `smbclient -L localhost` zeigt `[Encode]`, `[Encode-In]` und alle
Bestands-Shares.
4. Von `ghostnet-ki` (10.0.0.90) via NFS: Schreiben/Lesen im Export als
UID 982 und UID 983 erfolgreich (z. B. nach dem Mount auf
`ghostnet-ki` oder ein gezielter Mount-Test von CT-101 aus).
5. `ghost` kann in `[Encode-In]` Dateien anlegen und in `[Encode]` löschen
(mv-Simulation), dank `gn-media`-Mitgliedschaft.
6. `testparm`-Vergleich vor/nach: bestehende Shares funktional unverändert.
7. Idempotenz: zweiter Ansible-Lauf meldet `changed=0`.
8. Reboot-Test: Dienste (smbd, nfs-kernel-server) starten nach Neustart.
9. GNAI-017 (Abschnitt 6) und dieser Index aktualisiert.
## 5. Grenzen (Out of Scope)
- `ghostnet-ki`-Seite: NFS-Mount, Konten, Container, Worker, Dashboard —
anderes Projekt (GNENC/GNMON).
- Anlage der Pipeline-Unterverzeichnisse — erfolgt via NFS durch die Rolle
`video_encoding` auf `ghostnet-ki` (R1: nur Export-Root).
- Passwort-Neuvergabe für bestehende Benutzer ohne Betreiberentscheidung.
- Monitoring auf CT-101 (Plattenkapazität ist über den NFS-Mount auf
`ghostnet-ki` sichtbar, GNMON-001; eigener CT-101-Collector später).
- LLM-Metriken.
## 6. Referenzen
- [GNAI-017](GNAI-017-PLAN_Samba-NFS-Export.md) — Bestand, Plan, smb.conf-Schnipsel
- [GNENC-001](../../../llm-server/encoding/GNENC-001-PLAN_Architecture.md) — Architektur, Entscheidungen
- [GNENC-002](../../../llm-server/encoding/GNENC-002-PLAN_Pipeline.md) — Pipeline, Verzeichnislayout, Rechte
- [GNMON-001](../../../llm-server/monitoring/GNMON-001-PLAN_Architecture.md) — Monitoring-Anbindung
- [GNAI-011](../../GNAI-011-SEC_LXC-SSH-Architecture.md) — SSH-Zugang der LXCs
- [`proxmox/lxc/ct-102-keycloak/ansible/README.md`](../../../../../../proxmox/lxc/ct-102-keycloak/ansible/README.md) — Konventionen des Ansible-Projekts
## 7. Offene Punkte für den Rebuild
1. passdb-Strategie (Erhalt vs. Neuvergabe) — Entscheidung vor der Migration.
2. Backup-Ziel für `smb.conf` und Samba-State (Pfad, Aufbewahrung).
3. `usershare allow guests = yes` — beibehalten oder härten?
4. System-Baseline erfassen: Hostname, OS-Version, Platten/Kapazität (GNAI-017
Abschnitt 6).
@@ -0,0 +1,323 @@
# CT 101 – Samba-Dateiserver: Entwurfsentscheidungen der Ansible-Migration
**Dokumenten-ID:** GNAI-019-DEC
**Titel:** CT 101 Samba: Design-Entscheidungen für die Ansible-Migration (natives Samba, NFS-Ganesha als Quadlet, Fresh-State-Rebuild)
**Stand:** 2026-10-21
**Status:** Entwurfsentscheidungen verbindlich; im Projekt `proxmox/lxc/ct-101-samba/` umgesetzt und lokal verifiziert (Syntax-Checks, Check-Mode-Smoke); die Adoption des produktiven LXC steht aus und erfordert Betreiber-Autorisierung
**Referenzen:** [GNAI-017](GNAI-017-PLAN_Samba-NFS-Export.md), [GNAI-018](GNAI-018-REQ_Encoding-Pipeline-Integration.md), [GNAI-011](../../GNAI-011-SEC_LXC-SSH-Architecture.md), [GNAI-016](../ct-102-keycloak/GNAI-016-PLAN_Keycloak-Ansible-Rebuild.md), [GNENC-001](../../../llm-server/encoding/GNENC-001-PLAN_Architecture.md), [GNENC-002](../../../llm-server/encoding/GNENC-002-PLAN_Pipeline.md), [GNMON-001](../../../llm-server/monitoring/GNMON-001-PLAN_Architecture.md); Projektkonventionen: `proxmox/lxc/ct-100-dns/` und `proxmox/lxc/ct-102-keycloak/`
## 1. Zweck und Geltungsbereich
CT 101 (`10.0.0.9`) ist der produktive Samba-Dateiserver und bislang manuell
verwaltet. Betreiberentscheidungen vom 19.10.2026 (GNAI-017/GNAI-018): Aufnahme
ins Repository und Anbindung der Encoding-Pipeline in einem Schritt. Dieses
Dokument hält die verbindlichen Design-Entscheidungen für die Ansible-Migration
fest — insbesondere die Antworten auf die offene Frage „Samba nativ oder im
Podman-Container?“ — und begründet die Abweichungen von GNAI-017 Abschnitt 4.1
und GNAI-018 R1. Es ist das Referenzdokument für das ausführende Projekt
`proxmox/lxc/ct-101-samba/` (Rollen, Playbooks, PVE-Skripte, Runbooks).
## 2. Ausgangslage und Randbedingungen
- Produktiver, unprivileged LXC (Proxmox VE), Debian 12 (bookworm), manuell
verwaltet; Samba-Dateiserver mit 14 Shares auf fünf Host-Mounts
(`/media/daten1`, `/media/daten2`, `/media/daten3`, `/media/datenhdd2`,
`/media/datenhdd3`).
- Produktiver Samba-State: `smb.conf` plus `/var/lib/samba` inkl.
`private/passdb.tdb`; SMB-Benutzer `ghost`, `daidalaw`, `debugofen` mit
produktiven Passwörtern.
- Die Encoding-Pipeline auf `ghostnet-ki` (`10.0.0.90`) schreibt via NFS als
UID 982 (`gn-encoding`) bzw. UID 983 (`gn-download`); die Gruppe `gn-media`
(GID 970) muss auf beiden Seiten numerisch identisch sein (GNAI-018 R3,
GNENC-002).
- Verbindliche Anforderungen: GNAI-018 R1–R7. Projektkonventionen: CT 100
(Pi-hole-Quadlet, nftables-Pattern, Inventories agent/bootstrap/production)
und CT 102 (Keycloak-Ansible-Projekt, `podman_runtime`-Rolle, Quadlet-Pattern
mit digest-gepinntem Basisimage und sha256-gepinntem Containerfile).
- Secrets (SMB-Passwörter, passdb, `ghost`-Passwort, private SSH-Schlüssel,
Podman-Secrets) werden nie im Repository, im Inventory oder in Logs abgelegt
(Konvention analog CT 102).
## 3. Entscheidung 1: Samba bleibt nativ (Debian-Paket)
**Entscheidung:** Samba wird nicht containerisiert. Der Dienst läuft als
natives Debian-Paket (`samba`, `samba-common`, `samba-common-bin`, `smbclient`)
mit `smbd`/`nmbd` als systemd-Dienste in CT 101. Die vollständige `smb.conf`
ist als Jinja2-Template im Repository gepflegt (Entscheidung 8).
**Begründung:**
- Der produktive Bestand umfasst gewachsene POSIX-Rechte auf fünf Host-Mounts
und einen Samba-State (tdb/passdb). Ein Container-Wechsel würde die
Datei- und ID-Mapping-Semantik verändern, ohne einen Sicherheitsgewinn zu
bringen: Der LXC bleibt unprivileged, und Samba ist der Dienst, der die
Mounts direkt sehen muss.
- Image-Pinning und Container-Isolation (die sonst typische Begründung für
Podman, siehe CT 100/102) betreffen hier einen einzelnen, langlebigen
Systemdienst auf dem eigenen Host — der Mehrwert ist gering, die Komplexität
(State-Verlagerung, Druckerspool, ID-Mapping) hoch.
- Debian-Paketpflege ist über `unattended-upgrades` etabliert
(Rolle `samba_lxc_baseline`).
- Reproduzierbarkeit wird über das vollständig templated `smb.conf` plus
`testparm`-Gate hergestellt, nicht über ein Container-Image.
**Konsequenz:** Rolle `samba_smb`; native Dienste mit Handler-Neustart bei
Konfigurationsänderung; Post-State-Verifikation per `testparm`, `pdbedit -L`
und anonymer `smbclient -L`-Abfrage.
## 4. Entscheidung 2: NFS-Export via NFS-Ganesha als rootful Podman-Quadlet mit Host-Networking (statt `nfs-kernel-server`)
**Entscheidung:** Der NFS-Export für die Encoding-Pipeline (GNAI-018 R1) wird
nicht mit `nfs-kernel-server`, sondern mit **NFS-Ganesha** als **rootful**
Podman-Quadlet-Container (`ghostnet-samba-nfs.service`) mit **Host-Networking**
umgesetzt. Dafür wird in `/etc/pve/lxc/101.conf` ein **leerer
`lxc.seccomp.profile:`**-Eintrag gesetzt (Deaktivierung des LXC-Seccomp-Filters
für den gesamten CT).
**Begründung:**
- GNAI-018 R1 verlangte `nfs-kernel-server`. Der Kernel-NFS-Server kann in
einem unprivileged LXC nicht betrieben werden (kein Zugriff auf das
Kernel-NFS-Subsystem des Hosts). Ganesha ist ein Userspace-NFS-Server (VFS
FSAL) und läuft in einem unprivileged LXC.
- **Rootful** ist fachlich nötig: Der VFS-FSAL wendet die AUTH_SYS-Credentials
der Pipeline (UID 982/983) pro Request an; das erfordert `CAP_SETUID`/
`CAP_SETGID` innerhalb der LXC-User-Namespace, was ein rootless Container
nicht leisten kann. Standard-Squash bleibt aktiv (`Squash = rootid`, R1).
- **Host-Networking** bindet den Listener 2049 im Netz-Namespace von CT 101;
die nftables-Input-Chain deckt ihn ab. Die Quadlet-Unit trägt
`Requires=nftables.service` — ohne Firewall startet der Export nicht
(fail closed).
- **Leerer Seccomp-Eintrag:** Ganesha benötigt `open_by_handle_at` (VFS FSAL),
das das PVE-Standard-Seccomp-Profil blockiert. Der leere Eintrag deaktiviert
den Filter für den gesamten CT. Das ist vertretbar, weil der CT unprivileged
bleibt und Samba nativ keine privilegierten Syscalls jenseits der
User-Namespace benötigt. Beide PVE-Skripte setzen bzw. verifizieren den
leeren Eintrag (`scripts/upgrade-ct101-to-debian13.sh`,
`scripts/provision-ct101-samba.sh`).
- **Abweichung vom Export-Root aus R1:** Statt `root:root 0755` wird
`/media/datenhdd3/Encoding` als `root:gn-media 2775` angelegt. Die Pipeline
erzeugt die Top-Level-Verzeichnisse via NFS als UID 982/983 und benötigt
group-write plus setgid auf dem Export-Root (GNAI-017 Abschnitt 4.4); die
Pipeline-Unterverzeichnisse selbst entstehen weiterhin via NFS durch die
Rolle `video_encoding` auf `ghostnet-ki`.
**Konsequenz:** PVE-seitige Änderung am produktiven CT (Seccomp) — im
Upgrade-Skript durch einen `vzdump --mode stop` abgesichert. Die
Quadlet-Unit folgt dem CT-100/102-Pattern: digest-gepinntes Debian-13-Basisimage
(`debian:trixie-slim`), sha256-gepinntes `Containerfile.ganesha`,
`Pull=never`, Runtime-Tag `localhost/ghostnet/ganesha:trixie-ansible1`,
Healthcheck, read-only rootfs mit tmpfs `/run` und `/tmp`. Ohne dbus logged
Ganesha eine nicht-fatale Admin-Interface-Warnung (dokumentiert in
`roles/samba_nfs/README.md`).
## 5. Entscheidung 3: NFSv4-only — kein NFSv3, kein `showmount`
**Entscheidung:** Der Export ist NFSv4-only (`Protocols = 4`, kein NLM, kein
RQUOTA, kein mountd/rpcbind), Transport TCP+UDP, `SecType = sys`,
`Squash = rootid`, client-beschränkt auf `10.0.0.90`, `Pseudo` identisch zum
Export-Pfad (dokumentierter Mount-Pfad `10.0.0.9:/media/datenhdd3/Encoding`
bleibt unverändert).
**Begründung:** NFSv4 benötigt keinen Portmapper und kein mountd — weniger
Angriffsfläche und keine Legacy-Protokolle. Die Pipeline mountet NFSv4.2
(`hard`, `_netdev`, `noatime`; GNENC-001 Abschnitt 6).
**Konsequenz:** `showmount -e` ist kein zulässiges Abnahmekriterium
(NFSv4-only). GNAI-018 Abschnitt 4 Punkt 2 wird als **realer NFSv4.2-Mount-Test
von `ghostnet-ki`** interpretiert; dasselbe gilt für Punkt 8 (Dienste nach
Reboot: `ghostnet-samba-nfs.service` statt `nfs-kernel-server`).
## 6. Entscheidung 4: Identität — `gn-media` GID 970, aufgezeichnete Medien-UIDs, Mitgliedschaft nur `ghost`
**Entscheidung:**
- Gruppe `gn-media` mit GID 970 (identisch zu `ghostnet-ki`). Die Rolle
`samba_media` fails closed, wenn der GID-Slot oder der Gruppenname von einer
anderen Identität belegt ist.
- Die Medien-Konten `ghost`, `daidalaw`, `debugofen` werden mit ihren
**produktiv aufgezeichneten UIDs** im Inventory deklariert
(`samba_media_users`; UID-Platzhalter stoppen die Rollen-Validierung fail
closed, bis die Ist-Werte eingetragen sind). Bestehende Konten werden nur
auf die UID validiert und nie verändert; fehlende Konten werden im
Fresh-State-Rebuild mit exakt diesen UIDs angelegt (primäre Gruppe
`gid=uid`, `password_lock: true`, `daidalaw`/`debugofen` mit
`/usr/sbin/nologin` und ohne Home-Anlage).
- Mitgliedschaft in `gn-media`: nur `ghost` (GNAI-018 R3). `daidalaw` und
`debugofen` benötigen keine Mitgliedschaft — reiner Lesezugriff genügt.
**Begründung:** Die UID-Stabilität ist Voraussetzung der Pipeline
(AUTH_SYS-Credentials, `mv`-Abholung aus `[Encode]`, `.dlc`-Drop in
`[Encode-In]` über Gruppe `gn-media` mit Mode 2770). Fail-closed verhindert
Drift zwischen Soll- und Ist-Identität.
## 7. Entscheidung 5: passdb-Erhalt bei der Adoption; Secrets nie im Repository
**Entscheidung:**
- **Adoption (Default):** Die produktive passdb bleibt erhalten. Die Rolle
`samba_smb` assertet fail-closed, dass `/var/lib/samba/private/passdb.tdb`
vor der Convergence existiert, dass die `pdbedit -L`-Userliste vor und nach
der Convergence identisch ist und dass `ghost`, `daidalaw`, `debugofen`
enthalten sind (`samba_smb_preserve_passdb: true`).
- **Fresh-State-Rebuild:** Der erste `site.yml`-Lauf erfolgt einmalig mit
`-e samba_smb_preserve_passdb=false` (eine frische passdb existiert noch
nicht). Anschließend setzt der Operator die SMB-Passwörter interaktiv per
`smbpasswd -a ghost/daidalaw/debugofen` auf CT 101; der zweite Lauf mit dem
Default validiert die gefüllte passdb mit den vollen Guardrails.
- Secrets (SMB-Passwörter, passdb, `ghost`-Passwort, private SSH-Schlüssel,
Podman-Secrets) werden nie im Repository, im Inventory oder in Ansible-Logs
abgelegt; `pdbedit -L` listet nur Benutzernamen.
**Begründung:** GNAI-018 R5 (kein Lockout der produktiven Nutzung) und R4
(Backup vor der Umstellung); Konvention analog CT-102 (Secrets werden auf dem
Ziel generiert bzw. operator-seitig gesetzt).
## 8. Entscheidung 6: Backup-Strategie
**Entscheidung:**
- **Adoption:** `playbooks/backup.yml` (one-shot) sichert vor der ersten
Convergence `/etc/samba` und `/var/lib/samba` nach
`/var/backups/ghostnet/samba/` (root-only, `0700`). `verify-production.yml`
assertet das Vorhandensein dieses pre-migration Backups
(`samba_verify_require_premigration_backup: true`; Fresh-State-Rebuild:
`-e samba_verify_require_premigration_backup=false`).
- **Medien-Mounts:** Alle fünf Mounts tragen `backup=no` — `vzdump` archiviert
die Medienbibliothek nicht.
- **Upgrade:** `scripts/upgrade-ct101-to-debian13.sh` fährt vor dem
Dist-Upgrade einen `vzdump --mode stop --storage local --compress zstd` als
Sicherheitsnetz und sichert den laufenden Zustand (leerer Seccomp-Eintrag).
- **Restore-Pfad:** vzdump-Restore des CT plus erneuter `site.yml`-Convergence
(idempotent) bzw. das pre-migration Backup für den Samba-State.
**Offen (GNAI-017 Abschnitt 6 Punkt 4, GNAI-000 Abschnitt 4 Punkt 4):** Ein
hostunabhängiger Backup-/Restore-Test für CT 101 steht noch aus (analog zu den
anderen LXCs).
## 9. Entscheidung 7: `usershare allow guests = yes` beibehalten; `[printers]`-Duplikat bereinigt
**Entscheidung:**
- `usershare allow guests = yes` bleibt im templated `smb.conf` erhalten und
ist dort dokumentiert. Eine Änderung erfolgt nur nach ausdrücklicher
Betreiberentscheidung (GNAI-018 R4 und Abschnitt 7 Punkt 3).
- Der doppelte `[printers]`-Abschnitt aus dem Live-Bestand (inkl. duplizierter
Kommentarblöcke) ist im Template bereinigt (GNAI-018 R4).
**Begründung:** Bestandserhalt (R4) — eine Änderung des Guest-Verhaltens ohne
Betreiberentscheidung wäre ein funktionaler Eingriff in den produktiven
Betrieb.
## 10. Entscheidung 8: Config-as-Code — alle Konfigurationen als Repo-Templates
**Entscheidung:** Jede Konfigurationsdatei auf CT 101 ist ein Jinja2-Template
im Repository, das Ansible rendert und installiert; es gibt keinen
hand-editierten Zustand auf dem Ziel:
- `smb.conf` (vollständige Datei, 14 Shares: 12 Bestand-Shares + `[Encode]` und
`[Encode-In]` exakt nach GNAI-018 R2) — validiert per `testparm -s` vor der
Installation (`validate:`-Gate, GNAI-018 R6).
- `sshd` security drop-in (`/etc/ssh/sshd_config.d/99-security.conf`,
GNAI-011-Baseline ohne `AllowUsers` — siehe Template-Kommentar).
- `nftables.conf` plus systemd-Drop-in (Ghostnet-eigene Tabelle
`inet ghostnet_filter`, Netavark-Tabellen bleiben unberührt; `nft --check`
vor Installation).
- `ganesha.conf` (NFSv4-only, siehe Entscheidung 3).
- Quadlet `ghostnet-samba-nfs.container` (siehe Entscheidung 2).
`verify-production.yml` rendert die Templates per `lookup` erneut und
vergleicht sie mit den Live-Dateien (Drift-Erkennung).
## 11. Entscheidung 9: Fresh-State-Rebuild-Fähigkeit
**Entscheidung:** Die Playbooks bauen CT 101 von einem frischen Zustand
genau so wieder auf. Der dokumentierte Ablauf (Runbook in
`ansible/README.md`):
1. `scripts/provision-ct101-samba.sh` auf dem Proxmox-Host: frischer CT 101 aus
einer Debian-13-Vorlage mit dem aufgezeichneten Profil, fünf Medien-Mounts
(`backup=no`), leerer Seccomp-Eintrag, Baseline-Hook mit den
aufgezeichneten Konto-UIDs.
2. Operator auf der PVE-Konsole: `passwd ghost`, öffentliche Schlüssel aus
`ansible/files/ssh/` eintragen; Workstation: ssh-Aliase und frischer
known_hosts-Eintrag (Fingerprint gegenprüfen, GNAI-011 Abschnitt 3.3).
3. Erster `site.yml`-Lauf mit `-e samba_smb_preserve_passdb=false`
(`samba_media` legt fehlende Konten mit den aufgezeichneten UIDs an,
`samba_smb` installiert Samba und die templated `smb.conf`).
4. Operator: `smbpasswd -a` für `ghost`, `daidalaw`, `debugofen` (Secrets nie
im Repo).
5. Zweiter `site.yml`-Lauf mit Default: volle passdb-Guardrails, erwartet
`changed=0` (Idempotenz).
6. `verify-production.yml` mit
`-e samba_verify_require_premigration_backup=false`.
7. NFSv4.2-Mount-Test von `ghostnet-ki` (`10.0.0.90`).
Die einzige nicht deklarierbare State-Größe sind die Secrets (Schritt 4) —
sie existieren ausschließlich in der passdb auf CT 101.
## 12. Entscheidung 10: In-Place-Dist-Upgrade auf Debian 13 vor der Adoption
**Entscheidung:** Der bestehende produktive LXC wird vor der Übernahme per
`scripts/upgrade-ct101-to-debian13.sh` in-place von Debian 12 (bookworm) auf
Debian 13 (trixie) gehoben (Betreiberentscheidung: bestehender LXC bleibt
erhalten, zieht mit CT 100/102 gleich).
**Begründung:** Gleicher OS-Stand wie die übrigen Ansible-LXCs (CT 100/102 auf
Debian 13); frische Paketbasis für die Migration; die Baseline-Rolle erwartet
Debian 13.
**Ablauf (Skript):** Guards (CT läuft, unprivileged, Gast Debian 12, Dienste
aktiv, IPv4, uid_map, `backup=no` auf allen fünf Mounts) → `vzdump --mode stop`
→ laufender Zustand gesichert (leerer Seccomp-Eintrag) → In-Guest-Upgrade
(`bookworm` → `trixie` in deb822- und One-Line-Quellen, `dist-upgrade` mit
`--force-confold` — hält die produktive `smb.conf`, `autoremove`,
wtmpdb-Cleanup analog Baseline) → Reboot → Post-Verify (Debian 13, Dienste,
keine failed units, Listener 22/139/445, anonyme `smbclient -L`-Abfrage,
uid_map intakt, Seccomp deaktiviert, fünf Mounts eingehängt).
## 13. Verworfene Alternativen
| Alternative | Grund der Ablehnung |
| --- | --- |
| Samba im Podman-Container (analog CT 100/102) | Kein Sicherheitsgewinn bei unprivileged LXC; verändert ID-Mapping/State der gewachsenen Mounts; höherer Aufwand (Entscheidung 1) |
| `nfs-kernel-server` nativ (GNAI-018 R1) | In einem unprivileged LXC nicht betreibbar; Ganesha ist die Userspace-Alternative (Entscheidung 2) |
| NFSv3 mit `showmount`-Abnahme | Zusätzliche Legacy-Dienste (mountd/rpcbind); `showmount` ist kein verlässlicher Indikator; NFSv4-only (Entscheidung 3) |
| passdb-Neuvergebung als Default | Lockout-Risiko für produktive Nutzer (GNAI-018 R5); Erhalt mit Guardrails (Entscheidung 5) |
| SMB auch aus dem Admin-VPN (`10.8.0.0/24`) öffnen | Medien-Clients leben im LAN; Erweiterung ist ausdrückliche Betreiberentscheidung (GNAI-018 R7) |
| Medien-Mounts mit `backup=yes` | `vzdump` würde die Medienbibliothek archivieren (Ressourcen, Datenschutz); `backup=no` plus gezieltes State-Backup (Entscheidung 6) |
## 14. Auswirkungen auf GNAI-017 und GNAI-018
- **GNAI-017 Abschnitt 4.1** (`nfs-kernel-server`, `/etc/exports`) ist durch
Entscheidung 2 und 3 überholt und wird entsprechend aktualisiert.
- **GNAI-017 Abschnitt 2** (System-Baseline) wird um OS-Version (Debian 13 nach
Upgrade) und Hostname (Erfassung per `preflight.yml`) ergänzt; Abschnitt 6
(offene Punkte) wird um die Entscheidungen dieses Dokuments aktualisiert.
- **GNAI-018 R1** wird revidiert: NFS-Ganesha-Quadlet statt
`nfs-kernel-server`; Export-Root `root:gn-media 2775` statt `root:root 0755`
(begründete Abweichung, siehe Entscheidung 2).
- **GNAI-018 Abschnitt 4** (Abnahme): Punkt 2 (`showmount`) wird als realer
NFSv4.2-Mount-Test von `ghostnet-ki` interpretiert (Entscheidung 3); Punkt 8
nennt `ghostnet-samba-nfs.service` statt `nfs-kernel-server`.
- **GNAI-018 Abschnitt 7** (offene Punkte) ist entschieden: passdb-Erhalt
(Entscheidung 5), Backup-Ziel `/var/backups/ghostnet/samba/` plus vzdump im
Upgrade-Skript (Entscheidung 6), `usershare allow guests` beibehalten
(Entscheidung 7), System-Baseline via preflight-Platzhalter (Entscheidung 9).
## 15. Offene Punkte
1. Adoption des produktiven CT 101 gemäß Runbook in
`proxmox/lxc/ct-101-samba/ansible/README.md` (erfordert Betreiber-Autorisierung).
2. Elf Inventory-Platzhalter mit den Ist-Werten füllen (`preflight.yml` /
`audit-production.yml` liefern sie).
3. Drei Ed25519-Schlüsselpaare generieren (Operator); nur die öffentlichen
Schlüssel liegen im Repo unter `ansible/files/ssh/`.
4. Dist-Upgrade auf Debian 13 ausführen (`scripts/upgrade-ct101-to-debian13.sh`).
5. Reboot-Test nach der Convergence (GNAI-016 Abschnitt 7, LXC-boot_id-Caveat).
6. Hostunabhängiger Backup-/Restore-Test (GNAI-000 Abschnitt 4 Punkt 4).
7. Kapazitäts-Monitoring der daten-Platten auf CT 101 (GNAI-017 Abschnitt 6
Punkt 6; heute nur indirekt über den NFS-Mount auf `ghostnet-ki` sichtbar,
GNMON-001; eigener Collector später).
8. Erweiterung der SMB-Allowlist auf das Admin-VPN (`10.8.0.0/24`) —
Betreiberentscheidung, aktuell nicht geöffnet.