This commit is contained in:
parent
74ecdc2f7e
commit
7f03a31f67
126
worklog-2026-07-23-tts-anleitung-poller.md
Normal file
126
worklog-2026-07-23-tts-anleitung-poller.md
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
# 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:
|
||||||
|
```python
|
||||||
|
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):**
|
||||||
|
```bash
|
||||||
|
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.service` → `active (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).
|
||||||
Loading…
Reference in a new issue