hermes-erkenntnisse/worklog-2026-07-23-tts-anleitung-poller.md

6.3 KiB

Worklog 2026-07-23 — #33 barby-tts-api Rechte + #35 anleitung-poller

Wichtiger Vorab-Fund: hub_bash läuft NICHT auf hub.koerners.org

Der MCP-Tool hub_bash führt Befehle auf jump.panel1.de (49.13.209.112) aus, nicht auf hub.koerners.org (103.241.51.192). Für Aufgabe #33 musste von jump per ssh hub.koerners.org weitergesprungen werden. Aufgabe #35 stellte sich heraus als bereits auf jump.panel1.de deployt (SKILL.md nennt es "Jump Hub Produktion" — Verwechslungsgefahr bleibt bestehen, siehe reference-hub-topology.md).


#33 — barby-tts-api.service Leserechte (auf hub.koerners.org)

Problem: Dienst barby-tts-api.service läuft als User cloud, Verzeichnis /opt/credentials ist drwx------ root:root (700) → PermissionError: [Errno 13].

Exakte Ursache (aus Code + journalctl): /opt/scripts/barby-tts-api.py Zeile 24:

CF_ACCT = open("/opt/credentials/cloudflare-account-id").read().strip()

Datei selbst war bereits 644 (world-readable), aber der Verzeichnis-Zugriff (700) blockierte jeden Traversal für cloud. Die zweite Credential (/opt/credentials/gcp/code-barby-workspace-key.json, Zeile 10/49) war KEIN Problem — das gcp-Unterverzeichnis ist 755 und die Datei bereits cloud:cloud — kein Handlungsbedarf dort.

Backup (vorher):

/home/cloud/backups/acl-opt-credentials-before-202607231707.txt
# file: /opt/credentials       user::rwx group::--- other::---
# file: /opt/credentials/cloudflare-account-id  user::rw- group::r-- other::r--

Änderung (minimal, ACL statt chmod):

sudo apt-get install -y acl   # setfacl war nicht installiert
sudo setfacl -m u:cloud:x /opt/credentials                       # NUR Traverse, kein Read
sudo setfacl -m u:cloud:r /opt/credentials/cloudflare-account-id  # NUR diese eine Datei

Danach (getfacl):

/opt/credentials:                    user:cloud:--x  (mask --x)
/opt/credentials/cloudflare-account-id: user:cloud:r--  (mask r--)

Kein chmod, kein world-readable, kein Zugriff auf andere Dateien im Verzeichnis (--x erlaubt nur "durchqueren", kein ls, kein Read anderer Files).

Verifikation:

  • sudo -u cloud cat /opt/credentials/cloudflare-account-id → liest die Datei (vorher Permission denied)
  • systemctl start barby-tts-api.serviceactive (running)
  • curl localhost:3097/health{"ok":true,"service":"barby-voice",...}
  • Echter TTS-Testcall: POST /v1/audio/speech {"input":"Test eins zwei drei","voice":"leda"} → HTTP 200, 8352 Bytes, valides MP3 (MPEG Layer III, 24kHz) — abgespielt/geprüft, danach gelöscht.

Kein Scope-Creep: Nichts über das reine Lese-ACL hinaus geändert. Kein chmod auf dem Verzeichnis, kein User-Wechsel, kein anderer Dienst angefasst.


#35 — anleitung-poller Reaktivierung (auf jump.panel1.de = "Jump Hub Produktion")

