Image bauen und veröffentlichen / image (push) Canceled after 0s
Gitea verteilt Arbeit nur, es baut nicht selbst. Der Workflow ist auf dem Server und hat einen Lauf angelegt — der bleibt liegen, weil niemand ihn ausführt. Das ist keine Eigenheit dieser Installation, sondern wie Gitea Actions arbeitet. `server/docker-compose.runner.yml` ist der fehlende Teil, und er gehört **auf das NAS**: dort läuft Docker ohnehin, und damit braucht ein neues Image nie wieder einen Arbeitsrechner. Zwei Dinge darin sind nicht offensichtlich und stehen deshalb als Kommentar daneben: der Docker-Socket ist der Kern — der Runner baut nicht selbst, sondern lässt den Docker des NAS bauen, und wer in diesen Container kommt, kann Docker auf dem NAS steuern. Und `GITEA_RUNNER_LABELS` muss `ubuntu-latest` nennen, weil der Flaro-Workflow genau das in `runs-on` verlangt; ohne die Zeile meldet sich der Runner mit anderen Marken an und der Lauf findet ihn nicht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
287 lines
8.2 KiB
Markdown
287 lines
8.2 KiB
Markdown
# 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`.
|
|
|
|
#### A1 · Gitea baut selbst
|
|
|
|
`.gitea/workflows/image.yml` liegt im Projekt. Bei jedem Push auf `main`
|
|
baut Gitea das Image für **beide** Architekturen und legt es ab — ohne dass
|
|
jemand daran denken muss, und ohne Anmeldung am Arbeitsrechner.
|
|
|
|
**Voraussetzung ist ein registrierter Act-Runner.** Gitea verteilt Arbeit
|
|
nur, es baut nicht selbst: ohne Runner legt es bei jedem Push einen Lauf an,
|
|
der dann liegenbleibt. Nachsehen unter
|
|
*Repo → Einstellungen → Actions → Runner*.
|
|
|
|
Der Runner gehört **auf das NAS** — dort läuft Docker ohnehin, und damit
|
|
braucht es für ein neues Image nie wieder einen Arbeitsrechner. Fertig
|
|
vorbereitet liegt er in `server/docker-compose.runner.yml`; hineingehört nur
|
|
das Registrierungstoken aus derselben Gitea-Seite.
|
|
|
|
Danach erscheint der Runner in der Liste, und der wartende Lauf startet —
|
|
oder spätestens der nächste Push.
|
|
|
|
#### A2 · Von Hand vom Arbeitsrechner
|
|
|
|
Einmalig anmelden — das Passwort tippst du selbst ein:
|
|
|
|
```bash
|
|
docker login git.scarriffle.com
|
|
```
|
|
|
|
Danach genügt ein Befehl; er baut amd64 **und** arm64 und lädt hoch:
|
|
|
|
```bash
|
|
Tools/image-veroeffentlichen.sh
|
|
```
|
|
|
|
Mit einer Fassungsnummer, wenn du sie festnageln willst:
|
|
|
|
```bash
|
|
Tools/image-veroeffentlichen.sh 0.2.0
|
|
```
|
|
|
|
#### A3 · Das Paket öffentlich stellen
|
|
|
|
Sonst muss sich auch das NAS anmelden. In Gitea unter
|
|
*dein Profil → Pakete → flaro → Einstellungen* auf öffentlich stellen. Der
|
|
Quelltext ist ohnehin offen; das Image enthält nichts, was er nicht auch
|
|
enthält.
|
|
|
|
#### A4 · Die Registry im NAS eintragen
|
|
|
|
In der Docker-App des UGREEN: **Repository → Zahnrad → Quellname des
|
|
Images → Hinzufügen**. Dort stehen schon DockerHub und `ghcr.io`; daneben
|
|
kommt:
|
|
|
|
| Feld | Wert |
|
|
|---|---|
|
|
| Alias | `gitea` |
|
|
| Link | `https://git.scarriffle.com/` |
|
|
|
|
**Bestätigen** — danach findet die Suche in der Docker-App auch
|
|
`scarriffle/flaro`. Ist das Paket privat, trägst du unter
|
|
*Registierungseinstellungen* Benutzername und ein Gitea-Zugriffstoken ein
|
|
(nicht dein Kontopasswort: ein Token lässt sich einzeln widerrufen, unter
|
|
*Einstellungen → Anwendungen → Zugriffstoken*, Berechtigung `read:package`).
|
|
|
|
In der Compose-Datei steht dann:
|
|
|
|
```yaml
|
|
image: git.scarriffle.com/scarriffle/flaro:latest
|
|
```
|
|
|
|
### 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
|
|
```
|