Neue Packages und Module: - fileutil: Shared Upload-Logik mit Tenant-Isolation - httpapi/csrf.go: Double-Submit-Cookie CSRF-Schutz - httpapi/ratelimit.go: Rate-Limiting für /login - httpapi/uploads.go: neuteredFileSystem (kein Directory-Listing) - httpapi/manage/csrf_helpers.go: CSRF-Helpers für Templates - player/agent/internal/screenshot/screenshot.go: Periodische Screenshot-Erfassung Neue Umgebungsvariablen: - MORZ_INFOBOARD_REGISTER_SECRET: Pre-Shared-Secret für Agent-Registrierung - MORZ_INFOBOARD_SCREENSHOT_EVERY: Screenshot-Intervall im Player-Agent (Sekunden) Dokumentation aktualisiert: - server/backend/README.md: Neue Packages und Env-Variable REGISTER_SECRET - DEVELOPMENT.md: Beide neuen Env-Variablen mit Erklärungen - docs/API-ENDPOINTS.md: Screenshot-Endpoint als "In Vorbereitung" dokumentiert Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
13 KiB
Info-Board Neu - Entwicklung
Ziel
Dieses Dokument soll den Einstieg auf einem anderen Entwicklungsrechner moeglichst reibungsfrei machen.
Es beschreibt:
- minimale Voraussetzungen
- wichtige Verzeichnisse
- Build- und Run-Kommandos
- aktuelle Annahmen fuer den lokalen Entwicklungsbetrieb
Repository
- Remote:
git.az-it.net:az/morz-infoboard.git - Standard-Branch:
main
Projektwurzel:
/srv/docker/info-board-neu
Wichtige Verzeichnisse
docs/fuer Architektur- und Fachkonzepteserver/backend/fuer das zentrale Go-Backendplayer/agent/fuer den Go-basierten Player-Agentansible/fuer Deployment und Provisionierungcompose/spaeter fuer den zentralen Server-Stack
Aktueller Entwicklungsstand
Bereits vorhanden:
- fachliche Architektur- und Betriebskonzepte
- relationaler Schema-Entwurf in
docs/SCHEMA.md - funktionales Go-Backend (
server/backend) mit REST-API, PostgreSQL-Anbindung und Datenverwaltung - funktionaler Go-Agent (
player/agent) mit Server-Registrierung, Playlist-Management und Heartbeat-Sync - vollstaendiger Compose-Stack in
compose/server-stack.ymlmit PostgreSQL, Mosquitto und Backend-Service
Noch nicht vorhanden:
- produktives SSL/TLS-Handling fuer Deployment
- Docker-Secret-Integration fuer
MORZ_INFOBOARD_ADMIN_PASSWORD - Ansible-Variable
morz_admin_passwordals Vault-Variable (Phase 6)
Voraussetzungen auf dem Entwicklungsrechner
Mindestens empfohlen:
gitgoin Version1.24.xmake
Spaeter zusaetzlich sinnvoll:
dockerunddocker composepostgresql-clientmosquitto-clientsgolangci-lint
Fuer Container-Builds liegen erste Dockerfiles in:
server/backend/Dockerfileplayer/agent/Dockerfile
Schnellstart
Repository klonen:
git clone git.az-it.net:az/morz-infoboard.git
cd morz-infoboard
Dokumentationsbasis lesen:
README.mdPLAN.mdTECH-STACK.mddocs/SCHEMA.mddocs/OFFENE-ARCHITEKTURFRAGEN.mddocs/LAYOUT-JSON.md
Build-Kommandos
Backend bauen
cd server/backend
go build ./...
Agent bauen
cd player/agent
go build ./...
Alternativ ueber Makefile
make build
Aktuell bedeutet das:
make buildbaut Backend und Agentmake build-backendbaut nurserver/backendmake build-agentbaut nurplayer/agentmake run-backendstartet das Backendmake run-agentstartet den Agentenmake fmtformatiert beide Go-Modulemake lintprueft beide Go-Module mitgolangci-lint
Hinweis:
- auf dem aktuellen System dieser Session sind
makeundgonicht installiert; die Befehle sind fuer den Entwicklungsrechner vorbereitet
Lokale Entwicklung mit Login
Seit der Implementierung des Tenant-Features ist das Backend durch eine Session-basierte Authentifizierung geschuetzt. Fuer den lokalen Entwicklungsbetrieb muessen zwei zusaetzliche Umgebungsvariablen gesetzt werden:
MORZ_INFOBOARD_ADMIN_PASSWORD– legt das Passwort des initialen Admin-Users fest. Beim Backend-Start wird automatisch ein Useradminangelegt (bzw. dessen Passwort aktualisiert), der dem Standard-Tenantmorzzugeordnet ist. Bleibt die Variable leer, wird kein Admin angelegt und der Login-Bereich ist nicht nutzbar.MORZ_INFOBOARD_DEV_MODE– setzt das Session-Cookie ohne dasSecure-Flag, sodass er auch ueber unverschluesseltes HTTP (lokaleslocalhost) uebertragen wird. Ohne dieses Flag wird der Cookie nur ueber HTTPS gesetzt und der Login schlaegt im lokalen Betrieb still fehl.
Empfohlener Start fuer die lokale Entwicklung:
cd server/backend
MORZ_INFOBOARD_ADMIN_PASSWORD=dev \
MORZ_INFOBOARD_DEV_MODE=true \
go run ./cmd/api
Danach ist der Login unter http://localhost:8080/login mit admin / dev erreichbar.
Hinweis: MORZ_INFOBOARD_DEV_MODE=true darf niemals in einer produktiven Umgebung gesetzt werden, da der Cookie dort ausschliesslich ueber HTTPS uebertragen werden soll.
Lokaler Start
Backend lokal starten
cd server/backend
go run ./cmd/api
Standard:
- HTTP-Adresse:
:8080 - Health-Endpunkt:
GET /healthz - Basis-Endpunkt:
GET /api/v1
Konfigurierbar ueber:
MORZ_INFOBOARD_HTTP_ADDR– HTTP-Adresse (Standard::8080)MORZ_INFOBOARD_STATUS_STORE_PATH– Pfad zur JSON-Datei fuer persistenten Status-Store; leer lassen fuer reinen In-Memory-BetriebMORZ_INFOBOARD_ADMIN_PASSWORD– Passwort fuer den initialen Admin-User (leer = kein EnsureAdminUser-Lauf)MORZ_INFOBOARD_DEFAULT_TENANT– Slug des Standard-Tenants, dem der Admin-User zugeordnet wird (Standard:morz)MORZ_INFOBOARD_REGISTER_SECRET– Pre-Shared-Secret fuer POST /api/v1/screens/register; leer = offen fuer alleMORZ_INFOBOARD_DEV_MODE– wenntrue: Session-Cookie wird ohneSecure-Flag gesetzt (nur fuer lokale Entwicklung)
Beispiele:
MORZ_INFOBOARD_HTTP_ADDR=:18080 go run ./cmd/api
MORZ_INFOBOARD_HTTP_ADDR=:8080 \
MORZ_INFOBOARD_STATUS_STORE_PATH=/tmp/screen-status.json \
go run ./cmd/api
Agent lokal starten
cd player/agent
go run ./cmd/agent
Standardwerte:
MORZ_INFOBOARD_SCREEN_ID=unset-screenMORZ_INFOBOARD_SERVER_URL=http://127.0.0.1:8080MORZ_INFOBOARD_MQTT_BROKER=(leer = MQTT wird uebersprungen)MORZ_INFOBOARD_PLAYER_ADDR=127.0.0.1:8090MORZ_INFOBOARD_PLAYER_CONTENT_URL=(leer = kein Inhalt eingebettet)
Optional:
MORZ_INFOBOARD_MQTT_USERNAME– MQTT-BenutzernameMORZ_INFOBOARD_MQTT_PASSWORD– MQTT-PasswortMORZ_INFOBOARD_REGISTER_SECRET– Pre-Shared-Secret fuer Selbstregistrierung; muss mit Server-Konfiguration uebereinstimmenMORZ_INFOBOARD_SCREENSHOT_EVERY– Intervall fuer periodische Screenshots in Sekunden (z.B.300fuer 5 Minuten; 0 oder leer = deaktiviert)MORZ_INFOBOARD_CONFIG=/etc/signage/config.json– dateibasierte Konfiguration
Eine Beispielkonfiguration liegt in player/config/config.example.json.
Der Agent stellt unter http://127.0.0.1:8090/player eine lokale Kiosk-Seite bereit.
Beispiel ohne MQTT:
MORZ_INFOBOARD_SCREEN_ID=info01-dev \
MORZ_INFOBOARD_SERVER_URL=http://127.0.0.1:8080 \
go run ./cmd/agent
Beispiel mit MQTT:
MORZ_INFOBOARD_SCREEN_ID=info01-dev \
MORZ_INFOBOARD_SERVER_URL=http://127.0.0.1:8080 \
MORZ_INFOBOARD_MQTT_BROKER=tcp://127.0.0.1:1883 \
MORZ_INFOBOARD_MQTT_USERNAME=user \
MORZ_INFOBOARD_MQTT_PASSWORD=pass \
go run ./cmd/agent
Ansible-Deployment auf einen Zielrechner
Der ansible/-Ordner enthaelt ein vollstaendiges Playbook fuer das Deployment auf einen Pi oder ein Debian-System.
Voraussetzungen
- Ansible auf dem Entwicklungsrechner
- SSH-Key fuer den Zielrechner hinterlegt
- Ansible Vault fuer MQTT-Zugangsdaten
Inventory und Konfiguration
ansible/inventory.yml– Hosts und Gruppenansible/host_vars/<host>/vars.yml– host-spezifische Variablen (screen_id,ansible_host,ansible_user)ansible/group_vars/signage_players/vars.yml– globale Defaultsansible/group_vars/signage_players/vault.yml– verschluesselte Zugangsdaten (gitignored)
Vault-Datei anlegen:
ansible-vault create ansible/group_vars/signage_players/vault.yml
Inhalt:
vault_mqtt_username: "benutzername"
vault_mqtt_password: "passwort"
In vars.yml referenzieren:
morz_mqtt_username: "{{ vault_mqtt_username }}"
morz_mqtt_password: "{{ vault_mqtt_password }}"
Deployment ausfuehren
cd ansible
ansible-playbook site.yml -i inventory.yml --ask-vault-pass
Das Playbook erledigt:
- Agent-Binary cross-kompilieren (lokal,
GOOS=linux GOARCH=arm64) - Binary und Konfiguration auf den Zielrechner uebertragen
- systemd-Unit fuer den Agent anlegen und starten
- journald auf RAM-Speicherung konfigurieren (SD-Karte schonen)
- X11-Paketstack und Chromium installieren
- Kiosk-Startskript und systemd-Unit fuer die Anzeige anlegen
Rollen
signage_player– Agent, Konfiguration, systemd-Unit, journaldsignage_display– X11, Chromium, Kiosk-Service
Aktuelle Architekturentscheidungen mit direkter Auswirkung auf Entwicklung
message_wallwird serverseitig in konkrete Screen-Szenen aufgeloest- Kampagnengruppen werden serverseitig in konkrete Screen-Assignments expandiert
playlist_itemshaben im finalen Implementierungsschema keinen direktenscreen_id-Fremdschluessel- Provisionierung wird worker-/jumphost-faehig geplant
- API-Fehler sollen einen einheitlichen Fehlerumschlag nutzen
Empfohlene naechste Implementierungsschritte
Die Punkte 1–4 der urspruenglichen Liste (Fehlerformat, Routing, Status, MQTT) sind umgesetzt.
Offene Punkte aus Phase 6 des Tenant-Feature-Plans (docs/TENANT-FEATURE-PLAN.md):
- Docker-Secret fuer
MORZ_INFOBOARD_ADMIN_PASSWORDincompose/einrichten - Ansible-Variable
morz_admin_passwordals Vault-Variable definieren - Code-Review durch Larry (SQL-Injection, Session-Fixation, bcrypt-Cost, Middleware-Reihenfolge)
- End-to-End-Test-Checkliste in
docs/TEST-CHECKLIST-DEV.mddurchlaufen - Deployment: Image bauen, Migration
002_auth.sqlpruefen, Logs kontrollieren - Langfristig: Netzwerk-, Sync- und Kommandopfade produktionsnah ausbauen
End-to-End-Entwicklungstest (Backend + Agent)
Backend und Agent koennen lokal gegeneinander laufen. Reihenfolge:
- Backend starten (Terminal 1):
cd server/backend
MORZ_INFOBOARD_STATUS_STORE_PATH=/tmp/screen-status.json go run ./cmd/api
- Agent starten (Terminal 2):
cd player/agent
MORZ_INFOBOARD_SCREEN_ID=info01-dev \
MORZ_INFOBOARD_SERVER_URL=http://127.0.0.1:8080 \
go run ./cmd/agent
- Status pruefen:
# JSON-Uebersicht
curl http://127.0.0.1:8080/api/v1/screens/status
# HTML-Diagnoseseite
open http://127.0.0.1:8080/status
# Einzelner Screen
curl http://127.0.0.1:8080/api/v1/screens/info01-dev/status
# Screen loeschen
curl -X DELETE http://127.0.0.1:8080/api/v1/screens/info01-dev/status
Die Datei /tmp/screen-status.json enthaelt nach dem ersten Heartbeat den persistierten Status-Store.
Ergaenzt seit dem ersten Geruest:
Backend-REST-API (statusseite.py, playerstatus.go, messagewall.go):
message_wall-Resolver im Backend fuer Szenen-Aufloesung- Basisendpunkte und
message_wall-Validierung im Backend testseitig breiter abgedeckt POST /api/v1/player/statusmit Laufzeit-, Stale- und Server-Konnektivitaets-Tracking- Player-Status wird im Backend pro Screen in-memory vorgehalten und ueber Endpunkte lesbar gemacht
GET /api/v1/screens/statusfuer Gesamt-Uebersicht mit Query-FilternGET /api/v1/screens/{screenId}/statusfuer Einzelscreen-DetailsDELETE /api/v1/screens/{screenId}/statuszum Loeschen von Screen-Eintraegen- HTML-Diagnoseseite unter
/statusmit Auto-Refresh, Filterung und JSON-Drill-down - Query-Parameter:
q=(Screen-ID-Substring),derived_state=,server_connectivity=,stale=,updated_since=,limit= derived_state(online / degraded / offline) ausstale,server_connectivityundstatusabgeleitet- JSON-Persistenz optional in Datei (
MORZ_INFOBOARD_STATUS_STORE_PATH)
Backend-Datenverwaltung (manage/register.go, manage/playlist.go, manage/media.go):
- PostgreSQL-Anbindung mit
DATABASE_URL-Konfiguration - Agent-Selbstregistrierung ueber
POST /api/v1/manage/register - Playlist-Verwaltung und -Abruf (
GET /api/v1/manage/playlists/...) - Medien-Upload und Speicherverwaltung in
MORZ_INFOBOARD_UPLOAD_DIR - Admin-UI mit HTML-Templates fuer Playlist und Medien-Management
Agent-Funktionalitaeten (player/agent/):
- dateibasierte Agent-Konfiguration (
config.json) zusaetzlich zu Env-Overrides - strukturierte Agent-Logs mit internem Health-Snapshot und signalgesteuertem Shutdown
- periodischer HTTP-Status-Reporter fuer Server-Registrierung
- Server-Connectivity-Zustand (
unknown,online,degraded,offline) - HTTP-Statuspfad transportiert
statusundserver_connectivity - MQTT-Heartbeat (optional; wird uebersprungen wenn kein Broker konfiguriert)
- MQTT-Authentifizierung mit Username und Password
- Player-UI unter
/player(HTML-Kiosk) und/api/now-playing(JSON) - Playlist-Rotation und lokale Playlist-Verwaltung
Infrastruktur und Deployment:
- vollstaendiger Compose-Stack (
compose/server-stack.yml) mit PostgreSQL 17, Mosquitto, Backend-Service und Health-Checks - Ansible-Rollen
signage_playerundsignage_displayfuer vollstaendiges Deployment - journald auf volatile Storage konfiguriert (SD-Karte schonen)
- Cross-Compile fuer ARM64 im Ansible-Playbook
- systemd-Units fuer Agent und Kiosk-Display
Arbeitsweise
Empfohlen:
- kleine, klar umrissene Commits
- zuerst Konzepte anpassen, dann Code
- Schema und API-Vertrag synchron halten
- neue Fachentscheidungen immer in
docs/dokumentieren
Hinweise fuer einen zweiten Entwicklungsrechner
- vor Arbeitsbeginn
git pull --rebaseoder gleichwertig den aktuellen Stand holen - bei paralleler Arbeit zuerst in den Dokumenten pruefen, ob neue Architekturentscheidungen getroffen wurden
- falls lokale Tools abweichen, mindestens
go versionundmake --versionpruefen