medialab Server in einem Container installieren
medialab Server wird als Container-Image für linux/amd64 und linux/arm64 veröffentlicht:
ghcr.io/cristiancasapu/medialab-server
Das Image wird aus denselben signierten Debian-Paketen gebaut wie das apt-Repository (medialab-server,
medialab-server-web, jellyfin-ffmpeg8); seine Build-Dateien sind öffentlich auf
github.com/CristianCasapu/medialab-server-docker (GPL-2.0).
Tags:
| Tag | Bedeutung |
|---|---|
12.2-ml.10 |
eine Version; empfohlen, wenn du selbst bestimmen willst, wann du aktualisierst |
12.2 |
die neueste Version auf Basis von Jellyfin 12.2 |
latest |
die neueste Version |
12.2-ml10-deb12 |
die exakte apt-Version im Image |
Was du brauchst
- Docker (oder Podman, Unraid, Portainer, Kubernetes) auf einem 64-Bit-x86- oder ARM-Rechner.
- Ein Ordner für die Einstellungen (
/config), einer für den Cache (/cache) und dein Medienordner (/media). - Die numerische UID und GID, die Eigentümer der Einstellungen sein soll:
id -uundid -gdieses Kontos (PUID,PGID).
docker run
docker run -d --name medialab-server --restart unless-stopped \
-p 8096:8096 -p 7359:7359/udp \
-v /srv/medialab/config:/config \
-v /srv/medialab/cache:/cache \
-v /srv/media:/media:ro \
-e PUID=1000 -e PGID=1000 -e TZ=Europe/Bucharest \
ghcr.io/cristiancasapu/medialab-server:latest
Öffne http://<server>:8096. Auf einem neuen Server fragt der Einrichtungsassistent nach dem ersten Administrator,
der Sprache und deinen Bibliotheken (füge sie aus /media hinzu).
Um den Assistenten zu überspringen, lass den Container den Administrator anlegen. Schreib das Passwort in eine Datei, nicht in die Befehlszeile:
printf '%s' 'a-long-password' > /srv/medialab/admin_password
docker run -d ... \
-v /srv/medialab/admin_password:/run/secrets/admin_password:ro \
-e MLW_ADMIN_USER=admin \
-e MLW_ADMIN_PASSWORD_FILE=/run/secrets/admin_password \
ghcr.io/cristiancasapu/medialab-server:latest
Das funktioniert nur auf einem neuen Server; auf einem bereits eingerichteten Server werden die Variablen ignoriert. Das Passwort erscheint nie in den Container-Logs.
Docker Compose
compose.yaml:
services:
medialab-server:
image: ghcr.io/cristiancasapu/medialab-server:12.2-ml.10
container_name: medialab-server
restart: unless-stopped
ports:
- "8096:8096"
- "7359:7359/udp"
volumes:
- ./config:/config
- ./cache:/cache
- /srv/media:/media:ro
environment:
PUID: 1000
PGID: 1000
TZ: Europe/Bucharest
MLW_SERVER_NAME: Home media
MLW_ADMIN_USER: admin
MLW_ADMIN_PASSWORD_FILE: /run/secrets/admin_password
secrets:
- admin_password
secrets:
admin_password:
file: ./secrets/admin_password
mkdir -p secrets && printf '%s' 'a-long-password' > secrets/admin_password
docker compose up -d
docker compose logs -f
Ein vollständiges Beispiel mit einer .env-Datei liegt im Repository (examples/compose.yaml, examples/.env.example).
Unraid
- Wähle im Docker-Tab Add Container und setze Template auf die URL
https://raw.githubusercontent.com/CristianCasapu/medialab-server-docker/main/examples/unraid/medialab-server.xml(oder kopiere die Datei nach/boot/config/plugins/dockerMan/templates-user/). - Prüfe die Pfade:
/config→/mnt/user/appdata/medialab-server,/media→ deine Medienfreigabe. PUID99 undPGID100 sind die üblichen Unraid-Werte (nobody / users).- Intel- oder AMD-GPU: Füge
--device=/dev/drizu Extra Parameters hinzu und setze Hardware acceleration aufqsvodervaapi. NVIDIA: Installiere das Nvidia-Driver-Plugin, füge--runtime=nvidiahinzu und setze es aufnvenc. - Auf Apply, dann die WebUI öffnen.
Portainer
- Stacks → Add stack → Web editor und füge
examples/portainer/stack.ymlaus dem Repository ein. - Lade unter Environment variables
examples/portainer/stack.env(oder füge die Variablen von Hand hinzu) und passe die Pfade,PUID,PGIDundTZan. - Deploy the stack.
Portainer-Stacks können auf einem eigenständigen Host keine Docker-Secrets nutzen; das Beispiel übergibt
MLW_ADMIN_PASSWORD daher als Stack-Variable. Sie wird nur einmal verwendet; du kannst sie nach dem ersten Start löschen.
Kubernetes
examples/kubernetes/medialab-server.yaml enthält eine ConfigMap, zwei PersistentVolumeClaims, ein Deployment (ein
Replikat, Strategie Recreate, Health-Probes auf /health), einen Service und einen Ingress:
kubectl create namespace medialab
kubectl -n medialab create secret generic medialab-secrets \
--from-literal=admin-password='a-long-password' --from-literal=license-key='' --from-literal=repo-key=''
kubectl -n medialab apply -f medialab-server.yaml
Passe zuerst die Speichergrößen, das Medien-Volume (ein NFS-Beispiel ist enthalten) und den Hostnamen an. Betreibe nur
ein Replikat: Der Server legt seine Datenbank in /config ab.
Hardware-Beschleunigung
Intel (QSV / VAAPI) und AMD (VAAPI)
docker run ... --device /dev/dri:/dev/dri -e MLW_HW_ACCEL=qsv ... # Intel
docker run ... --device /dev/dri:/dev/dri -e MLW_HW_ACCEL=vaapi ... # AMD or older Intel
Der Container fügt den Server-Benutzer selbst den Gruppen hinzu, denen /dev/dri/* gehört; du musst also nicht die
Gruppennummern von render und video nachschlagen. Die Treiber kommen mit jellyfin-ffmpeg8; das amd64-Image enthält
außerdem Intels OpenCL-Runtime aus Debian 12 für HDR-Tone-Mapping (sehr neue Intel-GPUs brauchen eventuell eine neuere
Runtime, als Debian 12 sie enthält).
NVIDIA (NVENC / NVDEC)
Installiere den NVIDIA-Treiber und das NVIDIA Container Toolkit auf dem Host, dann:
docker run ... --gpus all -e MLW_HW_ACCEL=nvenc ...
Füge bei Compose examples/compose.nvidia.yaml hinzu; fordere in Kubernetes nvidia.com/gpu: 1 an.
Prüfe nach dem ersten Start Dashboard → Playback → Transcoding und spiele ein Video ab, das transkodiert werden muss;
das ffmpeg-Log in /config/log zeigt, ob die GPU genutzt wurde.
Plugins, Einstellungen und Lizenzen von außen
Alles Folgende ist optional; die vollständige Liste der Variablen steht in docs/ENVIRONMENT.md im Repository.
Server-Einstellungen. Zum Beispiel:
-e MLW_PUBLISHED_URL=https://media.example.org \
-e MLW_KNOWN_PROXIES=172.16.0.0/12 \
-e MLW_UI_CULTURE=en-US -e MLW_METADATA_COUNTRY=US \
-e MLW_REMOTE_ACCESS=true
Sie werden vor dem Start des Servers in system.xml, network.xml und encoding.xml geschrieben. Mit der
Voreinstellung MLW_CONFIG_MODE=first-run wird ein Wert auf einem neuen Server geschrieben und danach nur noch, wenn du
die Variable änderst; was du später im Dashboard änderst, bleibt also erhalten. MLW_CONFIG_MODE=enforce schreibt sie bei
jedem Start. Jede andere Eigenschaft lässt sich mit MLW_SYSTEM__<Property>, MLW_NETWORK__<Property> und
MLW_ENCODING__<Property> setzen.
Plugin-Katalog. Der öffentliche medialab.works-Katalog und Jellyfins offizielles Repository sind standardmäßig
hinzugefügt (MLW_PLUGIN_REPOS=medialab,jellyfin). Wenn dein Konto einen Repository-Schlüssel hat, füge ihn mit
MLW_REPO_KEY (oder MLW_REPO_KEY_FILE) hinzu; er wird in den Logs maskiert.
Plugins. Liste sie in MLW_PLUGINS auf; sie werden installiert, bevor der Server startet:
-e MLW_PLUGINS="jf-rosub,jf-registration@1.0.2"
Ein Plugin wird über seinen Slug (jf-rosub), seinen Namen oder seine GUID gefunden; @version stellt eine Version
fest. Das Archiv wird anhand der Prüfsumme im Katalog überprüft, und die medialab-Signatur (.dll.sig) bleibt erhalten,
sodass das Dashboard das Plugin als verifiziert anzeigt. Bereits installierte Plugins werden nicht erneut
heruntergeladen; MLW_PLUGINS_UPDATE=true installiert beim Start neuere Versionen.
Plugin-Einstellungen. Hänge entweder die Konfigurationsdatei des Plugins ein
(/config/plugins/configurations/<Assembly>.xml, z. B. Rosub.xml) oder setze einzelne Werte:
-e MLW_PLUGIN_ROSUB__ArchiveCacheDays=14
Lizenzschlüssel. MLW_LICENSE_KEY, MLW_LICENSE_KEY_<SLUG> (z. B. MLW_LICENSE_KEY_JF_ROSUB), ihre _FILE-Formen
und Docker-Secrets namens mlw_license_key oder mlw_license_key_<slug> werden unverändert an den Server-Prozess
übergeben. Plugins lesen sie daraus in den Plugin-Versionen, die das unterstützen; bei einer älteren Plugin-Version gibst
du den Schlüssel auf der Plugin-Seite im Dashboard ein (er wird in /config gespeichert).
Jede Variable akzeptiert auch <NAME>_FILE=/path/to/file, für Docker- und Kubernetes-Secrets.
Updates
Lade das neue Image herunter und erstelle den Container neu; die Einstellungen in /config bleiben erhalten:
docker pull ghcr.io/cristiancasapu/medialab-server:12.2-ml.10
docker stop medialab-server && docker rm medialab-server
docker run -d ... ghcr.io/cristiancasapu/medialab-server:12.2-ml.10 # dieselben Optionen wie zuvor
Mit Compose: Ändere den Tag in compose.yaml (oder behalte latest bei), dann
docker compose pull && docker compose up -d. Auf Unraid: Check for Updates im Docker-Tab. In Portainer:
Recreate mit Re-pull image.
Der In-App-Updater des Debian-Pakets ist nicht Teil des Images. Self-Update by MediaLab zeigt
die verfügbaren Versionen in einem Container an, installiert aber keine Pakete; aktualisiere, indem du den neuen
Image-Tag (12.2-ml.N) lädst und den Container neu erstellst.
Backup
/config enthält alles Wichtige (Einstellungen, Benutzer, Datenbank, Plugins, Metadaten). Stoppe den Container und
sichere den Ordner:
docker stop medialab-server
tar -C /srv/medialab -czf medialab-config-$(date +%F).tar.gz config
docker start medialab-server
/cache kann neu aufgebaut werden und braucht kein Backup. Zum Wiederherstellen lege config wieder an seinen Platz
und starte denselben Image-Tag oder einen neueren.
Fehlerbehebung
- Sieh nach, was der Container gemacht hat:
docker logs medialab-server. Zeilen, die mit[medialab]beginnen, stammen vom Startskript des Containers (geschriebene Einstellungen, installierte Plugins, angelegter Administrator). - Der Container stoppt sofort mit
[medialab] ERROR: Eine Variable hat einen ungültigen Wert; die Meldung nennt sie. - „Permission denied“:
PUID/PGIDpassen nicht zum Eigentümer der Ordner. Der Container korrigiert/configund/cacheselbst, niemals/media. Wurde er mit--usergestartet, ändert er nichts: Die Ordner müssen bereits diesem Benutzer gehören. - Eine Einstellung aus der Umgebung wird nicht übernommen: Im Modus
first-runwird ein Wert auf einem neuen Server geschrieben oder wenn er sich ändert. NutzeMLW_CONFIG_MODE=enforce, um ihn zu erzwingen. - Ein Plugin wird nicht installiert: Das Log sagt warum (Katalog nicht erreichbar, Name nicht gefunden, Prüfsumme
stimmt nicht, keine Version für diesen Server). Der Server startet trotzdem, außer bei
MLW_PLUGINS_STRICT=true. - Der Container wird als unhealthy angezeigt: Der Health-Check ruft
/healthauf Port 8096 (oder dem Port und der Basis-URL innetwork.xml) auf. Der erste Start kann ein bis zwei Minuten dauern. - Hinter einem Reverse Proxy bekommen Clients die falsche Adresse: Setze
MLW_KNOWN_PROXIESauf die Adresse des Proxys undMLW_PUBLISHED_URLauf die öffentliche URL.