Dialoge statt Blöcke, bessere Filter, ein Dashboard — und eine NAS-Anleitung

**Was etwas anlegt oder ändert, steht jetzt in einem Dialog.** Das Formular
zum Anlegen einer Mediathek nahm als Block in der Seite Platz für etwas weg,
das man einmal im Monat braucht — und sah aus wie eine Eingabe, die noch
aussteht. Dasselbe für Benutzer, Umbenennen, den Servernamen und die
Metadaten-Einstellungen.

Gebaut mit dem `<dialog>` des Browsers, nicht mit einem nachgebauten: Escape
schliesst, der Hintergrund wird unbedienbar, der Tastaturfokus bleibt
gefangen, Vorlesesoftware kündigt ihn als Dialog an. Jede Zeile, die das
selbst baut, ist eine Zeile, die es schlechter kann. Scheitert das
Speichern, bleibt der Dialog offen — ihn zu schliessen hiesse, die Eingabe
wegzuwerfen und die Meldung dorthin zu schreiben, wo gerade niemand hinsieht.

**Die Filter sehen nicht mehr nach Eingabe aus.** Bei Plex stehen dort
Wörter mit einem kleinen Pfeil; ein umrandetes Auswahlfeld sagt „hier fehlt
noch etwas", und das stimmt nicht. Gesetzte Filter werden farbig, daneben
steht die Anzahl, und „Filter zurücksetzen" erscheint nur, wenn es etwas
zurückzusetzen gibt. Dazu neu: gesehen / noch nicht gesehen.

Das siebt vorerst in der Oberfläche, nicht am Server — er kann es noch
nicht. Der Preis steht in der Zahl daneben: sie zeigt dann „3 von 7".

---

**„Wird abgespielt" — wer gerade was schaut.**

Abgeleitet aus den Fortschrittsmeldungen, nicht aus einer eigenen Anmeldung
am Spieler: jeder Client meldet beim Abspielen ohnehin alle zehn Sekunden,
wo er steht. Wer das als Lebenszeichen liest, braucht kein zweites
Verfahren, das ein Client vergessen könnte — bleibt die Meldung aus, läuft
der Eintrag nach einer Minute von selbst ab.

Im Arbeitsspeicher, nicht in der Datenbank: „wer schaut gerade was" ist eine
Frage über den Augenblick. Nach einem Neustart lautet die Antwort „niemand",
und das zu speichern hiesse, Wiedergaben anzuzeigen, die es nicht gibt.

Zwei Geräte desselben Menschen sind zwei Zeilen — derselbe Mensch kann auf
dem Fernseher und auf dem Telefon gleichzeitig etwas laufen lassen.
Geschlüsselt wird deshalb über das Gerätetoken, nicht über den Benutzer und
nicht über den Gerätenamen: zwei iPhones heissen beide „iPhone".

**Nur für Administratoren.** Wer wann welchen Film anschaut, ist eine
Auskunft über Menschen, nicht über den Server. In einem Haushalt mag das
harmlos sein; die Vorgabe eines offenen Projekts darf es trotzdem nicht sein.

Der Spieler meldet beim Schliessen ausdrücklich „beendet". Ohne das stünde
ein geschlossener Film noch eine Minute als „läuft" — und wer gerade den
Spieler zugemacht hat, sähe sich selbst beim Schauen zu.

---

**`docs/NAS-EINRICHTEN.md`** beantwortet die Frage, die offen war: **es ist
ein einziges Image.** Die Weboberfläche wird beim Bauen hineingelegt und vom
Server selbst ausgeliefert — ein Container, drei Volumes, kein Proxy, keine
Datenbank daneben.

Drei Wege aufs NAS: über die Container-Registry deines Gitea (die läuft —
nachgeprüft), als Datei über `docker save`, oder dort bauen. Dazu der
Schritt, den man am leichtesten überspringt und am teuersten bezahlt: die
Architektur. Ein Mac baut ohne Angabe arm64, ein Intel-NAS braucht amd64,
und `exec format error` sagt das nicht deutlich.

Eine Zahl darin war geraten und ist korrigiert: `docker save | gzip` ergibt
nicht 90 MB, sondern 230 — die Ebenen eines Images sind bereits gepackt.

