CT-101 Samba: dark2devil-Korrektur, ACL-Abgleich und AGENTS.md-Grundwissen
- dark2devil (UID 1002) aus der gesamten deklarierten State entfernt: derselbe Benutzer wie debugofen (Betreiberklärung 2026-10-28); GNAI-019 Entscheidung 11 revidiert, gn-media-Mitgliedschaft nur ghost - Share-ACLs im Inventar an die live smb.conf angeglichen (GNAI-018 R4): admin users auf elf Shares ergänzt, write list Dokumente/Extern ergänzt, Serien2 ohne force user/group; Template [printers] um browseable=no ergänzt - passdb-Asserts und Audit-Loops auf die drei deklarierten Medien-User umgestellt; Platzhalterzahl 11; provision-Script-Hash aktualisiert - AGENTS.md (Repo-Root) um Grundwissen für Agenten ergänzt: ghost-agent-Convention, Account-Landscape/Inventory-Pfade, Operator-Run-Steps, LXC-Konventionen, Repo-Konventionen Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
@@ -5,3 +5,95 @@ Before infrastructure work, read `.codex/LOCAL_MEMORY.md` if it exists. It conta
|
||||
For read-only access to the KI server, use the tested SSH profile `ghostnet-ai-agent`, which logs in as the unprivileged account `ghost-agent` on `10.0.0.90`. On this workstation, invoke it as `ssh -F ~/.ssh/config ghostnet-ai-agent` because the system-wide SSH client configuration currently has an ownership/permissions error. Do not assume sudo access or make server changes without an explicit user request.
|
||||
|
||||
The KI server at `10.0.0.90` is deliberately a fresh base system. The operator plans to install the LLM application stack in a later Ansible sprint. Do not install applications or change server configuration as part of documentation review or access checks unless the operator explicitly requests that work.
|
||||
|
||||
## Agent access convention: `ghost-agent`
|
||||
|
||||
`ghost-agent` is the standard unprivileged account for the AI agent on the
|
||||
Proxmox LXCs and the KI server (operator-confirmed 2026-10-28: "on the KI
|
||||
server and many other Proxmox LXCs"). It is a convention, not a per-host
|
||||
exception.
|
||||
|
||||
- Login is key-based with a **passphrase-less** Ed25519 key kept in the
|
||||
operator's `~/.ssh` (`id_ed25519_ghostnet_<host>_agent`); `~/.ssh/config`
|
||||
carries the matching `ghostnet-<host>-agent` aliases, which also work with
|
||||
`ssh -o BatchMode=yes`. Private keys never enter the repository.
|
||||
- `ghost-agent` has **no sudo** (verified on CT 100, CT 101, CT 103 and
|
||||
ghostnet-ki): treat every agent session as read-only unless the operator
|
||||
explicitly authorizes a change.
|
||||
- Known aliases (verify live state before use; the WireGuard LXC has no
|
||||
`ghost-agent` alias and uses the legacy `admin` account via alias `lxc`):
|
||||
|
||||
| Alias | System | IP |
|
||||
| --- | --- | --- |
|
||||
| `ghostnet-ct100-agent` | CT 100, Pi-hole/Split-DNS `dns` | 10.0.0.14 |
|
||||
| `ghostnet-ct101-agent` | CT 101, Samba file server | 10.0.0.9 |
|
||||
| `ghostnet-ct102-agent` | CT 102, Keycloak | 10.0.0.4 |
|
||||
| `ghostnet-ct103-agent` | CT 103, reverse proxy (NPM) | 10.0.0.10 |
|
||||
| `ghostnet-ct104-agent` | CT 104, Keycloak | 10.0.0.16 |
|
||||
| `ghostnet-ai-agent` | ghostnet-ki, LLM/AI server | 10.0.0.90 |
|
||||
|
||||
- Invoke ssh as `ssh -F ~/.ssh/config <alias>`: a bare `ssh` currently rejects
|
||||
`/etc/ssh/ssh_config.d/20-systemd-ssh-proxy.conf` because of its
|
||||
ownership/permissions; `-F` deliberately uses the local profile without
|
||||
loading that broken system configuration.
|
||||
- Dated per-host observations (host-key fingerprints, verified identities,
|
||||
account details) live in `.codex/LOCAL_MEMORY.md`, not here.
|
||||
|
||||
## Account landscape and Ansible inventory paths
|
||||
|
||||
| Account | Role | Key (operator `~/.ssh`) | sudo |
|
||||
| --- | --- | --- | --- |
|
||||
| `ghost-agent` | AI agent, read-only | `id_ed25519_ghostnet_<host>_agent` (no passphrase) | no |
|
||||
| `ghost` | human operator/admin | `id_ed25519_ghostnet_<host>_ghost` (passphrase-protected) | yes, password-gated |
|
||||
| `ansible-deploy` | Ansible deployment; created by the project's access role during adoption | `id_ed25519_ghostnet_<host>_ansible_deploy` (no passphrase) | `NOPASSWD: ALL` (treat the key as root-equivalent) |
|
||||
|
||||
Each Ansible LXC project (`proxmox/lxc/<ct>/ansible/`) maps these accounts to
|
||||
three inventories: `agent` (`ghost-agent`, read-only preflight), `bootstrap`
|
||||
(`ghost`, `--ask-become-pass`), `production` (`ansible-deploy`, NOPASSWD).
|
||||
Legacy exceptions exist (CT 103 is root-only and bootstrapped via the Proxmox
|
||||
console; the WireGuard LXC uses `admin`) — see `.codex/LOCAL_MEMORY.md`.
|
||||
|
||||
## Operator-run steps
|
||||
|
||||
- The workstation has **no Proxmox host access** (no `pct`): PVE-side commands
|
||||
(`pct exec`, `pct reboot`, `vzdump`, editing `/etc/pve/lxc/*.conf`) are run by
|
||||
the operator as root@pve. The agent prepares exact commands and reviews the
|
||||
pasted output.
|
||||
- Interactive secret steps are operator-run: `passwd`, `smbpasswd -a`, playbook
|
||||
runs with `--ask-become-pass`, and key passphrase prompts. The agent hands
|
||||
over copy-paste commands; the operator executes them.
|
||||
- Secrets never enter the repository, inventories, playbooks or logs: SMB
|
||||
passwords, the Samba passdb, the `ghost` password, private SSH keys, Podman
|
||||
secrets. Only public keys belong in the repo (`ansible/files/ssh/`).
|
||||
|
||||
## LXC / Proxmox conventions
|
||||
|
||||
- Reboot caveat (GNAI-016 section 7): in LXC, `/proc/sys/kernel/random/boot_id`
|
||||
belongs to the PVE host and does **not** change on a guest reboot — never use
|
||||
boot_id-based waiters; reboot via PVE and verify independently over SSH.
|
||||
- Unprivileged LXCs: keep the empty `lxc.seccomp.profile:` line (rootful
|
||||
Podman/Ganesha containers need `open_by_handle_at`), mask
|
||||
`sys-kernel-config.mount` (configfs is unavailable), and expect
|
||||
`uid_map 0 100000 65536` — host UIDs appear as 65534 (nobody) inside the
|
||||
guest.
|
||||
- In-place dist-upgrades: take a `vzdump` safety net first and use
|
||||
`--force-confold` so productive configuration files survive.
|
||||
|
||||
## Repository conventions
|
||||
|
||||
- Documentation: `docs/platform/proxmox-server/lxc/<ct>/GNAI-*.md` (German;
|
||||
decisions carry operator/date stamps, findings are lettered a), b), …).
|
||||
Ansible project READMEs are English. The central index is
|
||||
`docs/GNAI-000-DOC_Index.md`.
|
||||
- Ansible projects are self-contained under `proxmox/lxc/<ct>/ansible/`
|
||||
(`ansible.cfg`, `inventories/{agent,bootstrap,production}`, `playbooks/`,
|
||||
`roles/`, `files/ssh/`), use the repository-wide control venv (`.venv`, built
|
||||
from `shared/ansible/requirements-control.txt`) and the shared roles in
|
||||
`shared/ansible/roles/`.
|
||||
- Change discipline: productive changes only with explicit operator go; preview
|
||||
with `--check --diff` first; convergence must be idempotent (a second run
|
||||
reports `changed=0`); commit only when the operator asks.
|
||||
- Communicate with the operator in German.
|
||||
- Verify account/identity assumptions with the operator before declaring them
|
||||
(CT 101 example: `dark2devil` turned out to be the same person as
|
||||
`debugofen`; GNAI-019 decision 11 was revised accordingly).
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
|
||||
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
|
||||
mehreren Platten (Mounts `/media/daten1`, `/media/daten2`,
|
||||
`/media/daten3`, `/media/datenhdd1`, `/media/datenhdd2/extern`,
|
||||
`/media/datenhdd3`; erfasst am 27.10.2026). Bislang ist die LXC nicht im
|
||||
Infrastructure-Repository verwaltet; am 19.10.2026 wurde beschlossen, sie
|
||||
aufzunehmen (Betreiberentscheidung).
|
||||
|
||||
@@ -26,9 +27,10 @@ offenen Punkte fest. Bestehende Shares bleiben unberührt.
|
||||
| Container-ID | CT 101 |
|
||||
| IPv4 | 10.0.0.9 |
|
||||
| Samba-Rolle | standalone server, Workgroup `Ghost.net` (aus `smb.conf`) |
|
||||
| SMB-Benutzer | `ghost`, `daidalaw`, `debugofen` |
|
||||
| SMB-Benutzer | `ghost`, `daidalaw`, `debugofen` (die passdb enthält zusätzlich den Alt-Eintrag `dark2devil`, UID 1002 — dieselbe Person wie `debugofen`, nicht deklariert; siehe Abschnitt 6.8 (e) und GNAI-019 Entscheidung 11) |
|
||||
| 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`) |
|
||||
| Hostname | `Samba` (großgeschrieben; FQDN `Samba.fritz.box`), erfasst am 27.10.2026; Inventory-Platzhalter `samba_expected_hostname` |
|
||||
| Ressourcen-Profil | 1 CPU (cpuset), 2048 MiB RAM, 2048 MiB Swap, 4 GiB Rootfs (lxcfs-/cgroup-Werte im Gast, 27.10.2026) |
|
||||
|
||||
## 3. Bestand: Shares (aus `smb.conf`, Stand 19.10.2026)
|
||||
|
||||
@@ -37,7 +39,7 @@ offenen Punkte fest. Bestehende Shares bleiben unberührt.
|
||||
| `[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` | — |
|
||||
| `[Dokumente]` | `/media/daten1/Dokumente` | RO, nur `ghost`, write `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` |
|
||||
@@ -85,9 +87,12 @@ PVE-Skripte `scripts/upgrade-ct101-to-debian13.sh` (Adoption) und
|
||||
|
||||
- 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.
|
||||
- Benutzer `ghost` in `gn-media` aufnehmen (GNAI-018 R3):
|
||||
Schreib-/Löschrecht auf den Pipeline-Verzeichnissen, damit die Abholung per
|
||||
`mv` aus `[Encode]` und der `.dlc`-Drop in `[Encode-In]` funktionieren.
|
||||
`daidalaw`/`debugofen` benötigen keine Mitgliedschaft — reiner Lesezugriff
|
||||
genügt. **Korrektur 28.10.2026:** Die zunächst geplante Aufnahme von
|
||||
`dark2devil` entfällt (GNAI-019 Entscheidung 11 revidiert).
|
||||
- Die Platte `datenhdd3` erscheint im Monitoring über den NFS-Mount auf
|
||||
`ghostnet-ki` (Disk-Metrik des NFS-Exports, GNMON-001).
|
||||
|
||||
@@ -147,9 +152,12 @@ GNENC-002 Abschnitt 4): `input/`, `jd/`, `queue/`, `work/`, `output/`,
|
||||
`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).
|
||||
verifiziert (Syntax-Checks, Check-Mode-Smoke). **In Arbeit (Stand
|
||||
27.10.2026):** Adoption gemäß Runbook in `ansible/README.md` — Schlüssel
|
||||
installiert, SSH-Zugang für `ghost-agent` (UID 1004) und `ghost` (UID 1000)
|
||||
hergestellt; die elf Inventory-Platzhalter wurden am 27.10.2026 aus
|
||||
preflight/live gefüllt (alle drei Inventare byte-identisch); ausstehend:
|
||||
audit, bootstrap, Konvergenz, 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).
|
||||
@@ -158,7 +166,7 @@ GNENC-002 Abschnitt 4): `input/`, `jd/`, `queue/`, `work/`, `output/`,
|
||||
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
|
||||
Convergence; alle sechs 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
|
||||
@@ -184,3 +192,62 @@ GNENC-002 Abschnitt 4): `input/`, `jd/`, `queue/`, `work/`, `output/`,
|
||||
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).
|
||||
8. **Adoption (27.10.2026): Befunde und Korrekturen vor der Konvergenz** —
|
||||
erledigt: (a) Hostname erfasst: `Samba` (großgeschrieben, FQDN
|
||||
`Samba.fritz.box`); die Defaults in `samba_lxc_baseline` und
|
||||
`provision-ct101-samba.sh` standen fälschlich auf klein `samba` und wurden
|
||||
korrigiert (Rolle-Identity-Assert, Fresh-State-Rebuild). (b)
|
||||
`sys-kernel-config.mount` war auf CT 101 `failed` (configfs ist in
|
||||
unprivileged LXC nicht verfügbar); CT 100/102/103 maskieren die Unit seit
|
||||
ihrer Erstellung. Die Maske ist jetzt in `samba_lxc_baseline` und
|
||||
`provision-ct101-samba.sh` deklariert und wurde auf CT 101 manuell gesetzt
|
||||
(`preflight.yml` verlangt „no failed units"). (c) Das manuelle
|
||||
Dist-Upgrade vom 21.10. hatte den leeren `lxc.seccomp.profile:` nicht
|
||||
gesetzt (Seccomp-Filter aktiv, `Seccomp: 2`); am 27.10.2026 nachgetragen
|
||||
und per CT-Neustart wirksam (GNAI-019 Entscheidung 2). (d) Das Konto
|
||||
`ghost` hatte das Home-Feld `/home/ghost/` (Trailing Slash) und die Shell
|
||||
`/bin/false`; vor der Baseline auf `/home/ghost` und `/bin/bash`
|
||||
normalisiert (27.10.2026). (e) Konto `dark2devil` (UID 1002, Lars Peuser,
|
||||
Home `/home/dark2devil`, seit 11.03.2024) — **Korrektur 28.10.2026:** Der
|
||||
Betreiber klärte, dass `dark2devil` und `debugofen` (UID 1003) dieselbe
|
||||
Person sind und `debugofen` der valide Account ist; `dark2devil` ist ein
|
||||
Alt-Account. Die am 27.10.2026 beschlossene Gleichstellung mit `ghost`
|
||||
(GNAI-019 Entscheidung 11) wurde zurückgenommen: `dark2devil` ist nicht in
|
||||
`samba_media_users` deklariert, nicht Mitglied von `gn-media` und in keiner
|
||||
Share-ACL eingetragen (die live `smb.conf` nennt ihn nirgends). Konto und
|
||||
passdb-Eintrag bleiben auf der Adoption unangetastet (keine produktive
|
||||
Account-Löschung ohne ausdrückliche Betreiberentscheidung); optionaler
|
||||
Cleanup, Betreiberentscheidung: `smbpasswd -x dark2devil` auf CT 101.
|
||||
(f) Der private
|
||||
`ghost`-SSH-Key erhielt am 27.10.2026 eine Passphrase (GNAI-011 Abschnitt
|
||||
3.3); Entsperrung über den lokalen ssh-agent. (g) Mount-Topologie und
|
||||
Ressourcen-Profil erfasst (27.10.2026, nach dem Reboot): Sechs Medien-Mounts
|
||||
sind produktiv eingehängt — `/media/daten1`, `/media/daten2`,
|
||||
`/media/daten3` (btrfs), `/media/datenhdd1` (ext4, leer, Verzeichnis auf der
|
||||
Host-Root-Platte), `/media/datenhdd2/extern` (btrfs; die Extern-Platte ist
|
||||
am Unterverzeichnis eingehängt, nicht an `/media/datenhdd2` selbst) und
|
||||
`/media/datenhdd3` (btrfs). Die geplante Mount-Liste wich davon ab (fünf
|
||||
Einträge mit `/media/datenhdd2`) und wurde korrigiert: Inventory
|
||||
`samba_media_mount_points`, `samba_media`-Defaults,
|
||||
`provision-ct101-samba.sh` (mp0–mp5) und `upgrade-ct101-to-debian13.sh`
|
||||
(GNAI-019 entsprechend). Profil des produktiven CT: 1 CPU, 2048 MiB RAM,
|
||||
2048 MiB Swap, 4 GiB Rootfs — die Defaults in `provision-ct101-samba.sh`
|
||||
wurden darauf korrigiert (zuvor 2 Cores / 32 GiB / 1024 MiB Swap).
|
||||
`/media/datenhdd3/Encoding` existiert produktiv noch nicht; die Konvergenz
|
||||
legt es als `root:gn-media 2775` an (GNAI-019 Entscheidung 2). (h) Die
|
||||
Gruppe `gn-media` existiert produktiv noch nicht (GID 970 frei; `ghost`
|
||||
nicht Mitglied) — `samba_media` legt sie bei der Konvergenz an und nimmt
|
||||
`ghost` auf; `preflight.yml` toleriert das Fehlen (Report statt Abbruch).
|
||||
(i) **Share-ACLs gegen live abgeglichen (28.10.2026):** Das Inventory
|
||||
deklarierte die `admin users`-Zeilen der live `smb.conf` nicht (betroffen:
|
||||
Dokumente, Filme, Filme2, Serien2, Animation, Anime, Extern, Musik,
|
||||
Audiobooks, Software, Downloads), das `write list` von `[Dokumente]` und
|
||||
`[Extern]` fehlte, und `[Serien2]` trug ein `force user/group = root`, das
|
||||
live nicht existiert. Nach GNAI-018 R4 (funktionsgleicher Erhalt) deklariert
|
||||
das Inventory die ACLs nun exakt wie die live `smb.conf` (Erfassung
|
||||
28.10.2026); die Konvergenz ändert damit keine produktiven Share-Rechte
|
||||
außer der planmäßigen Ergänzung von `[Encode]`/`[Encode-In]`. Die
|
||||
Normalisierung `public = yes` → `guest ok = no` auf den Medien-Shares ist
|
||||
funktionsneutral (mit `valid users` ist Gastzugriff ohnehin verweigert).
|
||||
Ebenfalls angeglichen: `[printers]` trägt im Template nun `browseable = no`
|
||||
wie live (Sichtbarkeit im anonymen Listing).
|
||||
|
||||
@@ -20,9 +20,10 @@ und GNAI-018 R1. Es ist das Referenzdokument für das ausführende Projekt
|
||||
## 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`).
|
||||
verwaltet; Samba-Dateiserver mit 12 produktiven Shares auf sechs
|
||||
Host-Mounts (`/media/daten1`, `/media/daten2`, `/media/daten3`,
|
||||
`/media/datenhdd1`, `/media/datenhdd2/extern`, `/media/datenhdd3`) plus zwei
|
||||
geplanten Pipeline-Shares (`[Encode]`, `[Encode-In]`).
|
||||
- Produktiver Samba-State: `smb.conf` plus `/var/lib/samba` inkl.
|
||||
`private/passdb.tdb`; SMB-Benutzer `ghost`, `daidalaw`, `debugofen` mit
|
||||
produktiven Passwörtern.
|
||||
@@ -47,7 +48,7 @@ ist als Jinja2-Template im Repository gepflegt (Entscheidung 8).
|
||||
|
||||
**Begründung:**
|
||||
|
||||
- Der produktive Bestand umfasst gewachsene POSIX-Rechte auf fünf Host-Mounts
|
||||
- Der produktive Bestand umfasst gewachsene POSIX-Rechte auf sechs 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
|
||||
@@ -145,6 +146,9 @@ Reboot: `ghostnet-samba-nfs.service` statt `nfs-kernel-server`).
|
||||
`/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.
|
||||
**Update 28.10.2026:** Die Gleichstellung von `dark2devil` wurde
|
||||
zurückgenommen (Entscheidung 11 revidiert) — `dark2devil` und `debugofen`
|
||||
sind dieselbe Person; nur `ghost` ist Mitglied von `gn-media`.
|
||||
|
||||
**Begründung:** Die UID-Stabilität ist Voraussetzung der Pipeline
|
||||
(AUTH_SYS-Credentials, `mv`-Abholung aus `[Encode]`, `.dlc`-Drop in
|
||||
@@ -183,7 +187,7 @@ Ziel generiert bzw. operator-seitig gesetzt).
|
||||
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
|
||||
- **Medien-Mounts:** Alle sechs 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
|
||||
@@ -236,7 +240,7 @@ 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
|
||||
einer Debian-13-Vorlage mit dem aufgezeichneten Profil, sechs 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
|
||||
@@ -245,8 +249,8 @@ genau so wieder auf. Der dokumentierte Ablauf (Runbook in
|
||||
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).
|
||||
4. Operator: `smbpasswd -a` für `ghost`, `daidalaw` und
|
||||
`debugofen` (Secrets nie im Repo).
|
||||
5. Zweiter `site.yml`-Lauf mit Default: volle passdb-Guardrails, erwartet
|
||||
`changed=0` (Idempotenz).
|
||||
6. `verify-production.yml` mit
|
||||
@@ -268,15 +272,35 @@ 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`
|
||||
aktiv, IPv4, uid_map, `backup=no` auf allen sechs 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).
|
||||
uid_map intakt, Seccomp deaktiviert, sechs Mounts eingehängt).
|
||||
|
||||
## 13. Verworfene Alternativen
|
||||
## 13. Entscheidung 11: `dark2devil` — Alt-Account, keine Gleichstellung (revidiert 28.10.2026)
|
||||
|
||||
**Entscheidung (revidiert):** Die am 27.10.2026 beschlossene Gleichstellung
|
||||
von `dark2devil` mit `ghost` wird zurückgenommen. Der Betreiber klärte am
|
||||
28.10.2026, dass `dark2devil` (UID 1002) und `debugofen` (UID 1003) dieselbe
|
||||
Person sind (Lars Peuser) und `debugofen` der valide Account ist;
|
||||
`dark2devil` ist ein Alt-Account ohne produktive Share-Berechtigung (die live
|
||||
`smb.conf` nennt ihn nirgends). Konkret: `dark2devil` ist nicht in
|
||||
`samba_media_users` deklariert, nicht Mitglied von `gn-media` und in keiner
|
||||
Share-ACL eingetragen; die passdb-Asserts verlangen nur `ghost`, `daidalaw`
|
||||
und `debugofen`. Konto und passdb-Eintrag bleiben auf der Adoption
|
||||
unangetastet (keine produktive Account-Löschung ohne ausdrückliche
|
||||
Betreiberentscheidung). Optionaler Cleanup (Betreiberentscheidung, nicht Teil
|
||||
der Migration): `smbpasswd -x dark2devil` auf CT 101.
|
||||
|
||||
**Begründung:** Die Gleichstellung beruhte auf der Annahme, `dark2devil` sei
|
||||
ein aktiver privater Benutzer. Nach der Betreiberklärung ist die Person über
|
||||
den validen Account `debugofen` angebunden; eine zweite Identität für
|
||||
dieselbe Person auf Medien-/SMB-Ebene ist nicht erforderlich.
|
||||
|
||||
## 14. Verworfene Alternativen
|
||||
|
||||
| Alternative | Grund der Ablehnung |
|
||||
| --- | --- |
|
||||
@@ -287,7 +311,7 @@ uid_map intakt, Seccomp deaktiviert, fünf Mounts eingehängt).
|
||||
| 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
|
||||
## 15. 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.
|
||||
@@ -304,16 +328,36 @@ uid_map intakt, Seccomp deaktiviert, fünf Mounts eingehängt).
|
||||
(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).
|
||||
- **GNAI-017 Abschnitt 1/2** (Mount-Topologie): korrigiert auf die sechs
|
||||
produktiv eingehängten Mounts (inkl. `/media/datenhdd1` und
|
||||
`/media/datenhdd2/extern`); `provision-ct101-samba.sh` attachiert `mp0`–`mp5`
|
||||
mit dem aufgezeichneten Profil (1 CPU, 2048 MiB RAM, 2048 MiB Swap, 4 GiB
|
||||
Rootfs).
|
||||
- **Korrektur 28.10.2026 (GNAI-018 R4):** GNAI-017 Abschnitt 2
|
||||
(SMB-Benutzer-Tabelle) und Abschnitt 4.2 (`gn-media`-Mitgliedschaft) werden
|
||||
korrigiert — `dark2devil` ist nicht deklariert (Entscheidung 11
|
||||
revidiert). Das Inventory deklariert die Share-ACLs exakt wie die live
|
||||
`smb.conf` (inkl. `admin users` auf elf Shares, `write list` auf
|
||||
`[Dokumente]`/`[Extern]`; `[Serien2]` ohne `force user/group`), damit die
|
||||
Konvergenz keine produktiven Share-Rechte ändert.
|
||||
|
||||
## 15. Offene Punkte
|
||||
## 16. 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).
|
||||
`audit-production.yml` liefern sie) — **erledigt 27.10.2026**: preflight und
|
||||
Live-Abfragen lieferten die Werte; alle drei Inventare sind byte-identisch
|
||||
gefüllt (Hostname `Samba`, 1 vCPU, 2048 MiB RAM, Rootfs-Mindestwerte
|
||||
4 GB/1 GB, Medien-UIDs 1000/1001/1003 — der Alt-Account `dark2devil`,
|
||||
UID 1002, ist nicht deklariert, siehe Entscheidung 11 —, admin 1000,
|
||||
agent 1004, deploy 1005).
|
||||
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`).
|
||||
Schlüssel liegen im Repo unter `ansible/files/ssh/` — **erledigt**: agent und
|
||||
deploy ohne Passphrase, ghost mit Passphrase (GNAI-011 Abschnitt 3.3).
|
||||
4. Dist-Upgrade auf Debian 13 ausführen (`scripts/upgrade-ct101-to-debian13.sh`) —
|
||||
**erledigt 21.10.2026**, manuell durch den Betreiber (GNAI-017 Abschnitt 6
|
||||
Punkt 7).
|
||||
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
|
||||
|
||||
@@ -59,8 +59,8 @@ role argument specs reject them before any task runs). `preflight.yml` on the
|
||||
`samba_minimum_root_available_bytes` (group_vars)
|
||||
- `samba_access_admin_uid`, `samba_access_agent_uid`,
|
||||
`samba_access_deploy_uid` (host_vars)
|
||||
- `samba_media_users[ghost|daidalaw|debugofen].uid` (group_vars; the recorded
|
||||
productive UIDs — the pipeline depends on them, GNAI-018 R1)
|
||||
- `samba_media_users[ghost|daidalaw|debugofen].uid` (group_vars; the
|
||||
recorded productive UIDs — the pipeline depends on them, GNAI-018 R1)
|
||||
|
||||
## Playbooks
|
||||
|
||||
@@ -87,13 +87,21 @@ keeps the healthy file server and its Samba passdb intact:
|
||||
2. On the Proxmox host, run `scripts/upgrade-ct101-to-debian13.sh` (see
|
||||
`scripts/README.md`): in-place Debian 12 → 13 dist-upgrade of the existing
|
||||
CT 101 with a pre-upgrade `vzdump` and the empty `lxc.seccomp.profile`.
|
||||
When the dist-upgrade was performed manually instead of via the script,
|
||||
ensure the empty `lxc.seccomp.profile:` line is present in
|
||||
`/etc/pve/lxc/101.conf` and reboot the CT — the Ganesha container needs it
|
||||
(GNAI-019 decision 2).
|
||||
3. On the PVE console of CT 101: capture the productive `ghost` UID, pick a
|
||||
free UID for `ghost-agent`, then run the shared baseline
|
||||
`ghostnet-lxc-baseline.sh 101` with `GHOSTNET_AGENT_UID`/`GHOSTNET_ADMIN_UID`
|
||||
(validates the unprivileged mapping, creates the locked `ghost-agent`,
|
||||
prepares `.ssh`, adds `ghost` to `sudo`, disables `ssh.socket`). Then set
|
||||
`passwd ghost` and paste the `ghost-agent` and `ghost` public keys into the
|
||||
respective `authorized_keys`.
|
||||
prepares `.ssh`, adds `ghost` to `sudo`, disables `ssh.socket`). Also mask
|
||||
`sys-kernel-config.mount` (configfs is unavailable in unprivileged LXC; CT
|
||||
100/102/103 convention) and clear its failed state — `preflight.yml`
|
||||
requires no failed units:
|
||||
`pct exec 101 -- systemctl mask sys-kernel-config.mount && pct exec 101 -- systemctl reset-failed sys-kernel-config.mount`.
|
||||
Then set `passwd ghost` and paste the `ghost-agent` and `ghost` public
|
||||
keys into the respective `authorized_keys`.
|
||||
4. On the workstation: add the `ghostnet-ct101-agent` / `ghostnet-ct101-ghost`
|
||||
ssh aliases and seed `~/.ssh/known_hosts_ghostnet_ct101` (verify the
|
||||
fingerprint on the PVE console first, GNAI-011 section 3.3).
|
||||
@@ -122,11 +130,11 @@ and installs; the only state that cannot be declared is secret material.
|
||||
|
||||
1. Prerequisites: the inventory is fully filled (all 11 placeholders carry the
|
||||
recorded productive values), the three `.pub` files are committed, and the
|
||||
five media host paths are known.
|
||||
six media host paths are known.
|
||||
2. On the Proxmox host, run `scripts/provision-ct101-samba.sh` with
|
||||
`GHOSTNET_AGENT_UID`, `GHOSTNET_ADMIN_UID` and `GHOSTNET_MP0_HOST` …
|
||||
`GHOSTNET_MP4_HOST` (see `scripts/README.md`). This creates CT 101 from a
|
||||
Debian 13 template with the recorded profile, attaches the five media
|
||||
`GHOSTNET_MP5_HOST` (see `scripts/README.md`). This creates CT 101 from a
|
||||
Debian 13 template with the recorded profile, attaches the six media
|
||||
mounts (`backup=no`), disables the LXC seccomp filter and runs the baseline
|
||||
hook, which creates `ghost-agent` and `ghost` with the recorded UIDs.
|
||||
3. Operator: `pct exec 101 -- passwd ghost`, then install the `ghost-agent` and
|
||||
|
||||
@@ -8,15 +8,16 @@ ansible_ssh_common_args: >-
|
||||
|
||||
samba_expected_distribution: Debian
|
||||
samba_expected_distribution_major_version: "13"
|
||||
# Live hostname of CT 101; copy from preflight.yml (SMB1 is disabled, so the
|
||||
# live server does not answer NetBIOS names):
|
||||
samba_expected_hostname: REPLACE-WITH-PREFLIGHT-HOSTNAME
|
||||
# Live hostname of CT 101 (recorded 2026-10-27 from preflight.yml; SMB1 is
|
||||
# disabled, so the live server does not answer NetBIOS names):
|
||||
samba_expected_hostname: Samba
|
||||
samba_expected_virtualization_type: lxc
|
||||
# Expected Podman version after the dist-upgrade (trixie), analog to CT 100/102:
|
||||
samba_expected_podman_version: "5.4.2"
|
||||
# Resource minimums; copy from preflight.yml:
|
||||
samba_minimum_root_size_bytes: REPLACE-WITH-PREFLIGHT-ROOT-SIZE
|
||||
samba_minimum_root_available_bytes: REPLACE-WITH-PREFLIGHT-ROOT-AVAIL
|
||||
# Resource minimums (recorded 2026-10-27; round values at/below the live
|
||||
# capacity, CT 100/102 convention):
|
||||
samba_minimum_root_size_bytes: 4000000000
|
||||
samba_minimum_root_available_bytes: 1000000000
|
||||
|
||||
samba_firewall_management_ipv4:
|
||||
- 10.0.0.0/24
|
||||
@@ -35,48 +36,64 @@ samba_access_source_networks: 10.0.0.0/24,10.8.0.0/24
|
||||
|
||||
samba_media_group_name: gn-media
|
||||
samba_media_group_gid: 970
|
||||
# Media accounts with their productive UIDs; copy from preflight.yml /
|
||||
# audit-production.yml (fresh-state rebuild: missing accounts are created with
|
||||
# exactly these UIDs; existing accounts are only validated on the UID):
|
||||
# Media accounts with their productive UIDs (recorded 2026-10-27 from
|
||||
# preflight.yml / audit-production.yml; fresh-state rebuild: missing accounts
|
||||
# are created with exactly these UIDs; existing accounts are only validated on
|
||||
# the UID). The legacy account dark2devil (UID 1002) exists on the productive
|
||||
# CT 101 but is deliberately NOT declared: it belongs to the same person as
|
||||
# debugofen (operator clarification 2026-10-28, GNAI-019 decision 11) and is
|
||||
# not referenced by any share in the live smb.conf.
|
||||
samba_media_users:
|
||||
- name: ghost
|
||||
uid: REPLACE-WITH-AUDIT-UID-GHOST
|
||||
uid: 1000
|
||||
shell: /bin/bash
|
||||
home: /home/ghost
|
||||
create_home: true
|
||||
- name: daidalaw
|
||||
uid: REPLACE-WITH-AUDIT-UID-DAIDALAW
|
||||
uid: 1001
|
||||
shell: /usr/sbin/nologin
|
||||
home: /home/daidalaw
|
||||
create_home: false
|
||||
- name: debugofen
|
||||
uid: REPLACE-WITH-AUDIT-UID-DEBUGOFEN
|
||||
uid: 1003
|
||||
shell: /usr/sbin/nologin
|
||||
home: /home/debugofen
|
||||
create_home: false
|
||||
samba_media_group_members:
|
||||
- ghost
|
||||
# Live media mount topology of the productive CT 101 (recorded 2026-10-27):
|
||||
# six Proxmox mount points. /media/datenhdd1 is an empty ext4 directory from
|
||||
# the host root filesystem; the Extern disk is mounted at the subdirectory
|
||||
# /media/datenhdd2/extern (not at /media/datenhdd2 itself).
|
||||
samba_media_mount_points:
|
||||
- /media/daten1
|
||||
- /media/daten2
|
||||
- /media/daten3
|
||||
- /media/datenhdd2
|
||||
- /media/datenhdd1
|
||||
- /media/datenhdd2/extern
|
||||
- /media/datenhdd3
|
||||
|
||||
samba_smb_workgroup: Ghost.net
|
||||
samba_smb_service_units:
|
||||
- smbd.service
|
||||
- nmbd.service
|
||||
# Complete share target state from GNAI-017 section 3 plus [Encode] and
|
||||
# [Encode-In] from GNAI-018 R2. Comments only where the live system shows them
|
||||
# (Debian defaults and the new pipeline shares); the media shares had empty
|
||||
# comments in the anonymous listing and stay without comments.
|
||||
# Complete share target state: the twelve productive shares mirror the live
|
||||
# smb.conf ACLs exactly (valid users / write list / admin users / force
|
||||
# user+group; recorded 2026-10-28, GNAI-018 R4 funktionsgleicher Erhalt), plus
|
||||
# [Encode] and [Encode-In] per GNAI-017 section 4.3 / GNAI-018 R2. Comments
|
||||
# only where the live system shows them (Debian defaults and the new pipeline
|
||||
# shares); the media shares had empty comments in the anonymous listing and
|
||||
# stay without comments.
|
||||
samba_smb_media_shares:
|
||||
- name: Dokumente
|
||||
path: /media/daten1/Dokumente
|
||||
read_only: "yes"
|
||||
valid_users:
|
||||
- ghost
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Filme
|
||||
path: /media/daten1/Filme
|
||||
read_only: "yes"
|
||||
@@ -86,6 +103,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Filme2
|
||||
path: /media/datenhdd3/Filme
|
||||
read_only: "yes"
|
||||
@@ -95,6 +114,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Serien
|
||||
path: /media/daten2/Serien
|
||||
read_only: "yes"
|
||||
@@ -115,8 +136,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
force_user: root
|
||||
force_group: root
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Animation
|
||||
path: /media/daten1/Animation
|
||||
read_only: "yes"
|
||||
@@ -126,6 +147,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Anime
|
||||
path: /media/daten3/Anime
|
||||
read_only: "yes"
|
||||
@@ -135,11 +158,17 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Extern
|
||||
path: /media/datenhdd2/extern
|
||||
read_only: "no"
|
||||
valid_users:
|
||||
- ghost
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Musik
|
||||
path: /media/daten1/Musik
|
||||
read_only: "yes"
|
||||
@@ -149,6 +178,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Audiobooks
|
||||
path: /media/daten1/Audiobooks
|
||||
read_only: "yes"
|
||||
@@ -158,6 +189,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Software
|
||||
path: /media/datenhdd3/Software
|
||||
read_only: "yes"
|
||||
@@ -168,6 +201,9 @@ samba_smb_media_shares:
|
||||
write_list:
|
||||
- ghost
|
||||
- daidalaw
|
||||
admin_users:
|
||||
- ghost
|
||||
- daidalaw
|
||||
- name: Downloads
|
||||
path: /media/datenhdd3/Downloads
|
||||
read_only: "no"
|
||||
@@ -175,6 +211,10 @@ samba_smb_media_shares:
|
||||
- ghost
|
||||
- daidalaw
|
||||
- debugofen
|
||||
admin_users:
|
||||
- ghost
|
||||
- daidalaw
|
||||
- debugofen
|
||||
- name: Encode
|
||||
comment: "Encoding-Pipeline: fertige Encodes (Abholung per mv)"
|
||||
path: /media/datenhdd3/Encoding/output
|
||||
@@ -183,10 +223,10 @@ samba_smb_media_shares:
|
||||
- ghost
|
||||
- daidalaw
|
||||
- debugofen
|
||||
admin_users:
|
||||
- ghost
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
force_group: gn-media
|
||||
create_mask: "0664"
|
||||
directory_mask: "0775"
|
||||
@@ -196,10 +236,10 @@ samba_smb_media_shares:
|
||||
read_only: "no"
|
||||
valid_users:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
force_group: gn-media
|
||||
create_mask: "0664"
|
||||
directory_mask: "0775"
|
||||
|
||||
@@ -6,11 +6,13 @@ samba_expected_ipv4: 10.0.0.9
|
||||
# (GNAI-011 section 3.3):
|
||||
samba_expected_ssh_host_key_fingerprint: >-
|
||||
SHA256:+MUO4J4x3TCYLc1iei95UcPTzkPwDPOzovfaIieuOKs
|
||||
# Live values; copy from preflight.yml:
|
||||
samba_expected_processor_vcpus: REPLACE-WITH-PREFLIGHT-VCPUS
|
||||
samba_minimum_memory_mb: REPLACE-WITH-PREFLIGHT-MEMORY-MB
|
||||
# UID of the existing ghost account; copy from audit-production.yml:
|
||||
samba_access_admin_uid: REPLACE-WITH-AUDIT-GHOST-UID
|
||||
# Free UIDs to pick from audit-production.yml (ghost-agent / ansible-deploy):
|
||||
samba_access_agent_uid: REPLACE-WITH-FREE-AGENT-UID
|
||||
samba_access_deploy_uid: REPLACE-WITH-FREE-DEPLOY-UID
|
||||
# Live values (recorded 2026-10-27 from preflight.yml; lxcfs presents the
|
||||
# configured profile inside the guest):
|
||||
samba_expected_processor_vcpus: 1
|
||||
samba_minimum_memory_mb: 2048
|
||||
# UID of the existing ghost account (audit-production.yml):
|
||||
samba_access_admin_uid: 1000
|
||||
# Recorded UIDs (audit-production.yml): ghost-agent exists with 1004;
|
||||
# ansible-deploy takes the lowest free UID >= 1000:
|
||||
samba_access_agent_uid: 1004
|
||||
samba_access_deploy_uid: 1005
|
||||
|
||||
@@ -8,15 +8,16 @@ ansible_ssh_common_args: >-
|
||||
|
||||
samba_expected_distribution: Debian
|
||||
samba_expected_distribution_major_version: "13"
|
||||
# Live hostname of CT 101; copy from preflight.yml (SMB1 is disabled, so the
|
||||
# live server does not answer NetBIOS names):
|
||||
samba_expected_hostname: REPLACE-WITH-PREFLIGHT-HOSTNAME
|
||||
# Live hostname of CT 101 (recorded 2026-10-27 from preflight.yml; SMB1 is
|
||||
# disabled, so the live server does not answer NetBIOS names):
|
||||
samba_expected_hostname: Samba
|
||||
samba_expected_virtualization_type: lxc
|
||||
# Expected Podman version after the dist-upgrade (trixie), analog to CT 100/102:
|
||||
samba_expected_podman_version: "5.4.2"
|
||||
# Resource minimums; copy from preflight.yml:
|
||||
samba_minimum_root_size_bytes: REPLACE-WITH-PREFLIGHT-ROOT-SIZE
|
||||
samba_minimum_root_available_bytes: REPLACE-WITH-PREFLIGHT-ROOT-AVAIL
|
||||
# Resource minimums (recorded 2026-10-27; round values at/below the live
|
||||
# capacity, CT 100/102 convention):
|
||||
samba_minimum_root_size_bytes: 4000000000
|
||||
samba_minimum_root_available_bytes: 1000000000
|
||||
|
||||
samba_firewall_management_ipv4:
|
||||
- 10.0.0.0/24
|
||||
@@ -35,48 +36,64 @@ samba_access_source_networks: 10.0.0.0/24,10.8.0.0/24
|
||||
|
||||
samba_media_group_name: gn-media
|
||||
samba_media_group_gid: 970
|
||||
# Media accounts with their productive UIDs; copy from preflight.yml /
|
||||
# audit-production.yml (fresh-state rebuild: missing accounts are created with
|
||||
# exactly these UIDs; existing accounts are only validated on the UID):
|
||||
# Media accounts with their productive UIDs (recorded 2026-10-27 from
|
||||
# preflight.yml / audit-production.yml; fresh-state rebuild: missing accounts
|
||||
# are created with exactly these UIDs; existing accounts are only validated on
|
||||
# the UID). The legacy account dark2devil (UID 1002) exists on the productive
|
||||
# CT 101 but is deliberately NOT declared: it belongs to the same person as
|
||||
# debugofen (operator clarification 2026-10-28, GNAI-019 decision 11) and is
|
||||
# not referenced by any share in the live smb.conf.
|
||||
samba_media_users:
|
||||
- name: ghost
|
||||
uid: REPLACE-WITH-AUDIT-UID-GHOST
|
||||
uid: 1000
|
||||
shell: /bin/bash
|
||||
home: /home/ghost
|
||||
create_home: true
|
||||
- name: daidalaw
|
||||
uid: REPLACE-WITH-AUDIT-UID-DAIDALAW
|
||||
uid: 1001
|
||||
shell: /usr/sbin/nologin
|
||||
home: /home/daidalaw
|
||||
create_home: false
|
||||
- name: debugofen
|
||||
uid: REPLACE-WITH-AUDIT-UID-DEBUGOFEN
|
||||
uid: 1003
|
||||
shell: /usr/sbin/nologin
|
||||
home: /home/debugofen
|
||||
create_home: false
|
||||
samba_media_group_members:
|
||||
- ghost
|
||||
# Live media mount topology of the productive CT 101 (recorded 2026-10-27):
|
||||
# six Proxmox mount points. /media/datenhdd1 is an empty ext4 directory from
|
||||
# the host root filesystem; the Extern disk is mounted at the subdirectory
|
||||
# /media/datenhdd2/extern (not at /media/datenhdd2 itself).
|
||||
samba_media_mount_points:
|
||||
- /media/daten1
|
||||
- /media/daten2
|
||||
- /media/daten3
|
||||
- /media/datenhdd2
|
||||
- /media/datenhdd1
|
||||
- /media/datenhdd2/extern
|
||||
- /media/datenhdd3
|
||||
|
||||
samba_smb_workgroup: Ghost.net
|
||||
samba_smb_service_units:
|
||||
- smbd.service
|
||||
- nmbd.service
|
||||
# Complete share target state from GNAI-017 section 3 plus [Encode] and
|
||||
# [Encode-In] from GNAI-018 R2. Comments only where the live system shows them
|
||||
# (Debian defaults and the new pipeline shares); the media shares had empty
|
||||
# comments in the anonymous listing and stay without comments.
|
||||
# Complete share target state: the twelve productive shares mirror the live
|
||||
# smb.conf ACLs exactly (valid users / write list / admin users / force
|
||||
# user+group; recorded 2026-10-28, GNAI-018 R4 funktionsgleicher Erhalt), plus
|
||||
# [Encode] and [Encode-In] per GNAI-017 section 4.3 / GNAI-018 R2. Comments
|
||||
# only where the live system shows them (Debian defaults and the new pipeline
|
||||
# shares); the media shares had empty comments in the anonymous listing and
|
||||
# stay without comments.
|
||||
samba_smb_media_shares:
|
||||
- name: Dokumente
|
||||
path: /media/daten1/Dokumente
|
||||
read_only: "yes"
|
||||
valid_users:
|
||||
- ghost
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Filme
|
||||
path: /media/daten1/Filme
|
||||
read_only: "yes"
|
||||
@@ -86,6 +103,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Filme2
|
||||
path: /media/datenhdd3/Filme
|
||||
read_only: "yes"
|
||||
@@ -95,6 +114,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Serien
|
||||
path: /media/daten2/Serien
|
||||
read_only: "yes"
|
||||
@@ -115,8 +136,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
force_user: root
|
||||
force_group: root
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Animation
|
||||
path: /media/daten1/Animation
|
||||
read_only: "yes"
|
||||
@@ -126,6 +147,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Anime
|
||||
path: /media/daten3/Anime
|
||||
read_only: "yes"
|
||||
@@ -135,11 +158,17 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Extern
|
||||
path: /media/datenhdd2/extern
|
||||
read_only: "no"
|
||||
valid_users:
|
||||
- ghost
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Musik
|
||||
path: /media/daten1/Musik
|
||||
read_only: "yes"
|
||||
@@ -149,6 +178,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Audiobooks
|
||||
path: /media/daten1/Audiobooks
|
||||
read_only: "yes"
|
||||
@@ -158,6 +189,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Software
|
||||
path: /media/datenhdd3/Software
|
||||
read_only: "yes"
|
||||
@@ -168,6 +201,9 @@ samba_smb_media_shares:
|
||||
write_list:
|
||||
- ghost
|
||||
- daidalaw
|
||||
admin_users:
|
||||
- ghost
|
||||
- daidalaw
|
||||
- name: Downloads
|
||||
path: /media/datenhdd3/Downloads
|
||||
read_only: "no"
|
||||
@@ -175,6 +211,10 @@ samba_smb_media_shares:
|
||||
- ghost
|
||||
- daidalaw
|
||||
- debugofen
|
||||
admin_users:
|
||||
- ghost
|
||||
- daidalaw
|
||||
- debugofen
|
||||
- name: Encode
|
||||
comment: "Encoding-Pipeline: fertige Encodes (Abholung per mv)"
|
||||
path: /media/datenhdd3/Encoding/output
|
||||
@@ -183,10 +223,10 @@ samba_smb_media_shares:
|
||||
- ghost
|
||||
- daidalaw
|
||||
- debugofen
|
||||
admin_users:
|
||||
- ghost
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
force_group: gn-media
|
||||
create_mask: "0664"
|
||||
directory_mask: "0775"
|
||||
@@ -196,10 +236,10 @@ samba_smb_media_shares:
|
||||
read_only: "no"
|
||||
valid_users:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
force_group: gn-media
|
||||
create_mask: "0664"
|
||||
directory_mask: "0775"
|
||||
|
||||
@@ -6,11 +6,13 @@ samba_expected_ipv4: 10.0.0.9
|
||||
# (GNAI-011 section 3.3):
|
||||
samba_expected_ssh_host_key_fingerprint: >-
|
||||
SHA256:+MUO4J4x3TCYLc1iei95UcPTzkPwDPOzovfaIieuOKs
|
||||
# Live values; copy from preflight.yml:
|
||||
samba_expected_processor_vcpus: REPLACE-WITH-PREFLIGHT-VCPUS
|
||||
samba_minimum_memory_mb: REPLACE-WITH-PREFLIGHT-MEMORY-MB
|
||||
# UID of the existing ghost account; copy from audit-production.yml:
|
||||
samba_access_admin_uid: REPLACE-WITH-AUDIT-GHOST-UID
|
||||
# Free UIDs to pick from audit-production.yml (ghost-agent / ansible-deploy):
|
||||
samba_access_agent_uid: REPLACE-WITH-FREE-AGENT-UID
|
||||
samba_access_deploy_uid: REPLACE-WITH-FREE-DEPLOY-UID
|
||||
# Live values (recorded 2026-10-27 from preflight.yml; lxcfs presents the
|
||||
# configured profile inside the guest):
|
||||
samba_expected_processor_vcpus: 1
|
||||
samba_minimum_memory_mb: 2048
|
||||
# UID of the existing ghost account (audit-production.yml):
|
||||
samba_access_admin_uid: 1000
|
||||
# Recorded UIDs (audit-production.yml): ghost-agent exists with 1004;
|
||||
# ansible-deploy takes the lowest free UID >= 1000:
|
||||
samba_access_agent_uid: 1004
|
||||
samba_access_deploy_uid: 1005
|
||||
|
||||
+63
-23
@@ -8,15 +8,16 @@ ansible_ssh_common_args: >-
|
||||
|
||||
samba_expected_distribution: Debian
|
||||
samba_expected_distribution_major_version: "13"
|
||||
# Live hostname of CT 101; copy from preflight.yml (SMB1 is disabled, so the
|
||||
# live server does not answer NetBIOS names):
|
||||
samba_expected_hostname: REPLACE-WITH-PREFLIGHT-HOSTNAME
|
||||
# Live hostname of CT 101 (recorded 2026-10-27 from preflight.yml; SMB1 is
|
||||
# disabled, so the live server does not answer NetBIOS names):
|
||||
samba_expected_hostname: Samba
|
||||
samba_expected_virtualization_type: lxc
|
||||
# Expected Podman version after the dist-upgrade (trixie), analog to CT 100/102:
|
||||
samba_expected_podman_version: "5.4.2"
|
||||
# Resource minimums; copy from preflight.yml:
|
||||
samba_minimum_root_size_bytes: REPLACE-WITH-PREFLIGHT-ROOT-SIZE
|
||||
samba_minimum_root_available_bytes: REPLACE-WITH-PREFLIGHT-ROOT-AVAIL
|
||||
# Resource minimums (recorded 2026-10-27; round values at/below the live
|
||||
# capacity, CT 100/102 convention):
|
||||
samba_minimum_root_size_bytes: 4000000000
|
||||
samba_minimum_root_available_bytes: 1000000000
|
||||
|
||||
samba_firewall_management_ipv4:
|
||||
- 10.0.0.0/24
|
||||
@@ -35,48 +36,64 @@ samba_access_source_networks: 10.0.0.0/24,10.8.0.0/24
|
||||
|
||||
samba_media_group_name: gn-media
|
||||
samba_media_group_gid: 970
|
||||
# Media accounts with their productive UIDs; copy from preflight.yml /
|
||||
# audit-production.yml (fresh-state rebuild: missing accounts are created with
|
||||
# exactly these UIDs; existing accounts are only validated on the UID):
|
||||
# Media accounts with their productive UIDs (recorded 2026-10-27 from
|
||||
# preflight.yml / audit-production.yml; fresh-state rebuild: missing accounts
|
||||
# are created with exactly these UIDs; existing accounts are only validated on
|
||||
# the UID). The legacy account dark2devil (UID 1002) exists on the productive
|
||||
# CT 101 but is deliberately NOT declared: it belongs to the same person as
|
||||
# debugofen (operator clarification 2026-10-28, GNAI-019 decision 11) and is
|
||||
# not referenced by any share in the live smb.conf.
|
||||
samba_media_users:
|
||||
- name: ghost
|
||||
uid: REPLACE-WITH-AUDIT-UID-GHOST
|
||||
uid: 1000
|
||||
shell: /bin/bash
|
||||
home: /home/ghost
|
||||
create_home: true
|
||||
- name: daidalaw
|
||||
uid: REPLACE-WITH-AUDIT-UID-DAIDALAW
|
||||
uid: 1001
|
||||
shell: /usr/sbin/nologin
|
||||
home: /home/daidalaw
|
||||
create_home: false
|
||||
- name: debugofen
|
||||
uid: REPLACE-WITH-AUDIT-UID-DEBUGOFEN
|
||||
uid: 1003
|
||||
shell: /usr/sbin/nologin
|
||||
home: /home/debugofen
|
||||
create_home: false
|
||||
samba_media_group_members:
|
||||
- ghost
|
||||
# Live media mount topology of the productive CT 101 (recorded 2026-10-27):
|
||||
# six Proxmox mount points. /media/datenhdd1 is an empty ext4 directory from
|
||||
# the host root filesystem; the Extern disk is mounted at the subdirectory
|
||||
# /media/datenhdd2/extern (not at /media/datenhdd2 itself).
|
||||
samba_media_mount_points:
|
||||
- /media/daten1
|
||||
- /media/daten2
|
||||
- /media/daten3
|
||||
- /media/datenhdd2
|
||||
- /media/datenhdd1
|
||||
- /media/datenhdd2/extern
|
||||
- /media/datenhdd3
|
||||
|
||||
samba_smb_workgroup: Ghost.net
|
||||
samba_smb_service_units:
|
||||
- smbd.service
|
||||
- nmbd.service
|
||||
# Complete share target state from GNAI-017 section 3 plus [Encode] and
|
||||
# [Encode-In] from GNAI-018 R2. Comments only where the live system shows them
|
||||
# (Debian defaults and the new pipeline shares); the media shares had empty
|
||||
# comments in the anonymous listing and stay without comments.
|
||||
# Complete share target state: the twelve productive shares mirror the live
|
||||
# smb.conf ACLs exactly (valid users / write list / admin users / force
|
||||
# user+group; recorded 2026-10-28, GNAI-018 R4 funktionsgleicher Erhalt), plus
|
||||
# [Encode] and [Encode-In] per GNAI-017 section 4.3 / GNAI-018 R2. Comments
|
||||
# only where the live system shows them (Debian defaults and the new pipeline
|
||||
# shares); the media shares had empty comments in the anonymous listing and
|
||||
# stay without comments.
|
||||
samba_smb_media_shares:
|
||||
- name: Dokumente
|
||||
path: /media/daten1/Dokumente
|
||||
read_only: "yes"
|
||||
valid_users:
|
||||
- ghost
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Filme
|
||||
path: /media/daten1/Filme
|
||||
read_only: "yes"
|
||||
@@ -86,6 +103,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Filme2
|
||||
path: /media/datenhdd3/Filme
|
||||
read_only: "yes"
|
||||
@@ -95,6 +114,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Serien
|
||||
path: /media/daten2/Serien
|
||||
read_only: "yes"
|
||||
@@ -115,8 +136,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
force_user: root
|
||||
force_group: root
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Animation
|
||||
path: /media/daten1/Animation
|
||||
read_only: "yes"
|
||||
@@ -126,6 +147,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Anime
|
||||
path: /media/daten3/Anime
|
||||
read_only: "yes"
|
||||
@@ -135,11 +158,17 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Extern
|
||||
path: /media/datenhdd2/extern
|
||||
read_only: "no"
|
||||
valid_users:
|
||||
- ghost
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Musik
|
||||
path: /media/daten1/Musik
|
||||
read_only: "yes"
|
||||
@@ -149,6 +178,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Audiobooks
|
||||
path: /media/daten1/Audiobooks
|
||||
read_only: "yes"
|
||||
@@ -158,6 +189,8 @@ samba_smb_media_shares:
|
||||
- debugofen
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
- name: Software
|
||||
path: /media/datenhdd3/Software
|
||||
read_only: "yes"
|
||||
@@ -168,6 +201,9 @@ samba_smb_media_shares:
|
||||
write_list:
|
||||
- ghost
|
||||
- daidalaw
|
||||
admin_users:
|
||||
- ghost
|
||||
- daidalaw
|
||||
- name: Downloads
|
||||
path: /media/datenhdd3/Downloads
|
||||
read_only: "no"
|
||||
@@ -175,6 +211,10 @@ samba_smb_media_shares:
|
||||
- ghost
|
||||
- daidalaw
|
||||
- debugofen
|
||||
admin_users:
|
||||
- ghost
|
||||
- daidalaw
|
||||
- debugofen
|
||||
- name: Encode
|
||||
comment: "Encoding-Pipeline: fertige Encodes (Abholung per mv)"
|
||||
path: /media/datenhdd3/Encoding/output
|
||||
@@ -183,10 +223,10 @@ samba_smb_media_shares:
|
||||
- ghost
|
||||
- daidalaw
|
||||
- debugofen
|
||||
admin_users:
|
||||
- ghost
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
force_group: gn-media
|
||||
create_mask: "0664"
|
||||
directory_mask: "0775"
|
||||
@@ -196,10 +236,10 @@ samba_smb_media_shares:
|
||||
read_only: "no"
|
||||
valid_users:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
write_list:
|
||||
- ghost
|
||||
admin_users:
|
||||
- ghost
|
||||
force_group: gn-media
|
||||
create_mask: "0664"
|
||||
directory_mask: "0775"
|
||||
|
||||
@@ -6,11 +6,13 @@ samba_expected_ipv4: 10.0.0.9
|
||||
# (GNAI-011 section 3.3):
|
||||
samba_expected_ssh_host_key_fingerprint: >-
|
||||
SHA256:+MUO4J4x3TCYLc1iei95UcPTzkPwDPOzovfaIieuOKs
|
||||
# Live values; copy from preflight.yml:
|
||||
samba_expected_processor_vcpus: REPLACE-WITH-PREFLIGHT-VCPUS
|
||||
samba_minimum_memory_mb: REPLACE-WITH-PREFLIGHT-MEMORY-MB
|
||||
# UID of the existing ghost account; copy from audit-production.yml:
|
||||
samba_access_admin_uid: REPLACE-WITH-AUDIT-GHOST-UID
|
||||
# Free UIDs to pick from audit-production.yml (ghost-agent / ansible-deploy):
|
||||
samba_access_agent_uid: REPLACE-WITH-FREE-AGENT-UID
|
||||
samba_access_deploy_uid: REPLACE-WITH-FREE-DEPLOY-UID
|
||||
# Live values (recorded 2026-10-27 from preflight.yml; lxcfs presents the
|
||||
# configured profile inside the guest):
|
||||
samba_expected_processor_vcpus: 1
|
||||
samba_minimum_memory_mb: 2048
|
||||
# UID of the existing ghost account (audit-production.yml):
|
||||
samba_access_admin_uid: 1000
|
||||
# Recorded UIDs (audit-production.yml): ghost-agent exists with 1004;
|
||||
# ansible-deploy takes the lowest free UID >= 1000:
|
||||
samba_access_agent_uid: 1004
|
||||
samba_access_deploy_uid: 1005
|
||||
|
||||
@@ -107,8 +107,9 @@
|
||||
samba_media_users | map(attribute='name') | list is
|
||||
subset(samba_audit_pdbedit.stdout_lines)
|
||||
fail_msg: >-
|
||||
The productive SMB users ghost, daidalaw and debugofen are missing
|
||||
from the passdb. Stop the adoption; the passdb must not be at risk.
|
||||
The productive SMB users ghost, daidalaw and debugofen
|
||||
are missing from the passdb. Stop the adoption; the passdb must not
|
||||
be at risk.
|
||||
|
||||
- name: Validate the effective SSH policy
|
||||
ansible.builtin.command:
|
||||
@@ -197,10 +198,7 @@
|
||||
- "{{ item }}"
|
||||
check_mode: false
|
||||
changed_when: false
|
||||
loop:
|
||||
- ghost
|
||||
- daidalaw
|
||||
- debugofen
|
||||
loop: "{{ samba_media_users | map(attribute='name') | list }}"
|
||||
register: samba_audit_password_states
|
||||
|
||||
- name: Read the complete account database for UID slot picking
|
||||
@@ -224,10 +222,7 @@
|
||||
- name: Stat the media account authorized keys
|
||||
ansible.builtin.stat:
|
||||
path: "/home/{{ item }}/.ssh/authorized_keys"
|
||||
loop:
|
||||
- ghost
|
||||
- daidalaw
|
||||
- debugofen
|
||||
loop: "{{ samba_media_users | map(attribute='name') | list }}"
|
||||
register: samba_audit_keys_stats
|
||||
|
||||
- name: Read the existing authorized keys
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
- hardware
|
||||
- network
|
||||
- virtual
|
||||
- mounts
|
||||
|
||||
tasks:
|
||||
- name: Verify required inventory safeguards are defined
|
||||
@@ -57,6 +58,32 @@
|
||||
- ansible_facts["hostname"] == samba_expected_hostname
|
||||
when: samba_expected_hostname is not match('^REPLACE-')
|
||||
|
||||
- name: Read the effective CPU allocation (nproc reflects the configured cores)
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- /usr/bin/nproc
|
||||
check_mode: false
|
||||
changed_when: false
|
||||
register: samba_preflight_nproc
|
||||
|
||||
- name: Verify the declared CPU allocation when the placeholder is already replaced
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- samba_preflight_nproc.stdout | int == samba_expected_processor_vcpus | int
|
||||
fail_msg: >-
|
||||
The guest reports {{ samba_preflight_nproc.stdout }} CPUs, but the
|
||||
inventory declares {{ samba_expected_processor_vcpus }} vCPUs.
|
||||
when: samba_expected_processor_vcpus is not match('^REPLACE-')
|
||||
|
||||
- name: Verify the declared memory minimum when the placeholder is already replaced
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- ansible_facts["memtotal_mb"] | int >= samba_minimum_memory_mb | int
|
||||
fail_msg: >-
|
||||
The guest reports {{ ansible_facts["memtotal_mb"] }} MiB RAM, below
|
||||
the declared minimum {{ samba_minimum_memory_mb }} MiB.
|
||||
when: samba_minimum_memory_mb is not match('^REPLACE-')
|
||||
|
||||
- name: Read the guest user-namespace ID mapping
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
@@ -182,6 +209,18 @@
|
||||
The pre-migration listener set is unexpected: SSH and SMB must be
|
||||
served and NFS (2049) must not be active yet.
|
||||
|
||||
- name: Verify the declared media mount points are mounted
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- >-
|
||||
ansible_facts["mounts"] | map(attribute="mount") | list is
|
||||
superset(samba_media_mount_points)
|
||||
fail_msg: >-
|
||||
Not all declared media mount points are mounted on CT 101. The Samba
|
||||
shares and the NFS export depend on the complete media library; stop
|
||||
the adoption until the storage topology is complete.
|
||||
success_msg: All declared media mount points are mounted.
|
||||
|
||||
- name: Read the Samba server version
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
@@ -200,7 +239,7 @@
|
||||
changed_when: false
|
||||
register: samba_preflight_smb_conf
|
||||
|
||||
- name: Read the live anonymous Samba share listing
|
||||
- name: Read the live anonymous Samba share listing (smbclient is installed by samba_smb during convergence)
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- /usr/bin/smbclient
|
||||
@@ -209,6 +248,7 @@
|
||||
- -N
|
||||
check_mode: false
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
register: samba_preflight_shares
|
||||
|
||||
- name: Read the media account entries
|
||||
@@ -237,7 +277,7 @@
|
||||
label: "{{ item.name }}"
|
||||
register: samba_preflight_media_uids
|
||||
|
||||
- name: Read the media group entry for the inventory placeholder
|
||||
- name: Read the media group entry (created by samba_media during convergence)
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- /usr/bin/getent
|
||||
@@ -245,6 +285,7 @@
|
||||
- "{{ samba_media_group_name }}"
|
||||
check_mode: false
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
register: samba_preflight_media_group
|
||||
|
||||
- name: Read the complete account database for UID slot picking
|
||||
@@ -279,6 +320,23 @@
|
||||
changed_when: false
|
||||
register: samba_preflight_root_capacity
|
||||
|
||||
- name: Verify the declared root filesystem minimums when the placeholders are replaced
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- >-
|
||||
samba_preflight_root_capacity.stdout.split()[0] | int >=
|
||||
samba_minimum_root_size_bytes | int
|
||||
- >-
|
||||
samba_preflight_root_capacity.stdout.split()[1] | int >=
|
||||
samba_minimum_root_available_bytes | int
|
||||
fail_msg: >-
|
||||
The root filesystem does not meet the declared minimums
|
||||
({{ samba_minimum_root_size_bytes }} bytes size,
|
||||
{{ samba_minimum_root_available_bytes }} bytes available).
|
||||
when:
|
||||
- samba_minimum_root_size_bytes is not match('^REPLACE-')
|
||||
- samba_minimum_root_available_bytes is not match('^REPLACE-')
|
||||
|
||||
- name: Read the media mount capacities
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
@@ -354,6 +412,7 @@
|
||||
{{ ansible_facts['virtualization_type'] }}
|
||||
{{ ansible_facts['virtualization_role'] }}
|
||||
host_visible_processor_vcpus: "{{ ansible_facts['processor_vcpus'] }}"
|
||||
configured_vcpus_nproc: "{{ samba_preflight_nproc.stdout }}"
|
||||
memory_mib: "{{ ansible_facts['memtotal_mb'] }}"
|
||||
cgroup_cpu_max: "{{ samba_preflight_cpu_max.stdout }}"
|
||||
cgroup_memory_max: "{{ samba_preflight_memory_max.stdout }}"
|
||||
@@ -367,7 +426,10 @@
|
||||
map(attribute='stdout') | list }}
|
||||
samba_version: "{{ samba_preflight_samba_version.stdout }}"
|
||||
smb_conf_sha256: "{{ samba_preflight_smb_conf.stdout.split()[0] }}"
|
||||
smb_share_listing: "{{ samba_preflight_shares.stdout }}"
|
||||
smb_share_listing: >-
|
||||
{{ samba_preflight_shares.stdout
|
||||
if samba_preflight_shares.rc == 0 else
|
||||
'smbclient not installed yet (samba_smb installs it during convergence)' }}
|
||||
media_accounts: >-
|
||||
{{ samba_preflight_media_accounts.results |
|
||||
map(attribute='stdout') | list }}
|
||||
@@ -376,7 +438,10 @@
|
||||
map(attribute='item.name') |
|
||||
zip(samba_preflight_media_uids.results | map(attribute='stdout')) |
|
||||
list }}
|
||||
media_group: "{{ samba_preflight_media_group.stdout }}"
|
||||
media_group: >-
|
||||
{{ samba_preflight_media_group.stdout
|
||||
if samba_preflight_media_group.rc == 0 else
|
||||
'missing (samba_media creates it during convergence)' }}
|
||||
agent_uid: "{{ samba_preflight_agent_uid.stdout }}"
|
||||
all_accounts: "{{ samba_preflight_all_accounts.stdout }}"
|
||||
all_groups: "{{ samba_preflight_all_groups.stdout }}"
|
||||
@@ -387,14 +452,14 @@
|
||||
{{ samba_expected_ssh_host_key_fingerprint }}
|
||||
placeholder_sources: >-
|
||||
samba_expected_hostname=hostname,
|
||||
samba_expected_processor_vcpus=host_visible_processor_vcpus,
|
||||
samba_expected_processor_vcpus=configured_vcpus_nproc (nproc; configured cores),
|
||||
samba_minimum_memory_mb=memory_mib,
|
||||
samba_minimum_root_size_bytes=root_size_bytes,
|
||||
samba_minimum_root_available_bytes=root_available_bytes,
|
||||
samba_minimum_root_size_bytes=round minimum at/below root_size_bytes,
|
||||
samba_minimum_root_available_bytes=round minimum at/below root_available_bytes,
|
||||
samba_access_admin_uid=UID of ghost in media_accounts,
|
||||
samba_access_agent_uid=agent_uid,
|
||||
samba_access_deploy_uid=free UID from all_accounts,
|
||||
samba_media_users[ghost].uid=uid of ghost in media_user_uids,
|
||||
samba_media_users[daidalaw].uid=uid of daidalaw in media_user_uids,
|
||||
samba_media_users[debugofen].uid=uid of debugofen in media_user_uids,
|
||||
samba_media_group_gid=gid of gn-media in media_group
|
||||
samba_media_group_gid=recorded 970 (GID slot free; samba_media creates the group)
|
||||
|
||||
@@ -235,7 +235,7 @@
|
||||
- /usr/bin/findmnt
|
||||
- --noheadings
|
||||
- --output
|
||||
- SOURCE,FSTYPE,OPTIONS
|
||||
- TARGET,SOURCE,FSTYPE,OPTIONS
|
||||
- --target
|
||||
- "{{ item }}"
|
||||
check_mode: false
|
||||
@@ -245,11 +245,17 @@
|
||||
label: "{{ item }}"
|
||||
register: samba_production_mounts
|
||||
|
||||
- name: Require every declared media mount to be mounted
|
||||
- name: Require every declared media mount to be mounted at its declared path
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- samba_production_mounts.results | map(attribute='rc') | unique | list == [0]
|
||||
fail_msg: Not all declared media mount points are mounted.
|
||||
- item.rc == 0
|
||||
- item.stdout.split()[0] == item.item
|
||||
fail_msg: >-
|
||||
{{ item.item }} is not a mount point; findmnt resolved it to
|
||||
{{ item.stdout.split()[0] }}.
|
||||
loop: "{{ samba_production_mounts.results }}"
|
||||
loop_control:
|
||||
label: "{{ item.item }}"
|
||||
|
||||
- name: Read the declared media accounts
|
||||
ansible.builtin.command:
|
||||
@@ -381,9 +387,9 @@
|
||||
samba_media_users | map(attribute='name') | list is
|
||||
subset(samba_production_pdbedit.stdout_lines)
|
||||
fail_msg: >-
|
||||
The productive SMB users ghost, daidalaw and debugofen are missing
|
||||
from the passdb (GNAI-018 R5). On a fresh-state rebuild, set them
|
||||
with smbpasswd -a <user> after the first convergence.
|
||||
The productive SMB users ghost, daidalaw and debugofen
|
||||
are missing from the passdb (GNAI-018 R5). On a fresh-state rebuild,
|
||||
set them with smbpasswd -a <user> after the first convergence.
|
||||
|
||||
- name: Read the anonymous Samba share listing
|
||||
ansible.builtin.command:
|
||||
|
||||
@@ -3,17 +3,17 @@ samba_access_source_networks: 10.0.0.0/24,10.8.0.0/24
|
||||
samba_access_public_key_root: "{{ playbook_dir }}/../files/ssh"
|
||||
|
||||
samba_access_agent_user: ghost-agent
|
||||
samba_access_agent_uid: 1000
|
||||
samba_access_agent_uid: 1004
|
||||
samba_access_agent_public_key_file: >-
|
||||
{{ samba_access_public_key_root }}/samba-ghost-agent.pub
|
||||
|
||||
samba_access_admin_user: ghost
|
||||
samba_access_admin_uid: 1001
|
||||
samba_access_admin_uid: 1000
|
||||
samba_access_admin_public_key_file: >-
|
||||
{{ samba_access_public_key_root }}/samba-ghost.pub
|
||||
|
||||
samba_access_deploy_user: ansible-deploy
|
||||
samba_access_deploy_uid: 1002
|
||||
samba_access_deploy_uid: 1005
|
||||
samba_access_deploy_public_key_file: >-
|
||||
{{ samba_access_public_key_root }}/samba-ansible-deploy.pub
|
||||
|
||||
@@ -22,6 +22,7 @@ samba_access_sudoers_file: /etc/sudoers.d/90-ghostnet-ansible-deploy
|
||||
|
||||
# CT 101 is an adopted legacy LXC: the personal administrator account ghost
|
||||
# already exists with its productive UID and is only validated here, never
|
||||
# recreated. ghost-agent and ansible-deploy are created with fixed UIDs that
|
||||
# the operator picks from the audit output because the media accounts
|
||||
# ghost/daidalaw/debugofen already occupy the low UID range.
|
||||
# recreated. ghost-agent (1004) and ansible-deploy (1005) are created with
|
||||
# fixed UIDs because the existing accounts ghost/daidalaw/dark2devil/
|
||||
# debugofen already occupy the low UID range (recorded 2026-10-27; the
|
||||
# inventory host_vars carry the same values).
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
# `samba_lxc_baseline`
|
||||
|
||||
Declaratively manages the CT 101 Samba LXC baseline: guest identity
|
||||
(hostname, Debian 13, `10.0.0.9`, LXC guest, systemd), the unprivileged
|
||||
(hostname `Samba`, Debian 13, `10.0.0.9`, LXC guest, systemd), the unprivileged
|
||||
ID-mapping premise, baseline administration packages, the `Europe/Berlin`
|
||||
timezone and the protected Ghostnet configuration/data/backup directories.
|
||||
It also masks `sys-kernel-config.mount` (configfs is unavailable in
|
||||
unprivileged LXC; CT 100/102/103 convention) and clears a stale failed state,
|
||||
so the no-failed-units gate of `playbooks/preflight.yml` holds.
|
||||
|
||||
The role refuses to run while the inventory still contains
|
||||
`REPLACE-WITH-*` placeholders; `playbooks/preflight.yml` on the `agent`
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
samba_lxc_baseline_expected_hostname: samba
|
||||
samba_lxc_baseline_expected_hostname: Samba
|
||||
samba_lxc_baseline_expected_distribution: Debian
|
||||
samba_lxc_baseline_expected_distribution_major_version: "13"
|
||||
samba_lxc_baseline_expected_ipv4: 10.0.0.9
|
||||
|
||||
@@ -56,6 +56,34 @@
|
||||
(GNAI-019) depends on the standard Proxmox ID mapping; a privileged
|
||||
conversion changes the UID/GID semantics of the media library.
|
||||
|
||||
- name: Mask the configfs mount unit (configfs is unavailable in unprivileged LXC)
|
||||
ansible.builtin.systemd_service:
|
||||
name: sys-kernel-config.mount
|
||||
masked: true
|
||||
register: samba_lxc_baseline_configfs_mask
|
||||
|
||||
- name: Probe the configfs mount unit failure state
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- /usr/bin/systemctl
|
||||
- is-failed
|
||||
- sys-kernel-config.mount
|
||||
check_mode: false
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
register: samba_lxc_baseline_configfs_failed
|
||||
|
||||
- name: Clear a stale failed state of the configfs mount unit
|
||||
ansible.builtin.command:
|
||||
argv:
|
||||
- /usr/bin/systemctl
|
||||
- reset-failed
|
||||
- sys-kernel-config.mount
|
||||
when: >-
|
||||
not ansible_check_mode and
|
||||
(samba_lxc_baseline_configfs_mask.changed or
|
||||
samba_lxc_baseline_configfs_failed.rc == 0)
|
||||
|
||||
- name: Install baseline administration packages
|
||||
ansible.builtin.apt:
|
||||
name: "{{ samba_lxc_baseline_packages }}"
|
||||
|
||||
@@ -4,12 +4,13 @@ Declaratively manages the CT 101 media prerequisites for the Samba shares and
|
||||
the NFS export (GNAI-018 R1/R3):
|
||||
|
||||
- Verifies that all declared media mount points (`/media/daten1`,
|
||||
`/media/daten2`, `/media/daten3`, `/media/datenhdd2`, `/media/datenhdd3`)
|
||||
are actually mounted. Mount facts are gathered on demand when the playbook
|
||||
fact subset omits them.
|
||||
- Validates the productive media accounts `ghost`, `daidalaw` and `debugofen`
|
||||
against their recorded UIDs (`samba_media_users`; the `REPLACE-WITH-*` UID
|
||||
placeholders fail closed in the argument spec before any task runs).
|
||||
`/media/daten2`, `/media/daten3`, `/media/datenhdd1`,
|
||||
`/media/datenhdd2/extern`, `/media/datenhdd3`) are actually mounted. Mount
|
||||
facts are gathered on demand when the playbook fact subset omits them.
|
||||
- Validates the productive media accounts `ghost`, `daidalaw`
|
||||
and `debugofen` against their recorded UIDs (`samba_media_users`; the
|
||||
`REPLACE-WITH-*` UID placeholders fail closed in the argument spec before
|
||||
any task runs).
|
||||
Existing accounts are only validated, never modified. On a fresh-state
|
||||
rebuild, missing accounts are created with exactly the declared UIDs
|
||||
(primary group `gid=uid`, `password_lock: true`; shell/home/create_home come
|
||||
@@ -18,10 +19,11 @@ the NFS export (GNAI-018 R1/R3):
|
||||
- Creates the group `gn-media` with the pipeline GID **970** — the numeric
|
||||
identity must match `ghostnet-ki` (GNENC-002). The role fails closed when
|
||||
the GID slot or the group name is occupied by a different identity.
|
||||
- Adds `ghost` to `gn-media` (required for the `mv` pickup from `[Encode]` and
|
||||
the `.dlc` drop into `[Encode-In]`, because the pipeline directories carry
|
||||
group `gn-media` with mode 2770). `daidalaw`/`debugofen` deliberately get no
|
||||
membership (read-only world access is sufficient, GNAI-018 R3).
|
||||
- Adds `ghost` to `gn-media` (required for the `mv` pickup
|
||||
from `[Encode]` and the `.dlc` drop into `[Encode-In]`, because the pipeline
|
||||
directories carry group `gn-media` with mode 2770; GNAI-018 R3).
|
||||
`daidalaw`/`debugofen` deliberately get no membership (read-only world
|
||||
access is sufficient).
|
||||
|
||||
Post-state verification (converged group entry, effective memberships) runs
|
||||
on real executions and on check-mode reruns of an already converged host;
|
||||
|
||||
@@ -5,7 +5,8 @@ samba_media_group_gid: 970
|
||||
# audit-production.yml). shell/home/create_home are only used when creating
|
||||
# missing accounts (fresh-state rebuild); existing accounts are only validated
|
||||
# on the UID and never modified. The UID placeholders stop the role
|
||||
# validation fail-closed until the live values are entered.
|
||||
# validation fail-closed until the live values are entered. The legacy account
|
||||
# dark2devil (UID 1002) is deliberately not declared (GNAI-019 decision 11).
|
||||
samba_media_users:
|
||||
- name: ghost
|
||||
uid: REPLACE-WITH-AUDIT-UID-GHOST
|
||||
@@ -24,9 +25,12 @@ samba_media_users:
|
||||
create_home: false
|
||||
samba_media_group_members:
|
||||
- ghost
|
||||
# Live media mount topology of the productive CT 101 (recorded 2026-10-27):
|
||||
# six Proxmox mount points; the Extern disk is mounted at /media/datenhdd2/extern.
|
||||
samba_media_mount_points:
|
||||
- /media/daten1
|
||||
- /media/daten2
|
||||
- /media/daten3
|
||||
- /media/datenhdd2
|
||||
- /media/datenhdd1
|
||||
- /media/datenhdd2/extern
|
||||
- /media/datenhdd3
|
||||
|
||||
@@ -7,7 +7,8 @@ decision 1: Debian package, no container — see there for the rationale).
|
||||
`samba_smb_preserve_passdb: true`, `/var/lib/samba/private/passdb.tdb` must
|
||||
exist before anything converges, the `pdbedit -L` user list is read before
|
||||
and after the convergence and must be identical, and the productive users
|
||||
`ghost`, `daidalaw`, `debugofen` must be present. On a fresh-state rebuild
|
||||
`ghost`, `daidalaw`, `debugofen` must be present. On a
|
||||
fresh-state rebuild
|
||||
the first `site.yml` run passes `-e samba_smb_preserve_passdb=false` (no
|
||||
passdb exists yet); the operator then sets the SMB passwords interactively
|
||||
(`smbpasswd -a`), and the second run validates the populated passdb with the
|
||||
|
||||
@@ -114,7 +114,8 @@
|
||||
subset(samba_smb_passdb_after.stdout_lines)
|
||||
fail_msg: >-
|
||||
The Samba user database changed during convergence. The productive
|
||||
users ghost, daidalaw and debugofen must be preserved (GNAI-018 R5).
|
||||
users ghost, daidalaw and debugofen must be preserved
|
||||
(GNAI-018 R5).
|
||||
when: samba_smb_preserve_passdb | bool
|
||||
|
||||
- name: Read the anonymous Samba share listing
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
[printers]
|
||||
comment = All Printers
|
||||
browseable = no
|
||||
path = /var/tmp
|
||||
printable = yes
|
||||
guest ok = no
|
||||
|
||||
@@ -14,7 +14,7 @@ Upgrades the productive CT 101 from Debian 12 (bookworm) to Debian 13
|
||||
productive `smb.conf` survive the upgrade (`--force-confold` keeps the
|
||||
productive `smb.conf`). Sequence:
|
||||
|
||||
1. Preflight: CT 101 is running, is unprivileged (GNAI-015), all five media
|
||||
1. Preflight: CT 101 is running, is unprivileged (GNAI-015), all six media
|
||||
mounts carry `backup=no` (otherwise `vzdump` would archive the media
|
||||
library), and in the guest Debian 12, `ssh`/`smbd`/`nmbd` are active and the
|
||||
IPv4 matches.
|
||||
@@ -29,7 +29,7 @@ productive `smb.conf`). Sequence:
|
||||
`wtmpdb-rotate.timer` cleanup rule from `ghostnet-lxc-baseline.sh`.
|
||||
5. Reboot and post-verify: Debian 13, `ssh`/`smbd`/`nmbd` active, no failed
|
||||
units, listeners 22/139/445, anonymous `smbclient -L` query successful,
|
||||
unprivileged uid_map intact, seccomp filter disabled, all five media
|
||||
unprivileged uid_map intact, seccomp filter disabled, all six media
|
||||
mounts mounted.
|
||||
|
||||
Before the run, all media mounts in the productive `pct config 101` must carry
|
||||
@@ -51,32 +51,35 @@ file-server service; the host key is unchanged, so the workstation does not
|
||||
have to replace a known host key.
|
||||
|
||||
The reviewed repository copy has SHA-256
|
||||
`f7adfbde7378708620975a64c30bb3de8727b96915ad8c58100893a52c2c2d6e`.
|
||||
`99f34cd991143d7d11dc1f64a49d29e966dee9db23737d081b06b67c1e409aac`.
|
||||
|
||||
## `provision-ct101-samba.sh` (fresh-state rebuild)
|
||||
|
||||
Creates a fresh CT 101 from a Debian 13 template with the recorded profile,
|
||||
attaches the five media mounts, disables the LXC seccomp filter and then runs
|
||||
the reviewed baseline hook with the recorded account UIDs. The script refuses
|
||||
to run when CT 101 already exists, and it names every material setting
|
||||
explicitly.
|
||||
attaches the six media mounts, disables the LXC seccomp filter and then runs
|
||||
the reviewed baseline hook with the recorded account UIDs. After the hook it
|
||||
masks `sys-kernel-config.mount` (configfs is unavailable in unprivileged LXC;
|
||||
CT 100/102/103 convention) and clears a stale failed state, so the fresh CT
|
||||
passes the no-failed-units gate of `playbooks/preflight.yml`. The script
|
||||
refuses to run when CT 101 already exists, and it names every material
|
||||
setting explicitly.
|
||||
|
||||
| Setting | Value |
|
||||
| --- | --- |
|
||||
| CT ID / hostname | `101` / `samba` (overridable via `GHOSTNET_CT101_HOSTNAME`) |
|
||||
| CT ID / hostname | `101` / `Samba` (overridable via `GHOSTNET_CT101_HOSTNAME`) |
|
||||
| OS | Debian 13, amd64 (newest `debian-13-*amd64*` template in the local cache, otherwise `GHOSTNET_OS_TEMPLATE`) |
|
||||
| Container type | unprivileged LXC with `nesting=1,keyctl=1` |
|
||||
| CPU / RAM / swap | 2 cores / 2048 MiB / 1024 MiB (adjustable via env) |
|
||||
| Rootfs | 32 GiB on `local-lvm` (adjustable via env) |
|
||||
| CPU / RAM / swap | 1 core / 2048 MiB / 2048 MiB (recorded profile, adjustable via env) |
|
||||
| Rootfs | 4 GiB on `local-lvm` (recorded profile, adjustable via env) |
|
||||
| Network | `vmbr0`, `10.0.0.9/24`, gateway `10.0.0.1`, DNS `10.0.0.14`, no IPv6 |
|
||||
| Boot / timezone | `onboot: 1`, `Europe/Berlin` |
|
||||
| Seccomp | empty `lxc.seccomp.profile:` (Ganesha `open_by_handle_at`) |
|
||||
| Media mounts | `mp0`–`mp4` → `/media/daten1`, `/media/daten2`, `/media/daten3`, `/media/datenhdd2`, `/media/datenhdd3`, each with `backup=no` |
|
||||
| Media mounts | `mp0`–`mp5` → `/media/daten1`, `/media/daten2`, `/media/daten3`, `/media/datenhdd1`, `/media/datenhdd2/extern`, `/media/datenhdd3`, each with `backup=no` |
|
||||
| Baseline hook | `/usr/local/sbin/ghostnet-lxc-baseline.sh` (SHA-256 pinned) |
|
||||
|
||||
The resource defaults are conservative starting values; for an exact rebuild of
|
||||
the productive profile, set the values from `pct config 101` of the productive
|
||||
CT 101 via the env variables.
|
||||
The resource defaults are the recorded productive profile (captured 2026-10-27
|
||||
inside the guest via lxcfs/cgroup and `findmnt`); override them via the env
|
||||
variables only deliberately.
|
||||
|
||||
Mandatory environment variables (the recorded values from the Ansible inventory
|
||||
or the productive `pct config 101`):
|
||||
@@ -85,7 +88,7 @@ or the productive `pct config 101`):
|
||||
| --- | --- |
|
||||
| `GHOSTNET_AGENT_UID` | UID of `ghost-agent` (must match `samba_access_agent_uid`) |
|
||||
| `GHOSTNET_ADMIN_UID` | UID of `ghost` (must match `samba_access_admin_uid`) |
|
||||
| `GHOSTNET_MP0_HOST` … `GHOSTNET_MP4_HOST` | Host paths of the five media mounts (must exist) |
|
||||
| `GHOSTNET_MP0_HOST` … `GHOSTNET_MP5_HOST` | Host paths of the six media mounts (must exist) |
|
||||
|
||||
Optional variables: `GHOSTNET_CT101_HOSTNAME`, `GHOSTNET_CT101_CORES`,
|
||||
`GHOSTNET_CT101_MEMORY_MB`, `GHOSTNET_CT101_ROOTFS_GB`, `GHOSTNET_CT101_SWAP_MB`,
|
||||
@@ -100,8 +103,8 @@ install -o root -g root -m 0700 \
|
||||
|
||||
GHOSTNET_AGENT_UID=<uid> GHOSTNET_ADMIN_UID=<uid> \
|
||||
GHOSTNET_MP0_HOST=/path/daten1 GHOSTNET_MP1_HOST=/path/daten2 \
|
||||
GHOSTNET_MP2_HOST=/path/daten3 GHOSTNET_MP3_HOST=/path/datenhdd2 \
|
||||
GHOSTNET_MP4_HOST=/path/datenhdd3 \
|
||||
GHOSTNET_MP2_HOST=/path/daten3 GHOSTNET_MP3_HOST=/path/datenhdd1 \
|
||||
GHOSTNET_MP4_HOST=/path/datenhdd2-extern GHOSTNET_MP5_HOST=/path/datenhdd3 \
|
||||
/usr/local/sbin/provision-ct101-samba.sh
|
||||
```
|
||||
|
||||
@@ -112,7 +115,7 @@ steps (set the ghost password, install the public keys from
|
||||
placeholders, rebuild sequence from `ansible/README.md`).
|
||||
|
||||
The reviewed repository copy has SHA-256
|
||||
`ac5d613fb3c3526135c96f02efff9fd7d8dc01952e3d4701b9b5a4a511fff1cd`.
|
||||
`f40f3da836d3b0b31773c8293fa245eb970fae079dfe6189c91c699a48c21306`.
|
||||
|
||||
## `ghostnet-lxc-baseline.sh`
|
||||
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
|
||||
# Fresh-state rebuild of CT 101 (Samba file server) on the Proxmox VE host.
|
||||
# Creates the container from a Debian 13 template with the recorded profile,
|
||||
# attaches the five media mounts, disables the LXC seccomp filter (required
|
||||
# attaches the six media mounts, disables the LXC seccomp filter (required
|
||||
# by the rootful NFS-Ganesha container, GNAI-019) and runs the reviewed
|
||||
# generic LXC baseline hook with the recorded account UIDs.
|
||||
# generic LXC baseline hook with the recorded account UIDs. It then masks the
|
||||
# configfs mount unit (configfs is unavailable in unprivileged LXC; CT
|
||||
# 100/102/103 convention) and clears a stale failed state.
|
||||
#
|
||||
# The script never replaces or destroys an existing CT 101. It contains no
|
||||
# password, private key or SMB secret. The SMB passwords are set by the
|
||||
@@ -14,7 +16,7 @@ set -Eeuo pipefail
|
||||
umask 077
|
||||
|
||||
readonly CTID='101'
|
||||
readonly HOSTNAME="${GHOSTNET_CT101_HOSTNAME:-samba}"
|
||||
readonly HOSTNAME="${GHOSTNET_CT101_HOSTNAME:-Samba}"
|
||||
readonly IPV4_CIDR='10.0.0.9/24'
|
||||
readonly GATEWAY='10.0.0.1'
|
||||
readonly NAMESERVER='10.0.0.14'
|
||||
@@ -24,10 +26,10 @@ readonly CONTAINER_STORAGE='local-lvm'
|
||||
readonly BASELINE_HOOK="${GHOSTNET_BASELINE_HOOK:-/usr/local/sbin/ghostnet-lxc-baseline.sh}"
|
||||
# Reviewed repository copy of proxmox/shared/scripts/ghostnet-lxc-baseline.sh:
|
||||
readonly BASELINE_HOOK_SHA256='111f1b70e47e3a2f6a1bcce22cb0ec50aacd8fbcff37d87fbcf853a318381b10'
|
||||
readonly CORES="${GHOSTNET_CT101_CORES:-2}"
|
||||
readonly CORES="${GHOSTNET_CT101_CORES:-1}"
|
||||
readonly MEMORY_MB="${GHOSTNET_CT101_MEMORY_MB:-2048}"
|
||||
readonly ROOTFS_GB="${GHOSTNET_CT101_ROOTFS_GB:-32}"
|
||||
readonly SWAP_MB="${GHOSTNET_CT101_SWAP_MB:-1024}"
|
||||
readonly ROOTFS_GB="${GHOSTNET_CT101_ROOTFS_GB:-4}"
|
||||
readonly SWAP_MB="${GHOSTNET_CT101_SWAP_MB:-2048}"
|
||||
# Empty: auto-detect the newest debian-13 amd64 template in the local cache.
|
||||
readonly OS_TEMPLATE="${GHOSTNET_OS_TEMPLATE:-}"
|
||||
# The recorded account UIDs must match samba_access_agent_uid and
|
||||
@@ -35,13 +37,15 @@ readonly OS_TEMPLATE="${GHOSTNET_OS_TEMPLATE:-}"
|
||||
readonly AGENT_UID="${GHOSTNET_AGENT_UID:-}"
|
||||
readonly ADMIN_UID="${GHOSTNET_ADMIN_UID:-}"
|
||||
|
||||
# Guest mount points of the media library (GNAI-017 section 2); the host
|
||||
# paths are supplied per environment variable and must already exist.
|
||||
# Guest mount points of the live media library (GNAI-017 section 1, recorded
|
||||
# 2026-10-27); the host paths are supplied per environment variable and must
|
||||
# already exist. The Extern disk is mounted at /media/datenhdd2/extern.
|
||||
readonly -a MOUNT_GUEST_PATHS=(
|
||||
'/media/daten1'
|
||||
'/media/daten2'
|
||||
'/media/daten3'
|
||||
'/media/datenhdd2'
|
||||
'/media/datenhdd1'
|
||||
'/media/datenhdd2/extern'
|
||||
'/media/datenhdd3'
|
||||
)
|
||||
readonly -a MOUNT_HOST_PATHS=(
|
||||
@@ -50,6 +54,7 @@ readonly -a MOUNT_HOST_PATHS=(
|
||||
"${GHOSTNET_MP2_HOST:-}"
|
||||
"${GHOSTNET_MP3_HOST:-}"
|
||||
"${GHOSTNET_MP4_HOST:-}"
|
||||
"${GHOSTNET_MP5_HOST:-}"
|
||||
)
|
||||
|
||||
log() {
|
||||
@@ -101,7 +106,7 @@ if pct status "$CTID" >/dev/null 2>&1; then
|
||||
die "CT ${CTID} is still registered"
|
||||
fi
|
||||
|
||||
[[ "$HOSTNAME" =~ ^[a-z0-9][a-z0-9-]*$ ]] ||
|
||||
[[ "$HOSTNAME" =~ ^[A-Za-z0-9][A-Za-z0-9-]*$ ]] ||
|
||||
die "invalid hostname: ${HOSTNAME}"
|
||||
require_numeric GHOSTNET_CT101_CORES "$CORES"
|
||||
require_numeric GHOSTNET_CT101_MEMORY_MB "$MEMORY_MB"
|
||||
@@ -114,7 +119,7 @@ require_numeric GHOSTNET_ADMIN_UID "$ADMIN_UID"
|
||||
|
||||
for index in "${!MOUNT_HOST_PATHS[@]}"; do
|
||||
[[ -n "${MOUNT_HOST_PATHS[$index]}" ]] ||
|
||||
die "GHOSTNET_MP${index}_HOST is not set; all five media mount host paths are required"
|
||||
die "GHOSTNET_MP${index}_HOST is not set; all six media mount host paths are required"
|
||||
[[ -d "${MOUNT_HOST_PATHS[$index]}" ]] ||
|
||||
die "media mount host path does not exist: ${MOUNT_HOST_PATHS[$index]}"
|
||||
done
|
||||
@@ -236,6 +241,10 @@ GHOSTNET_AGENT_UID="$AGENT_UID" GHOSTNET_ADMIN_UID="$ADMIN_UID" \
|
||||
"$BASELINE_HOOK" "$CTID" ||
|
||||
die 'the baseline hook failed; inspect the output above before any rerun'
|
||||
|
||||
log 'masking the configfs mount unit (configfs is unavailable in unprivileged LXC)'
|
||||
pct exec "$CTID" -- systemctl mask sys-kernel-config.mount
|
||||
pct exec "$CTID" -- systemctl reset-failed sys-kernel-config.mount
|
||||
|
||||
pct exec "$CTID" -- /bin/bash -s -- \
|
||||
"$HOSTNAME" "${IPV4_CIDR%/*}" "$AGENT_UID" "$ADMIN_UID" \
|
||||
"${MOUNT_GUEST_PATHS[@]}" <<'GUEST_VERIFY' ||
|
||||
@@ -268,8 +277,12 @@ ip -o -4 address show scope global | grep -Eq "[[:space:]]inet[[:space:]]+${ipv4
|
||||
test "$(id -u ghost-agent)" = "$agent_uid"
|
||||
test "$(id -u ghost)" = "$admin_uid"
|
||||
systemctl is-active --quiet ssh.service
|
||||
if systemctl --failed --no-legend --plain | grep -q .; then
|
||||
die 'failed systemd units are present after the baseline'
|
||||
fi
|
||||
for mount_point in "${mounts[@]}"; do
|
||||
findmnt --noheadings --target "$mount_point" >/dev/null
|
||||
awk -v target="$mount_point" '$2 == target { found = 1 } END { exit(found ? 0 : 1) }' /proc/mounts ||
|
||||
die "media mount point is not mounted: $mount_point"
|
||||
done
|
||||
# The empty lxc.seccomp.profile must disable the container seccomp filter.
|
||||
test "$(awk '$1 == "Seccomp:" { print $2 }' /proc/self/status)" = '0'
|
||||
|
||||
@@ -21,11 +21,14 @@ readonly EXPECTED_IPV4='10.0.0.9'
|
||||
readonly CONFIRMATION_PHRASE='DIST-UPGRADE_CT101_TO_DEBIAN_13'
|
||||
readonly BACKUP_STORAGE="${GHOSTNET_BACKUP_STORAGE:-local}"
|
||||
readonly BACKUP_DUMP_DIR="${GHOSTNET_BACKUP_DUMP_DIR:-/var/lib/vz/dump}"
|
||||
# Live media mount topology of the productive CT 101 (recorded 2026-10-27):
|
||||
# six Proxmox mount points; the Extern disk is mounted at /media/datenhdd2/extern.
|
||||
readonly -a MEDIA_MOUNT_POINTS=(
|
||||
'/media/daten1'
|
||||
'/media/daten2'
|
||||
'/media/daten3'
|
||||
'/media/datenhdd2'
|
||||
'/media/datenhdd1'
|
||||
'/media/datenhdd2/extern'
|
||||
'/media/datenhdd3'
|
||||
)
|
||||
|
||||
@@ -254,7 +257,7 @@ grep -q ':445 ' <<<"$listeners" || die 'SMB listener 445 is missing'
|
||||
test "$(awk '$1 == "Seccomp:" { print $2 }' /proc/self/status)" = '0' ||
|
||||
die 'the container seccomp filter is still active'
|
||||
for mount_point in "${mounts[@]}"; do
|
||||
findmnt --noheadings --target "$mount_point" >/dev/null ||
|
||||
awk -v target="$mount_point" '$2 == target { found = 1 } END { exit(found ? 0 : 1) }' /proc/mounts ||
|
||||
die "media mount is not mounted: ${mount_point}"
|
||||
done
|
||||
|
||||
|
||||
Reference in New Issue
Block a user