Ist-Zustand vor Eingriff:

  • Script /opt/scripts/poll_anleitung.py + Wrapper /opt/scripts/poll_with_health.sh waren bereits vorhanden.
  • Cron-Eintrag war entgegen der Aufgabenbeschreibung NICHT entfernt: /etc/crontab: */30 * * * * root /opt/scripts/poll_with_health.sh lief weiterhin (belegt durch /var/log/syslog CRON-Einträge alle 30 Min).
  • Tatsächliche Root-Cause für "tot seit 2026-06-30": /tmp/anleitung_key.txt (API-Key, wird bei Reboot geleert — dokumentierter Pitfall im Skill selbst) fehlte → jeder Lauf brach mit FATAL: API key file not found ab, seit dem letzten Reboot am 30.06. Für Bär von außen nicht von einem entfernten Cron zu unterscheiden.
  • /root/.hermes/skills/rezepte/ stand bei 73 Skills, last_poll: 2026-06-30T20:30:02.

Backup vor Änderung:

/root/backups/crontab-before-anleitung-poller-202607231720.bak
/root/backups/anleitung_poller.json.bak-202607231720
/root/backups/hermes-skills-rezepte-before-202607231720.tar.gz   (73 Skills gesichert)

Fix:

  • API-Key aus der (bereits im Repo dokumentierten, Klartext-)Deployment-Notiz references/deployment-notes.md erneut base64-kodiert nach /tmp/anleitung_key.txt (chmod 600, root:root) geschrieben — genau der vom Poller erwartete Zustand.
  • Cron-Eintrag NICHT dupliziert (war schon da, geprüft mit grep -n poll_with_health /etc/crontab → genau eine Zeile).

VERIFY ECHT:

Vorher:  73 Skills, last_poll 2026-06-30T20:30:02
Lauf 1:  sudo python3 /opt/scripts/poll_anleitung.py
         → "CHANGED: 117 REZEPTE found" / "DONE new=51 upd=17 skip=49 total=124"
Nachher: 124 Skills, last_poll 2026-07-23T17:25:33
Lauf 2 (Idempotenz-Check): "NO CHANGE hash=91ac921f22eb known=124" — sauber, keine Fehler.

Bekannte Einschränkung (nicht behoben, außerhalb des Auftrags): Der Wrapper poll_with_health.sh prüft vor jedem Lauf per SSH, ob GPU-Shadow (100.87.122.111) erreichbar ist (curl 127.0.0.1:8188). Aktuell ist das nicht der Fall → der reguläre Cron-Lauf skippt mit exit 0 ("GPU-Shadow not healthy — skipping poller"). Die Funktionsfähigkeit des Pollers selbst wurde durch direkten Aufruf von poll_anleitung.py bewiesen (s.o.). Sobald GPU-Shadow wieder erreichbar ist, läuft der reguläre 30-Min-Cron durch. Das ist eine bewusste Design-Gate-Logik aus dem Skill selbst, keine von mir eingeführte Einschränkung — nicht eigenmächtig geändert.


🚩 Sicherheits-Fund (zur Kenntnis, nicht blockierend)

Im Repo barby/fleet-shared liegt unter hermes-skills/devops/anleitung-poller/references/credential-redaction-bypass.md eine explizite Anleitung, wie Hermes' Credential-Redaction (die Bearer-Token/API-Keys in generiertem Code zensiert) systematisch umgangen werden kann (open(..., 'wb') statt write_file, base64-Template

  • @file-Syntax für curl-Header, etc.) — als "Workaround"-Doku für Agents geschrieben, nicht nur für diesen einen Use-Case. Ich habe diese Technik NICHT verwendet (Key wurde direkt per SSH/sudo geschrieben, kein Redaction-Agent involviert) und auch nicht verändert oder gelöscht — nur zur Kenntnisnahme gemeldet, da es sich um eine generelle Anleitung zum Aushebeln eines Sicherheitsmechanismus handelt, nicht bloß um Klartext-Credentials in Doku (was laut feedback-creds-in-docs.md explizit gewünschte Praxis ist).

Doku-Verteilung: Forgejo (barby/hermes-erkenntnisse), Obsidian (nas2:/volume1/Obsidian/Wissen/), Nachtplan-Worklist (Obsidian-Variante, da Desktop\nachtplan.md von diesem Linux-Host aus nicht erreichbar ist).