title: 🌲 Finale – Waldbau ohne Burnout
slug: finale_waldbau_kernel_pattern
lang: de
summary: Was wir heute erlebt, gebaut und verstanden haben – als wiederholbares Muster über Debian, Mint & macOS hinweg. Ohne Rust, mit Haltung.
tags: [Crumbforest, Playbook, MQTT, MikroTik, ESP32, Debian, Mint, macOS, Kernel-Regeln]


🌥️ Worum es heute ging

Ein Tag zwischen Container, Router, ESP und Wald. Wir haben Dinge kaputt-gemacht (unabsichtlich), gefixt (absichtlich) und daraus ein Pattern destilliert, das sich morgen wiederholen lässt – ohne neue Baustellen und ohne Rust.
Leitstern: kleine Patches, sichtbare Beweise, jederzeit Revert.


🎛️ Heute gelernt (kurz)

  • Mosquitto: lief nicht wegen doppelter persistence_location. Entfernen → Dienst startet, 1883 lauscht, Sub/Pub klappt.
  • Firewall-Reihenfolge ist alles: Mit einer zu harten input-Regel haben wir uns kurz ausgesperrt. Lektion: Safe-Mode, Allow-Regeln ganz nach oben, erst danach Drop.
  • ESP32: WLAN/Heartbeat klappt stabil, wenn SSID, PSK, Broker, User/Pass konsistent sind und 2,4 GHz erzwungen wird.
  • Beweis statt Bauch: mosquitto_sub/pub, nc -vz, tcpdump – jedes „läuft“ bekommt einen Log.

🛠️ Was steht jetzt stabil

  • Broker (1883): allow_anonymous false, password_file gesetzt, Log unter /var/log/mosquitto/mosquitto.log, testbar per mosquitto_sub/pub.
  • MikroTik: Minimal-Filter

  • Management von Admin-Netz (WinBox/SSH)

  • ESP-VLAN → Broker:1883 erlaubt
  • established,related erlaubt
  • drop zuletzt
    (Reihenfolge geprĂźft, Safe-Mode benutzt.)
  • ESP32 MicroPython: Mini-main.py publisht crumb/esp/<id>/heartbeat.
  • Cross-OS: Debian/Mint/macOS jeweils ein klarer Weg (siehe Patterns).

🧭 Was wir verstanden haben

  • Kernel-Regeln (unser Stil):

  • Beweis vor Behauptung • 2) Kleine Patches • 3) Revert jederzeit •

  • Interfaces stabil (Topics/Ports sind Verträge) • 5) Least Privilege •
  • Deterministische Tests • 7) Erklärbar in 3 Sätzen.
  • Reality-Gap schließen: Kein „Visionstheater“. Wir zeigen Logs, nicht Meinungen.
  • Haltung statt Hektik: Kinder zuerst → Risikominimierung schlägt Tempo.

📦 Muster ohne Rust – nur Bash, Make & Python

Ziel: ein Repo /tools, das auf Debian, Mint, macOS gleich funktioniert.

Ordnerstruktur

tools/
  mqtt_smoketest.sh      # Broker-Echo in <10s
  esp_push.py            # mpremote/rshell Fallback
  rsc/                   # MikroTik .rsc (apply / rollback)
  makefile               # Ein-Klick-Ziele

Makefile (Ausschnitt)

BROKER ?= 192.168.88.227
USER   ?= esp1
PASS   ?= geheim

smoke:
    ./tools/mqtt_smoketest.sh $(BROKER) $(USER) $(PASS)

esp-push:
    python3 tools/esp_push.py main.py

router-apply:
    @echo "Bitte in WinBox im Safe-Mode sein."
    # .rsc Datei importieren (GUI) – oder per ssh/winbox-cli

logs:
    tail -n 100 /var/log/mosquitto/mosquitto.log

Debian/Mint – Minimalpakete

sudo apt update
sudo apt install -y mosquitto mosquitto-clients python3-venv python3-pip
python3 -m venv .venv && source .venv/bin/activate
pip install --upgrade pip mpremote esptool

macOS (Homebrew)

brew install mosquitto python mpremote esptool
brew services start mosquitto

Einheitliche Checks

  • Broker: ./tools/mqtt_smoketest.sh 192.168.88.227 esp1 geheim
  • Port: nc -vz 192.168.88.227 1883
  • Wire: sudo tcpdump -ni any tcp port 1883 -vv

