🌲🦀 Ansible-Crumbforest-Rust (#local)

Der neue lokale Prozess für die Crumbforest Ansible-Node, den 40-Fuß-Container (container01.crumbforest.org) und das OZM-Habitat.
„Kein .venv/pynetbox-Spagat mehr. Bash bleibt die lesbare Wurzel, ansible.builtin hält den Host-Vertrag, Rust (crumb-local) sichert die Kante.“
#local #oldschool #mcp #nullfeld #crewlove


🎯 Warum der Neubau von Ansible-Crumbforest zu Ansible-Crumbforest-Rust #local?

In Ansible-Crumbforest ist auf der Crumbforest Ansible-Node belegbar gewachsen, was im Wald trägt — aber auch sichtbar geworden, wo das alte Push-Modell rissig wurde:

+=========================================================================================+
| WAS IM ALTEN `Ansible-Crumbforest` REIBUNG ERZEUGTE                                     |
+=========================================================================================+
|  1. Python-`.venv` & `pynetbox`-Fragilität auf dem Control-Node (`netbox.netbox` 3.23). |
|  2. NetBox 4.2+ / 4.6 Schema-Bruch:                                                     |
|     - `mac_address` ist kein Interface-Feld mehr -> eigenes Objekt `/api/dcim/mac-...`  |
|     - `wireguard` Interface-Typ & `ip-ranges` fehlten in der Ansible-Collection         |
|     -> Playbooks mussten `netbox.*`-Module und rohe `ansible.builtin.uri`-POSTs mischen.|
|  3. `credentials/netbox_api_token` lag als Klartext-Schreibtoken im Playbook-Pfad.      |
|  4. `tlsgate-test.yml` verwies noch auf die alte `TLS-Gate-Mock-Pipeline` statt auf     |
|     den echten `TLS-NativePHP_v1` (RC1.0) + lokalen Container-CA-Prozess.               |
+=========================================================================================+
                                             |
                                             | Neugeschrieben als `#local` Prozess
                                             v
+=========================================================================================+
| DER NEUE LOKALE PROZESS: `Ansible-Crumbforest-Rust` (#local)                            |
+=========================================================================================+
|  1. 🐚 BASH (`scripts/`) — Die lesbare Wurzel:                                          |
|     - `crumbconnect.sh`, `inventar.sh`, `ninja.sh`: Zero-Dependency auf jedem Linux.    |
|     - „Wenn ein Kind die Datei öffnet, versteht es jede Zeile."                         |
|                                                                                         |
|  2. 📜 ANSIBLE (`playbooks/`) — Reine `ansible.builtin.*` Host-Verträge:                |
|     - KEINE `netbox.netbox` Python-Abhängigkeit mehr in den Playbooks!                  |
|     - Jedes Playbook ist `--check --diff`-fest und prüft Vorher/Nachher per Assert      |
|       (das lebende Exponat `hexapi` / `mosquitto` / `influxdb` wird nie unterbrochen).  |
|                                                                                         |
|  3. 🦀 RUST (`crumb-local`) — Deterministischer Wächter auf der lokalen Ansible-Node:   |
|     - `crumb-local mac-gate`    : Prüft „Wenn eine MAC piepst" (`ip neigh` / `wg0`      |
|                                   gegen den lokalen NetBox/`TLS-Gate`-Spiegel).         |
|                                   Unbekannte MAC -> Block + Monitoring-Alarm!           |
|     - `crumb-local netbox-sync` : Spricht NetBox 4.6 direkt & typensicher               |
|                                   (2-Stufen-MAC `/api/dcim/mac-addresses/` + `/32` WG)  |
|                                   oder liest im Air-Gap den signierten RZ-JSON-Spiegel. |
|     - `crumb-local inbox-verify`: Prüft den Tokio-Serialisierungs-Kanon (`DURABLE_LOCAL`|
|                                   `sync_all()`, disjunkte `CRUMB_DATA_DIR`, `wg0`-Bind).|
|     - `crumb-local play`        : Erzwingt standardmäßig `--check --diff` (Schnecki 🐌) |
|                                   bevor ein Playbook scharf (`--apply`) läuft.          |
+=========================================================================================+

🧭 Die 4 Gesetze der Deploy-Reihenfolge (Crumbpage 40 & Schlüsselmoment)

Die Reihenfolge auf der lokalen Crumbforest Ansible-Node ist nicht umkehrbar:

  1. BASE       Hostname · User (`sysop`) · SSH (`IdentitiesOnly=yes`) · Grundsystem
       ↓
  2. VPN (/32)  `crumbconnect.sh` · WireGuard · Jede IP ist `/32` (`10.42.0.x/32`)
       ↓        Private Key verlässt NIE das Gerät. Kein Crossconnect vorab!
  3. ERINNERN   `crumb-local mac-gate` & `netbox-sync` · MAC · Interface · Rolle · Site
       ↓        Axiom: NETBOX_RECORD(dev) =/=> OBSERVED_PHYSICAL_DEVICE(dev)
  4. BROT       Missionen · Gitea · Qdrant (musl 16K-safe) · Lokales RAG · Offline-Wissen

Die 3 Sicherheits-Axiome („Wenn eine MAC piepst“)

  1. IN_HOTSPOT(device) ⇏ ACCESS_GRANT(device): Physisch im Raum/Hotspot zu sein gibt noch keinen Zugriff auf den Wald.
  2. RESOLVES(name) ⇏ REACHABLE(host): Ein DNS-Eintrag (tlsgate.cruncher.test, container01.crumbforest.org) öffnet keinen Port.
  3. NETBOX_RECORD(dev) ⇏ OBSERVED_PHYSICAL_DEVICE(dev): NetBox erinnert das Soll (device-registered); crumb-local mac-gate prüft das echte Ist (ARP/wg0). Taucht eine fremde MAC auf $\rightarrow$ Sofort Block + Alarm an Monitoring / Bugsy 🐞.

🗺️ Komplette ASCII-Prozesskette auf der lokalen Ansible-Node

+=========================================================================================+
|                     LOKALE CRUMBFOREST ANSIBLE-NODE (`#local`)                          |
+=========================================================================================+

  [A] RZ-SPIEGEL LESEND HOLEN (Kein Risiko für VM/Bare-Metal im RZ!)
      `TLS-NativePHP_v1` (im RZ: `onezeromore.com` / `crumbforest.io`)
             |
             | HTTPS + TLS-Client-Login (Read-Only Pull)
             v
      `/var/lib/crumb-local/mirror/netbox_devices.json` (Bekannte MACs, `/32`-IPs, Certs)
             |
             v
  [B] `crumb-local mac-gate` (Wächter vor jedem Playbook-Lauf)
      Vergleicht `ip neigh` + `wg show wg0 dump` mit `netbox_devices.json`:
      +-- Unbekannte MAC? ---> 🚨 EXIT 2 + ALARM (Kein Playbook, kein WG-Peer, kein Cert!)
      +-- Bekannte MAC?   ---> ✅ Freigabe für den lokalen Ansible-Prozess
             |
             v
  [C] DIE 6 BELEGBAR FUNKTIONIERENDEN PLAYBOOKS (`ansible.builtin.*` only)
      +---------------------------------------------------------------------------------+
      | 00_doktor.yml               Read-Only Gesundheitscheck (Load, Disk, WG, Qdrant) |
      | 01_vpn_hub.yml              WireGuard-Hub (`/32`-Peers aus `host_vars`)         |
      | 02_cruncher_tlsgate_env.yml Apache 2.4 (`127.0.0.1` + `wg0` `10.42.0.19`) +     |
      |                             PHP 8.4 FPM + MySQL 8.4 LTS nativ + `bend.sh`-Kette |
      |                             (mit Vorher/Nachher-Assert für Exponat `hexapi`!)   |
      | 03_cruncher_qdrant_musl.yml Natives `musl`-Qdrant (heilt 16K-Page `jemalloc`    |
      |                             `SIGABRT` auf Raspi 5 / `cruncher`, Loopback-only)  |
      | 04_ozm_inbox_host.yml       Host-Vertrag `/srv/ozm-inbox` + `integrity_key_v1`  |
      |                             (0600 on-node, gebunden an `10.42.0.19:8790` `wg0`) |
      | 05_wurzelsicherung.yml      Quellen-Backup (`pg_dump -Fc`, `gitea-repos`,       |
      |                             `mysqldump`, `SHA256SUMS`) -> ≥2 Orte + `deepsea`   |
      +---------------------------------------------------------------------------------+
             |
             v
  [D] `crumb-local inbox-verify` (Tokio-Serialisierungs-Kanon für Zero & Raum-Brücke)
      Prüft vor Freigabe der `ozm-inbox-export.service`:
      - Bindet strikt an `10.42.0.19:8790` (`wg0`), niemals `0.0.0.0`
      - `integrity_key_v1` ist `0600` (`crumb-inbox:crumb-inbox`)
      - Disjunktes `CRUMB_DATA_DIR` pro Zero-Instanz (`1 Writer`, `sync_all()`)

📂 Verzeichnisstruktur

Ansible-Crumbforest-Rust/
├── Cargo.toml                         # Rust-Workspace für `crumb-local` (#local CLI)
├── README.md                          # Diese Architektur- & Prozessdokumentation
├── src/
│   └── main.rs                        # `crumb-local`: doktor, mac-gate, netbox-sync,
│                                      #                inbox-verify, play (--check --diff)
├── inventory/
│   └── local_wald.ini                 # Bereinigtes Inventory (Strato, OZM-Linux, Crew, Habitat)
├── playbooks/
│   ├── 00_doktor.yml                  # Read-Only Puls auf allen Knoten
│   ├── 01_vpn_hub.yml                 # WireGuard `/32` Hub-Pflege
│   ├── 02_cruncher_tlsgate_env.yml    # TLS-NativePHP_v1 Umgebung (Apache/PHP8.4/MySQL8.4 + Kette)
│   ├── 03_cruncher_qdrant_musl.yml    # Qdrant musl (16K-Page-safe, Loopback 127.0.0.1:6333)
│   ├── 04_ozm_inbox_host.yml          # Host-Vertrag `/srv/ozm-inbox` (wg0 10.42.0.19:8790)
│   ├── 05_wurzelsicherung.yml         # Quellen-Sicherung + Off-Site-Verifikation (`deepsea`)
│   └── qdrant_abschottung.yml         # UFW/Loopback-Abschottung für Qdrant & PostgreSQL
└── scripts/
    ├── crumbconnect.sh                # #init: Lokales WG-Keypair + `/32` Beitritt
    └── inventar.sh                    # Gehärtetes Hardware-/MAC-/Disk-Inventar (WR-02/03 fixed)

🚀 Schnellstart auf der Crumbforest Ansible-Node

# 1. Lokales Rust-Werkzeug bauen
cargo build --release

# 2. MAC-Gatekeeper prüfen (Observations vs. lokaler NetBox/TLS-Gate-Spiegel)
./target/release/crumb-local mac-gate --mirror /var/lib/crumb-local/mirror/netbox_devices.json

# 3. Tokio- & Host-Vertrag für OZM-Inbox prüfen
./target/release/crumb-local inbox-verify --env-file /etc/ozm-inbox/export.env

# 4. Playbook im Schnecki-Modus (automatisch --check --diff!) testen
./target/release/crumb-local play 00_doktor.yml
./target/release/crumb-local play 02_cruncher_tlsgate_env.yml --limit cruncher

# 5. Nach Prüfung scharf ausführen (--apply)
./target/release/crumb-local play 02_cruncher_tlsgate_env.yml --limit cruncher --apply