Installation mit Docker
Tunetorch kommt als Docker-Image. Datenbank, Cache und FFmpeg sind schon enthalten, du brauchst also nur Docker, am besten mit Docker Compose.
Schnellstart
Lege eine Datei docker-compose.yml an:
services:
tunetorch:
image: tunetorch/tunetorch:latest
container_name: tunetorch
restart: unless-stopped
ports:
- "5000:5000"
volumes:
# Datenverzeichnis. Bitte regelmäßig sichern.
- ./tunetorch-daten:/app/data
# Optional: vorhandener Musikordner zum Scannen (immer read-only).
# - /pfad/zu/deiner/musik:/app/musik:ro
# Optional: Sammlung für den einmaligen Start-Import.
# - /pfad/zu/deiner/sammlung:/app/import:ro
# Passend für den direkten Zugriff per HTTP, wie ihn dieser Schnellstart
# beschreibt. Hinter einem TLS-Reverse-Proxy beide Zeilen wieder
# entfernen (siehe unten).
environment:
TT_HTTPS: "False" # kein TLS: Cookies ohne Secure-Flag
TT_TRUSTED_PROXIES: "0" # kein Proxy davor
# TT_PUID: "1000" # UID des Volume-Eigentümers
# TT_PGID: "1000" # GID des Volume-Eigentümers
Starten:
docker compose up -d
Die Weboberfläche erreichst du danach unter http://<server-adresse>:5000. Beim ersten Login
meldest du dich mit admin / BITTE_ÄNDERE_MICH an. Tunetorch verlangt sofort ein neues
Passwort (siehe Erste Schritte).
Die Volumes im Detail
| Pfad im Container | Pflicht | Zweck |
|---|---|---|
/app/data | ja | Datenbank, hochgeladene Audiodateien, Cover, Bilder, Logs, Anmelde-Schlüssel, Cache. Dieses Verzeichnis musst du sichern. |
/app/musik | nein | Ein bestehender Musikordner, den der Bibliothek-Scan einliest. Immer mit :ro einhängen. Tunetorch schreibt nie in deine Musikbibliothek. |
/app/import | nein | Eine bestehende Sammlung für den einmaligen Start-Import. Ebenfalls :ro. Nach dem Import kannst du die Zeile wieder entfernen. |
/app/data kannst du als Bind-Mount (./tunetorch-daten:/app/data) oder als
benanntes Volume (tunetorch_daten:/app/data) einhängen. Beim Bind-Mount solltest du
TT_PUID/TT_PGID auf deinen Host-Benutzer setzen (id -u / id -g), damit du auch vom
Host aus hineinschreiben kannst.
Beim Start übergibt der Container
/app/dataautomatisch an die eingestellte UID:GID. Ein Ordner, denrootangelegt hat, wird dadurch von selbst beschreibbar. Klappt das nicht (etwa wegen ACLs auf einer Synology), bricht der Start mit einer[entrypoint] FEHLER:-Meldung ab.
Nur Docker, ohne Compose
docker run -d \
--name tunetorch \
--restart unless-stopped \
-p 5000:5000 \
-v $(pwd)/tunetorch-daten:/app/data \
tunetorch/tunetorch:latest
Ein bereitgestelltes Image laden
Hast du das Image als Archiv bekommen:
docker load -i tunetorch-<VERSION>.tar.gz
Im Archiv heißt das Image tunetorch:<VERSION>-<arch>, die Compose-Datei oben erwartet aber
tunetorch/tunetorch:latest. Du musst es deshalb umbenennen. Sonst scheitert der Start mit
„image not found", und der Grund dafür ist nicht zu sehen:
docker tag tunetorch:<VERSION>-amd64 tunetorch/tunetorch:latest
Aktualisieren
docker compose pull
docker compose up -d
Deine Daten in /app/data bleiben erhalten. Änderungen an der Datenbank spielt Tunetorch
beim Start selbst ein, du musst nach einem Update nichts von Hand erledigen.
Vor größeren Updates lohnt sich ein Backup des Datenverzeichnisses. Siehe Sicherheit & Datensicherung.
Betrieb hinter einem TLS-Reverse-Proxy
Der Schnellstart oben ist für den direkten Zugriff per HTTP eingestellt. Dafür sind die
beiden Zeilen TT_HTTPS: "False" und TT_TRUSTED_PROXIES: "0" da. Läuft Tunetorch hinter
einem Reverse-Proxy mit TLS (Caddy, Traefik, Nginx Proxy Manager), entferne beide
wieder. Die Standardwerte True und 1 sind für genau diesen Fall gedacht. Der Proxy muss
dabei X-Forwarded-Proto: https weitergeben, daran erkennt Tunetorch die verschlüsselte
Verbindung.
Der Grund liegt im Umgang der Browser mit Cookies: Mit TT_HTTPS: "True" bekommen die
Anmelde-Cookies das Secure-Flag. Rufst du Tunetorch dann über http:// auf, verwirft der
Browser sie ohne Meldung. Die Anmeldung scheint fehlzuschlagen, obwohl der Server sie
angenommen hat. Im Server-Log steht dann eine Warnung, die genau das beschreibt.
Die Falle bei der Ersteinrichtung: Über
http://localhost:5000akzeptieren Chrome, Edge und FirefoxSecure-Cookies trotzdem, weil localhost für sie als sicher gilt. Wer Tunetorch direkt auf dem Server einrichtet, merkt eine falsche Einstellung deshalb nicht. Erst der Zugriff von einem zweiten Gerät über die LAN-Adresse scheitert.
Wenn du die Wahl hast, nimm TLS. TT_HTTPS: "False" ist die Lösung fürs Heimnetz ohne
Zertifikat, nicht die bessere Betriebsart.
Mehr dazu unter Konfiguration.
Synology DSM
Auf Synology-Systemen gehört ein freigegebener Ordner oft nicht 1000:1000, sondern zum
Beispiel 1026:100. Prüfe die Werte auf dem Host mit ls -ln im Volume-Verzeichnis und
trage sie ein:
environment:
TT_PUID: "1026"
TT_PGID: "100"
Wenn eine ACL den automatischen Eigentümerwechsel überstimmt, gib dem Benutzer mit dieser UID in der File Station zusätzlich ausdrücklich Schreibrecht.
Zwei weitere Eigenheiten von DSM kosten beim ersten Start oft Zeit: Port 5000 gehört der
DSM-Oberfläche (wähle einen anderen Host-Port), und ein freigegebener Ordner, den du als
/app/import oder /app/musik einhängst, ist für den Container nicht automatisch
lesbar. Dass du ihn selbst in der File Station öffnen kannst, heißt dabei nichts. Beides
samt Prüfbefehl steht auf der Seite Synology NAS (DSM).
Speicher für DLNA-Casting (optional)
Nutzt du DLNA-Casting mit Lautheits-Angleichung oder einem Ziel-Format, legt der Server kurzlebige Kopien des laufenden Titels an. Wo, entscheidet er selbst: am liebsten im Arbeitsspeicher, sonst auf dem Datenträger. Du musst dafür also nichts einstellen.
Hat dein Server reichlich RAM, kannst du die Kopien gezielt in den Arbeitsspeicher legen und so der SD-Karte oder SSD Schreibvorgänge ersparen:
shm_size: "1g"
Das ist eine Obergrenze, keine Reservierung. Solange der Platz nicht gebraucht wird, kostet er nichts. Auf einem Raspberry Pi ist RAM allerdings knapper als Schreibzyklen, dort ist die Voreinstellung meist die bessere Wahl.
CD-Laufwerk durchreichen (optional)
Für das CD-Rippen braucht der Container Zugriff auf ein CD-Laufwerk am Server, eingebaut oder per USB. Die nötigen Programme sind schon im Image, es fehlen nur diese Zeilen:
volumes:
- /dev:/dev
device_cgroup_rules:
- "b 11:* rmw"
group_add:
- "24"
/dev:/devstatt nur/dev/sr0: Ein USB-Laufwerk bekommt bei jedem Einstecken einen neuen Geräteeintrag. Mit einem einzeln durchgereichten Gerät würde der Container gar nicht starten, solange das Laufwerk fehlt.device_cgroup_rulesgibt davon nur CD-Laufwerke frei (/dev/sr*). Festplatten, USB-Sticks und alles andere bleiben für den Container gesperrt.privilegedbrauchst du nicht.group_addist die Gruppe, der das Laufwerk auf dem Host gehört. Auf Debian, Ubuntu und Raspberry Pi OS ist das24(cdrom). Nachsehen kannst du mitstat -c '%g %G' /dev/sr0.
Danach schaltest du das CD-Rippen in den Server-Einstellungen ein. Meldet die Oberfläche
„Kein Zugriff auf das Laufwerk", stimmt fast immer die Zahl bei group_add nicht.
Auf einer Synology NAS helfen diese Zeilen in der Regel nicht: DSM bringt den Treiber für CD-Laufwerke nicht mit, und Tunetorch sieht deshalb kein Laufwerk. Wie du das prüfst und was du stattdessen tun kannst, steht unter Synology NAS (DSM).
Nutzt du zusätzlich DLNA-Casting? Mit /dev:/dev sieht der Container den
Arbeitsspeicher-Ordner des Hosts, und shm_size (siehe oben) wirkt nicht mehr. Die
Casting-Kopien landen dann im RAM. Auf einem Raspberry Pi hältst du sie mit dieser Zeile
unter environment: auf dem Datenträger:
TT_DLNA_TMPFS: "/app/data/temp/dlna"
Raspberry Pi: Achte auf die Stromversorgung. Ein USB-Laufwerk braucht beim Anlaufen der CD kurz mehr Strom, als die USB-Buchsen des Pi liefern. Das zeigt sich nicht als klare Fehlermeldung, sondern als Lesefehler oder als Laufwerk, das mitten im Rip verschwindet. Abhilfe schafft ein Laufwerk mit eigenem Netzteil oder ein aktiver USB-Hub, also einer mit eigenem Netzteil. Ein Y-Kabel an zwei Buchsen des Pi hilft nicht. Auch ein passiver Verteiler, an den du zusätzlich ein Handy-Netzteil steckst, ist keine Lösung: Darin sind die Stromleitungen verbunden, und das Netzteil speist dann auch in den Pi zurück.
Startet dein Pi von einer USB-SSD, gilt das doppelt. SSD und Laufwerk teilen sich dann den Strom der USB-Buchsen. Bricht die Spannung beim Anlaufen der CD ein, kann der Pi kurz seine SSD verlieren und hängen bleiben: Er antwortet noch auf Ping, aber nicht mehr auf SSH oder die Oberfläche. Häng in diesem Fall nur das Laufwerk an den Hub und die SSD weiter direkt an den Pi. Am Hub wäre er eine zusätzliche Stelle, an der dir das Startmedium wegbrechen kann.
Ob die Versorgung reicht, prüfst du nach einem Rip auf dem Pi mit vcgencmd get_throttled.
throttled=0x0 heißt: Die Spannung ist seit dem Start nie eingebrochen.
Gesundheitsprüfung
Das Image bringt einen HEALTHCHECK mit, der alle 30 Sekunden prüft, ob der Server antwortet.
docker ps zeigt den Container dadurch als healthy oder unhealthy. So erkennst du auch
einen hängenden Server, den restart: unless-stopped allein nicht bemerken würde.
Der Start dauert je nach Hardware bis zu einer Minute (auf einem NAS waren es 44
Sekunden), weil Redis, Datenbankprüfung und Server nacheinander hochfahren. In dieser Zeit
gilt der Container noch nicht als healthy, und ein „Bad Gateway“ vom Reverse-Proxy ist
normal. Es verschwindet von selbst. Bleibt es, liegt die Ursache woanders, siehe
Fehlerbehebung.
docker ps
docker compose logs -f tunetorch
Nächster Schritt
- Konfiguration: Umgebungsvariablen und Server-Einstellungen
- Bibliothek befüllen: Musik hineinbringen