🔐 MikroTik – Minimal & sicher (ohne neue Baustellen)

Prinzip: Erst erlauben, was zwingend ist, dann „drop“. Regeln nach oben.

  • Management: input accept fĂźr WinBox/SSH aus Admin-Netz
  • State-Keep: established,related
  • ESP-VLAN → Broker:1883 erlauben (nur TCP 1883, nur Broker-IP)
  • Drop am Ende

Test:

  • Aus dem ESP-VLAN: nc -vz 192.168.88.227 1883 → Connected
  • mosquitto_sub auf Broker empfängt Heartbeat

🧪 ESP32 – 10-Zeilen-Heartbeat

import network, time, binascii, machine
from umqtt.simple import MQTTClient

SSID="ESP-Wald"; PSK=""       # oder deine SSID/PSK
BROKER="192.168.88.227"
USER=b"esp1"; PASS=b"geheim"

sta=network.WLAN(network.STA_IF); sta.active(True)
if not sta.isconnected():
    sta.connect(SSID, PSK)
    for _ in range(40):
        if sta.isconnected(): break
        time.sleep_ms(250)

cid=b"esp-"+binascii.hexlify(machine.unique_id())
topic=b"crumb/esp/%s/heartbeat"%cid
c=MQTTClient(cid,BROKER,user=USER,password=PASS,keepalive=60)
c.connect(); c.publish(topic,b"hi"); c.disconnect()
print("✅", sta.ifconfig(), topic)

🔭 Nächste kleine Schritte (keine neuen Berge)

  1. Broker-IP fixen (DHCP-Lease statisch) & Host-Firewall dokumentieren.
  2. Node-RED Hello-Flow: mqtt in → debug (ein Topic, ein Tab).
  3. ESP-ID im Topic standardisieren und in README.md notieren.
  4. Rollback-.rsc ablegen (vier Zeilen, um die Allow-Regeln zu entfernen/disable).
  5. One-Pager „Troubleshoot“: 10 häufige Fehler → eine Zeile Fix je Fehler.

❓„Würden wir den Wald ohne kleinen Krümel Linus bauen?“

Ja – wenn wir seine Prinzipien leben: kleine, prüfbare Schritte, Respekt vor dem System, Reverts immer parat.
Nicht der Name baut den Wald, die Haltung tut es.


📎 Anhänge (Copy-Paste ready)

A1 – mqtt_smoketest.sh

#!/usr/bin/env bash
set -euo pipefail
BROKER="${1:-127.0.0.1}"; USER="${2:-esp1}"; PASS="${3:-geheim}"
TOPIC="crumb/test"; MSG="ping-$RANDOM"
timeout 5s mosquitto_sub -h "$BROKER" -t "$TOPIC" -u "$USER" -P "$PASS" -C 1 -v > /tmp/mqtt_out.$$
mosquitto_pub -h "$BROKER" -t "$TOPIC" -m "$MSG" -u "$USER" -P "$PASS"
sleep 1
grep -q "$MSG" /tmp/mqtt_out.$$ && echo "✅ MQTT ok @ $BROKER ($MSG)" || (echo "❌ MQTT fail"; cat /tmp/mqtt_out.$$; exit 1)
rm -f /tmp/mqtt_out.$$

A2 – Mosquitto Pass anlegen

sudo mosquitto_passwd -c /etc/mosquitto/passwd esp1
sudo systemctl restart mosquitto && sudo tail -n 50 /var/log/mosquitto/mosquitto.log

A3 – Minimaler MikroTik-Filter (Reihenfolge!)

/ip firewall filter
add chain=input action=accept protocol=tcp dst-port=8291 src-address=192.168.88.0/24 comment="mgmt winbox"
add chain=input action=accept protocol=tcp dst-port=22   src-address=192.168.88.0/24 comment="mgmt ssh"
add chain=input action=accept connection-state=established,related comment="state keep"
add chain=input action=accept protocol=tcp dst-port=1883 src-address=192.168.50.0/24 dst-address=192.168.88.227 comment="ESP->Broker 1883"
add chain=input action=drop comment="DROP last"

🌳 Schluss

Heute war kein „nice Demo“, sondern Erdsprung: weniger Vermutung, mehr Beweis.
So wächst der Wald – leise, wiederholbar, mit Heimweg.
Kinder atmen, Maschinen antworten, und wir halten die Ordnung klein & klar.