378 Tests grün, sechs davon neu.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Scarriffle
2026-10-04 08:03:07 +02:00
co-authored by Claude Opus 5
parent a7ec3a73ba
commit f2b5ee633b
17 changed files with 1394 additions and 194 deletions
+249
View File
@@ -0,0 +1,249 @@
# Flaro auf dem NAS einrichten
Für ein UGREEN-NAS mit der mitgelieferten Docker-App, und für jedes andere
System, auf dem Docker Compose läuft.
## Die kurze Antwort auf „ein Image oder mehrere?"
**Ein einziges.** Die Weboberfläche wird beim Bauen mit hineingelegt und vom
Server selbst ausgeliefert; es gibt keinen zweiten Container, keine Datenbank
daneben, keinen Proxy davor. Ein Container, drei Volumes, fertig.
```
flaro:<fassung> 231 MB
├── .NET-Laufzeit + Flaro
├── wwwroot/ die Weboberfläche
└── ffmpeg + VAAPI-Treiber
```
---
## Schritt 1: Die Architektur bestimmen
**Das ist der Schritt, den man am leichtesten überspringt und am teuersten
bezahlt.** Ein Image für `arm64` läuft auf einem Intel-NAS nicht, und die
Fehlermeldung (`exec format error`) sagt das nicht deutlich.
Auf dem NAS, über SSH oder die Konsole der Docker-App:
```bash
uname -m
```
| Ausgabe | Architektur | Was du bauen musst |
|---|---|---|
| `x86_64` | amd64 | `--platform linux/amd64` |
| `aarch64` | arm64 | `--platform linux/arm64` |
Die meisten UGREEN-Geräte mit Intel-Prozessor (N100, i5) melden `x86_64`.
Ein Mac baut ohne Angabe **arm64** — also gehört die Angabe dazu.
---
## Schritt 2: Das Image auf das NAS bringen
Drei Wege. Der erste ist der bequemste, der zweite braucht keine Registry.
### Weg A — über die Registry deines Gitea (empfohlen)
Dein Gitea unter `git.scarriffle.com` bringt eine Container-Registry mit.
Einmal einrichten, danach ist jedes Update ein `docker compose pull`.
Auf dem Arbeitsrechner:
```bash
docker login git.scarriffle.com
```
```bash
cd ~/Projects_Coding/Flixy
docker buildx build --platform linux/amd64 \
-f server/Dockerfile \
-t git.scarriffle.com/scarriffle/flaro:latest \
--push .
```
`--push` lädt direkt hoch; ein getrenntes `docker push` entfällt.
Auf dem NAS dann in der Compose-Datei:
```yaml
image: git.scarriffle.com/scarriffle/flaro:latest
```
Ist das Paket in Gitea **privat**, muss sich auch das NAS anmelden:
```bash
docker login git.scarriffle.com
```
Einfacher ist, das Paket in Gitea auf öffentlich zu stellen — unter
*Pakete → flaro → Einstellungen*. Der Quelltext ist ohnehin offen; das Image
enthält nichts, was es nicht auch tut.
### Weg B — als Datei hochladen
Ohne Registry, dafür bei jedem Update von Hand.
```bash
docker buildx build --platform linux/amd64 \
-f server/Dockerfile -t flaro:latest --load .
```
```bash
docker save flaro:latest | gzip > flaro.tar.gz
```
Das ergibt rund **230 MB** — gemessen, nicht geschätzt. Das `gzip` bringt
dabei fast nichts: die Ebenen eines Docker-Images sind bereits gepackt.
Die Datei über die Dateiverwaltung auf das NAS legen, dann dort:
```bash
docker load < /volume1/docker/flaro.tar.gz
```
In der Compose-Datei steht dann schlicht `image: flaro:latest`.
### Weg C — auf dem NAS bauen
Geht, lohnt sich aber selten: der Bau braucht den Quelltext, Node, das
.NET-SDK als Zwischenschritt und ordentlich Arbeitsspeicher. Die Docker-App
von UGREEN kann `build:` in einer Compose-Datei ausserdem nicht immer.
---
## Schritt 3: Die Compose-Datei
```yaml
services:
flaro:
image: git.scarriffle.com/scarriffle/flaro:latest
container_name: flaro
restart: unless-stopped
ports:
- "8096:8080"
environment:
- TZ=Europe/Zurich
# Schreibt Plakate und NFO neben die Mediendateien. Ohne das bleibt
# der Medienordner unangetastet.
- FLARO_WRITE_SIDECARS=true
volumes:
# Datenbank und Konfiguration. **Das ist das Volume, das du sichern
# musst** — darin stehen Benutzer, Zuordnungen und Sehfortschritt.
- /volume1/docker/flaro/config:/config
# Heruntergeladene Plakate. Verlierbar: wird neu geholt.
- /volume1/docker/flaro/cache:/cache
# Umgepackte Dateien. Ebenfalls verlierbar, kann aber gross werden.
- /volume1/docker/flaro/transcode:/transcode
# Die Medien. Links der Pfad auf dem NAS, rechts der im Container —
# und **rechts** ist der, den du in Flaro einträgst.
- /volume1/Medien/Filme:/media/Filme
- /volume1/Medien/Serien:/media/Serien
# Hardware-Beschleunigung. Weglassen, wenn das NAS keine hat.
devices:
- /dev/dri:/dev/dri
```
### Rechte
Der Container läuft als Benutzer `1000:1000` — der erste Benutzer auf fast
jedem Linux und auf den üblichen NAS-Geräten. Gehören deine Ordner jemand
anderem, setz es ausdrücklich:
```yaml
user: "1001:100"
```
Welche Kennung gilt, sagt auf dem NAS:
```bash
id
```
### Der Port
`8096` ist frei gewählt. Läuft dort schon Jellyfin, nimm etwas anderes —
links die Zahl, unter der du Flaro erreichst, rechts bleibt `8080`.
---
## Schritt 4: Starten und einrichten
```bash
docker compose up -d
```
Dann im Browser `http://<nas>:8096` öffnen. Es erscheint der
Einrichtungsassistent:
1. **Administratorkonto** anlegen — Benutzername und Passwort, mindestens
acht Zeichen.
2. Unter **Verwaltung → Mediatheken** eine Mediathek hinzufügen. Beim Ordner
gehört der Pfad **im Container** hinein, also `/media/Filme`, nicht
`/volume1/Medien/Filme`.
3. **Scannen.** Der Scan liest die Dateien, danach holt Flaro die Metadaten.
4. Unter **Verwaltung → Server → Metadaten** die Sprache einstellen, etwa
`de-DE`. Danach einmal **Metadaten auffrischen** — vorhandene Titel
ändern sich sonst nicht.
---
## Sichern
Was unersetzlich ist, liegt in **einem** Verzeichnis:
```
/volume1/docker/flaro/config/
```
Darin: die SQLite-Datenbank mit Benutzern, Zuordnungen, Sehfortschritt und
Einstellungen. Eine Kopie dieser Datei ist die ganze Sicherung — kein
Datenbank-Dump, kein Export.
`cache` und `transcode` dürfen weg; beides baut sich neu auf.
**Die Mediendateien fasst Flaro nicht an.** Es liest sie, und es legt —
sofern `FLARO_WRITE_SIDECARS=true` gesetzt ist — Plakate und NFO-Dateien
daneben. Umbenannt oder gelöscht wird nie etwas; es gibt im ganzen Programm
keine Stelle, die das könnte.
---
## Aktualisieren
Mit Weg A:
```bash
docker compose pull && docker compose up -d
```
Migrationen der Datenbank laufen beim Start von selbst. Ein Rückschritt auf
eine ältere Fassung ist **nicht** vorgesehen — vor einem Sprung lohnt eine
Kopie von `config/`.
---
## Wenn etwas nicht geht
```bash
docker compose logs -f flaro
```
| Zeichen | Ursache |
|---|---|
| `exec format error` | falsche Architektur — siehe Schritt 1 |
| Mediathek bleibt leer | der Pfad in Flaro ist der des NAS statt der im Container |
| „Zugriff verweigert" im Protokoll | Rechte, siehe `user:` oben |
| Keine Plakate, Titel wie Dateinamen | kein TMDB-Zugang oder kein Netz |
| Hardware-Beschleunigung greift nicht | `/dev/dri` nicht durchgereicht |
Ein Gesundheitsendpunkt ohne Anmeldung:
```bash
curl http://<nas>:8096/health
```