- ansible_stand {commit, sha256} aus dem Check-in: Archiv mit Secret im
Header laden, Summe prüfen, mit tarfile-Datenfilter entpacken, atomar nach
/var/lib/tuxflotte/ansible/<commit>/ (0700), aktueller + voriger Stand
bleiben; dann ansible-playbook -c local mit denselben Tags/Extra-Vars
- Fingerabdruck nimmt den Commit aus ansible_stand statt git ls-remote
(gleicher Wert wie bisher, kein Extra-Lauf beim Umstieg)
- ohne Stand oder bei Fehler: ansible-pull mit ansible_repo wie bisher
- Check-in meldet ansible_weg (archiv/git/git-rueckfall)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rolle persoenliche-konten laeuft bei jedem Lauf mit, die Liste (mit
Passwort-Hashes) nur ueber die root-lesbare Extra-Vars-Datei. Das Ergebnis
der Rolle geht an /api/v1/agent/persoenliche-konten; die Datei bleibt
liegen, wenn die Meldung scheitert.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Liebherr-83 verlor am 14.10.2026 mitten im Lauf das Netz und checkte danach
stundenlang nicht mehr ein: subprocess.run wartete ohne Grenze. Jetzt
eigene Prozessgruppe, nach PULL_TIMEOUT_SECONDS SIGTERM, nach 30s SIGKILL
an alle (ansible-playbook/apt/dpkg), danach dpkg --configure -a; der Lauf
gilt als fehlgeschlagen und wird nach 5 Minuten wiederholt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bisher stand das JSON samt entschluesselter _passwort/_secret-Optionen in
der Kommandozeile von ansible-pull: waehrend des Laufs fuer jeden
angemeldeten Benutzer per ps lesbar und von ansible-pull selbst ins Journal
geschrieben. Jetzt 0600-Datei unter /run/tuxflotte/agent, -e @datei, nach
dem Lauf geloescht; Schreibfehler zaehlt als fehlgeschlagener Lauf.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Damit sieht der Server, welche Agent-Fassung auf einem Gerät läuft
(ADR-0044). Ist die Datei nicht lesbar, fehlt das Feld einfach.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ohne EnvironmentFile= war der bereits vorhandene TUXFLOTTE_ANODE_URL-
Override in agent.py auf jedem fertig installierten Geraet wirkungslos -
der systemd-Dienst kannte die Variable schlicht nie. Fuehrendes "-" macht
die Datei optional (Produktivgeraete ohne /etc/tuxflotte/agent.env sind
unveraendert).
Teil der E2E-Testrunde, siehe platform-docs/roadmap/
e2e-testrunde-lokale-adressierung.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DWKevK2QUK5tsGmqfSD6Yy
apply_roles() bekommt jetzt hostname als eigenen Parameter, "hostname"-
Rolle ist wie webapp-shortcuts immer Teil des ansible-pull-Laufs
(tuxflotte_zielhostname als Extra-Var, leer wenn keine Konvention
konfiguriert oder das Gerät seinen eigenen Namen behalten hat).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
'webapp-shortcuts' (siehe admin/ansible-content) ist jetzt IMMER Teil
der --tags, auch bei leeren Listen - anders als die anderen Rollen ist
sie nicht present/absent-gesteuert, sondern bekommt die komplette
aktuelle Webapp-Liste als eigene Extra-Var (tuxflotte_webapps) und
gleicht selbst ab, was existieren soll. Icon-URLs werden hier
(nicht im Server) zu vollen URLs zusammengesetzt (ANODE_URL + relativer
icon_path aus dem Checkin) - der Server kennt seine eigene oeffentliche
Adresse nirgends, gleiches Muster wie bei GOLDEN_IMAGE_URL.
Der bisherige 'nothing to do'-Kurzschluss (kein ansible-pull-Lauf ohne
Blueprints/Auftraege) entfaellt dadurch zwangslaeufig - ein Geraet mit
gerade entfernten Webapps, aber sonst leeren Listen, muss trotzdem
laufen, um aufzuraeumen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VLk93dhDMrkPXefVdknMV9
collect_health() sammelt Diskbelegung/RAM/Uptime/Load Average rein per
Stdlib (shutil.disk_usage, /proc/meminfo, /proc/uptime, os.getloadavg),
jeder Wert einzeln try/except. checkin() schickt das Ergebnis jetzt mit.
main()-Loop wendet 0-30 Min Jitter nur auf 'große' Intervalle (>=1h) an -
der kurze Debug-Modus (60s) und der Fallback-Retry bleiben unverjittert,
sonst würde Jitter den Debug-Zweck untergraben. Boot-Checkin war schon
vorher vorhanden (run_once() läuft immer vor der ersten sleep()), hier
nicht angefasst.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ermöglicht die neue Reprovisionieren-Aktion im Kundenportal: wenn das
lokale Secret serverseitig ungültig gemacht wurde (Deprovisionierung),
holt sich der Agent beim nächsten Poll automatisch ein neues über den
bestehenden /api/v1/agent/bootstrap-Endpoint statt dauerhaft mit 401
hängenzubleiben.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
apply_roles() baut zusätzlich zu den present/absent-States ein
optionen-Dict je Rolle aus der Check-in-Antwort und gibt es im selben
--extra-vars-JSON mit (z.B. standardbrowser für brave-fedora).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Extends the checkin/apply cycle to cover the "auftraege" list from the
check-in response (see ADR-0010) alongside the existing workspace
blueprints: both are merged into one ansible-pull invocation, with
--tags the union of all involved roles (a catalog role needs to run
even when its target state is absent, so its removal branch executes)
and a new --extra-vars payload (tuxflotte_auftrag_states, role ->
present/absent) that ansible-content's site.yml threads down into each
role.
After the pull, reports the outcome of each Auftragskatalog entry back
via the new POST /api/v1/agent/report endpoint (applied/apply_failed/
removed/remove_failed). This is intentionally coarse: ansible-pull has
one exit code for the whole run, not per-role results, so all entries
in a given run share that outcome. Workspace blueprints are not
reported on, matching ADR-0010's scope.
Verified end to end against anode and the QEMU test VM: selecting
browser-brave as a catalog entry produced an "applied" event and the
marker file; deselecting it removed the marker and produced a
"removed" event - both written by the agent's own report call, not
simulated.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Erste lauffaehige Version: laedt Credentials, meldet sich per Bearer-Token
bei anode/api/v1/agent/checkin, wendet zugewiesene Blueprints per
ansible-pull an und schlaeft bis zum naechsten Intervall.