61c38a0d14
Ampel / ampel (push) Successful in 28s
Commander-Plan fuer die Uebergabe: "Repo auf den Dockge-Server laden, Compose reinhauen, Profit?!" - und genau da sitzt die Falle, in die jeder zuerst tappt. DER KERN, der jetzt oben im Abschnitt steht: Rippy hat KEINE Registry-Images. api, worker und ui werden aus dem Repo gebaut (build: context: .). Die Compose-Datei allein ist deshalb wertlos - in ein leeres Verzeichnis kopiert gibt es sofort "failed to read dockerfile". Daraus folgt fuer JEDE Oberflaeche dieselbe Regel: das Repo muss dort liegen, wo die Oberflaeche den Stack baut. Je Werkzeug der konkrete Weg, weil sie sich genau darin unterscheiden: - Dockge kann das Repo NICHT selbst holen -> hinein in den Stacks-Ordner klonen (Standard /opt/stacks). Dann ist die Compose des Repos die des Stacks, und man darf den Stack gerade NICHT neu in Dockge anlegen - sonst liegt eine leere Compose in einem anderen Ordner. - Portainer KANN es selbst holen -> Stacks > Add stack > Repository mit Git-URL. Web-Editor und Upload funktionieren nicht (kein Build-Kontext). Geraeteknoten dort als Stack-Umgebungsvariablen statt .env. - Arcane: Repo auf dem Host, Deploy per Shell - der Git-Sync zieht nicht selbststaendig (auf dieser Installation seit Wochen die geuebte Praxis). - Shell: unveraendert git clone + sudo ./install.sh. Dazu die Vorab-Pruefung als gemeinsamer Einstieg: ./install.sh --nur-pruefen braucht kein root, aendert nichts und nennt vor allem die ECHTEN Geraeteknoten - der einzige Punkt, der zuverlaessig zuschlaegt. RICHTIGSTELLUNG an mir selbst: Ich hatte die Mount-Propagation als Huerde dargestellt. Auf den meisten systemd-Hosts ist / schon rshared und /srv/rippy/ media erbt das - da ist nichts zu tun. Nur wenn Docker ueber "not a shared mount" klagt, braucht es die Shell. Steht jetzt so drin. Stoerungstabelle von vier auf sechs Faelle: "failed to read dockerfile" und "Worker startet nicht, /dev/sgN fehlt" ergaenzt - die beiden, die ein Oberflaechen-Nutzer als erste sieht. Interne Verweise gegengeprueft, alle vier loesen auf. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
470 lines
20 KiB
Markdown
470 lines
20 KiB
Markdown
# Rippy — die All-in-one Disc-Ripping-Maschine
|
||
|
||
Disc rein → automatisch erkannt (Titel, Poster, Metadaten) → verlustfrei
|
||
gerippt (MakeMKV) → auf Arbeitsgröße komprimiert (HandBrake) → fertig
|
||
abgelegt, wo du willst (lokal, NAS, jede Freigabe). Modernes Web-UI, komplett
|
||
in Docker, komplett lokal — keine Cloud, keine Telemetrie.
|
||
|
||
---
|
||
|
||
## Installation
|
||
|
||
Du brauchst: einen **Linux-Rechner mit Docker** und ein **optisches Laufwerk**.
|
||
|
||
```bash
|
||
git clone <repo-url> rippy && cd rippy
|
||
sudo ./install.sh
|
||
```
|
||
|
||
Das war es. Am Ende steht die Adresse im Terminal — im Browser öffnen, der
|
||
**Einrichtungs-Assistent** übernimmt den Rest.
|
||
|
||
Zuerst nur nachsehen, ob alles passt, ohne etwas zu ändern:
|
||
|
||
```bash
|
||
./install.sh --nur-pruefen
|
||
```
|
||
|
||
<details>
|
||
<summary><b>Was <code>install.sh</code> für dich macht</b> (aufklappen)</summary>
|
||
|
||
Es nimmt genau die Schritte ab, an denen man vorher scheitern konnte:
|
||
|
||
1. **Prüft die Voraussetzungen** — Linux, Docker, Compose. Fehlt etwas, steht
|
||
der Installationsbefehl dabei.
|
||
2. **Findet dein Laufwerk selbst.** MakeMKV braucht **zwei** Geräteknoten:
|
||
`/dev/srN` und den passenden `/dev/sgM`. Welche sg-Nummer dazugehört, ist
|
||
**je Rechner anders** — das Skript gleicht sie über die SCSI-Adresse ab
|
||
statt zu raten. (Genau daran ging vorher die Handarbeit schief.)
|
||
3. **Legt die Verzeichnisse an** (`/srv/rippy/media` für die Filme,
|
||
`/srv/rippy/makemkv` für MakeMKVs Daten).
|
||
4. **Richtet die Mount-Propagation ein** und macht sie neustart-fest — sonst
|
||
funktioniert das Einhängen von NAS-Freigaben aus dem UI nach jedem Reboot
|
||
nicht mehr.
|
||
5. **Schreibt die `.env`** mit den gefundenen Werten. Bestehende Werte werden
|
||
**nie** überschrieben.
|
||
6. **Baut und startet** alles.
|
||
|
||
Das Skript ist **wiederholbar**: mehrmals ausführen ändert nichts kaputt. Es
|
||
ist auch der Update-Weg — siehe unten.
|
||
|
||
</details>
|
||
|
||
### Aktualisieren
|
||
|
||
```bash
|
||
git pull && sudo ./install.sh
|
||
```
|
||
|
||
---
|
||
|
||
## Mit einer Docker-Oberfläche (Dockge, Portainer, Arcane)
|
||
|
||
**Die eine Sache, die du wissen musst:** Rippy hat **keine fertigen Images in
|
||
einer Registry.** Die drei Dienste `api`, `worker` und `ui` werden aus dem Repo
|
||
gebaut (`build: context: .`). Die Compose-Datei allein ist deshalb wertlos —
|
||
wer sie in ein leeres Verzeichnis kopiert, bekommt sofort
|
||
*„failed to read dockerfile"*.
|
||
|
||
Daraus folgt für **jede** Oberfläche: **das Repo muss dort liegen, wo die
|
||
Oberfläche den Stack baut.** Alles andere ist Kleinarbeit.
|
||
|
||
| | kann das Repo selbst holen? | Weg |
|
||
|---|---|---|
|
||
| **Shell** | — | `git clone` + `sudo ./install.sh` |
|
||
| **Dockge** | nein | Repo **in** den Stacks-Ordner klonen |
|
||
| **Portainer** | **ja** | Stack aus *Repository* (Git-URL) |
|
||
| **Arcane** | nein | Repo auf dem Host, Deploy per Shell |
|
||
|
||
### Vorab-Prüfung — braucht kein root, ändert nichts
|
||
|
||
Egal welche Oberfläche: Führe nach dem Klonen einmal das hier aus. Es sagt dir
|
||
in fünf Sekunden, ob die Maschine passt — vor allem, **welche Geräteknoten dein
|
||
Laufwerk wirklich hat**:
|
||
|
||
```bash
|
||
./install.sh --nur-pruefen
|
||
```
|
||
|
||
### Dockge
|
||
|
||
Dockge verwaltet Stacks als Verzeichnisse. Klone das Repo **in** den
|
||
Stacks-Ordner (Standard `/opt/stacks`, bei dir ggf. anders):
|
||
|
||
```bash
|
||
cd /opt/stacks
|
||
git clone <repo-url> rippy
|
||
cd rippy && ./install.sh --nur-pruefen
|
||
```
|
||
|
||
Dockge zeigt `rippy` danach als Stack an, und „Start" baut die Images. Du musst
|
||
**keine Compose-Datei einfügen** — die des Repos ist die des Stacks. Lege den
|
||
Stack also **nicht** neu in Dockge an, sonst landet eine leere Compose-Datei in
|
||
einem anderen Ordner und der Bau scheitert.
|
||
|
||
### Portainer
|
||
|
||
Portainer kann das Repo selbst klonen, das ist hier der bequemste Weg:
|
||
**Stacks → Add stack → Repository**, Git-URL eintragen, Compose-Pfad
|
||
`docker-compose.yml`. Der Web-Editor und „Upload" funktionieren **nicht** —
|
||
beide liefern keinen Build-Kontext.
|
||
|
||
Die Geräteknoten trägst du als Stack-Umgebungsvariablen ein (statt in eine
|
||
`.env`), falls sie von `/dev/sr0` und `/dev/sg1` abweichen:
|
||
|
||
```
|
||
OPTICAL_SR=/dev/sr0
|
||
OPTICAL_SG=/dev/sg0
|
||
```
|
||
|
||
Welche es sind, sagt dir auf dem Host `lsscsi -g` — oder die Vorab-Prüfung oben.
|
||
|
||
### Arcane
|
||
|
||
Das Repo liegt auf dem Host (z. B. `~/projects/rippy`), Arcane verwaltet die
|
||
Container. Deployt wird per Shell — Arcanes Git-Sync zieht **nicht**
|
||
selbstständig:
|
||
|
||
```bash
|
||
cd ~/projects/rippy && git pull --ff-only && docker compose up -d --build
|
||
```
|
||
|
||
### Was keine Oberfläche für dich tun kann
|
||
|
||
Drei Dinge passieren auf dem **Host**, nicht im Container — deshalb gibt es
|
||
`install.sh` überhaupt:
|
||
|
||
1. **Geräteknoten.** MakeMKV braucht `/dev/srN` **und** den passenden
|
||
`/dev/sgM`; die sg-Nummer ist je Rechner anders. Stimmt sie nicht, **startet
|
||
der Worker-Container gar nicht.** Das ist der Fehler, der praktisch immer als
|
||
erster kommt.
|
||
2. **Ablage-Ordner** `/srv/rippy/media` und `/srv/rippy/makemkv`.
|
||
3. **Mount-Propagation** (`rshared`) für das Einhängen von NAS-Freigaben aus dem
|
||
UI. Auf den meisten systemd-Hosts ist `/` schon `rshared` und es ist nichts
|
||
zu tun — nur wenn `docker compose up` über *„not a shared mount"* klagt,
|
||
braucht es die Shell.
|
||
|
||
Punkt 1 ist der einzige, der zuverlässig zuschlägt. `sudo ./install.sh` erledigt
|
||
alle drei; danach kannst du den Stack dauerhaft über die Oberfläche fahren.
|
||
|
||
---
|
||
|
||
## Wenn etwas nicht geht
|
||
|
||
Die sechs Fälle, die praktisch alles abdecken:
|
||
|
||
| Symptom | Ursache & Lösung |
|
||
|---|---|
|
||
| **`failed to read dockerfile`** | Die Compose-Datei liegt ohne das Repo da. Rippy hat **keine Registry-Images**, die drei Dienste werden gebaut. Siehe **[Mit einer Docker-Oberfläche](#mit-einer-docker-oberfläche-dockge-portainer-arcane)**. |
|
||
| **Worker-Container startet nicht, `/dev/sgN` nicht gefunden** | Die sg-Nummer ist **je Rechner anders**; die Vorgaben `sr0`/`sg1` passen nur zufällig. `./install.sh --nur-pruefen` sagt dir die richtigen (oder `lsscsi -g`), dann in die `.env` bzw. als Stack-Variablen eintragen. **Der Fehler, der praktisch immer als erster kommt.** |
|
||
| **„Kein optisches Laufwerk gefunden"** | In einer **VM**? Das Laufwerk muss per **USB-Passthrough** durchgereicht werden, nicht als emuliertes CD-ROM (`media=cdrom`) — das kann keine SCSI-Kommandos, MakeMKV sieht es nie. Proxmox: `qm set <vmid> -usb0 host=<hersteller>:<produkt>,usb3=1`. Auf echter Hardware: `ls /dev/sr*` prüfen. |
|
||
| **Build bricht beim MakeMKV-Download ab** | Cloudflare drosselt manchmal. Der zuverlässige Weg: Tarballs von makemkv.com/download händisch nach `docker/worker/vendor/` legen, dann `sudo ./install.sh` erneut — der Build nimmt sie von dort und braucht kein Netz. Hast du eine eigene Quelle (Spiegel im LAN), trage sie als `MAKEMKV_URL_FALLBACK` in die `.env` ein; sie wird automatisch versucht, wenn makemkv.com nicht liefert. |
|
||
| **Kompression läuft ewig** | Deine CPU kann kein AVX2. Rippy zeigt das jetzt selbst an (Einstellungen → System, „Vektorbefehle"). Siehe **[Rippy schneller machen](#rippy-schneller-machen)**. |
|
||
| **4K-UHD: „The volume key is unknown"** | Erwartbar und **kein Fehler in Rippy**. Siehe **[4K-UHD](#4k-uhd)**. |
|
||
|
||
Logs ansehen: `docker compose logs -f` · Status: `docker compose ps`
|
||
|
||
---
|
||
|
||
## Rippy schneller machen
|
||
|
||
**Läuft Rippy in einer virtuellen Maschine, ist das hier der wirksamste
|
||
Handgriff überhaupt** — und er kostet fünf Minuten.
|
||
|
||
Virtualisierer geben der VM standardmäßig eine **generische CPU** (bei
|
||
Proxmox/KVM heißt sie `kvm64` bzw. `qemu64`). Die kann absichtlich nur alte
|
||
Befehlssätze, damit sich eine VM zwischen verschiedenen Wirten verschieben
|
||
lässt. Der Preis: **kein AVX2** — und genau davon lebt der Video-Encoder x265.
|
||
|
||
Was das ausmacht, ist auf der Rippy-Maschine gemessen worden: ein 4K-Film in
|
||
H.265 brauchte **28 bis 55 Stunden**, bei voll ausgelasteten Kernen. Mit AVX2
|
||
sind typisch **2- bis 4-mal schneller** drin.
|
||
|
||
**So stellst du es um (Proxmox):**
|
||
|
||
1. VM **herunterfahren.** Ein Neustart von innen genügt nicht — Proxmox
|
||
übernimmt Hardware-Änderungen nur bei einem echten Stopp.
|
||
2. Im Web-UI: VM auswählen → **Hardware** → **Processors** → Doppelklick →
|
||
**Type** auf **`host`** stellen → OK.
|
||
Oder auf der Proxmox-Konsole:
|
||
```bash
|
||
qm set <vmid> --cpu host
|
||
```
|
||
3. VM **starten.**
|
||
|
||
**Nachprüfen — Rippy sagt es dir selbst:** Einstellungen → System, Zeile
|
||
„Vektorbefehle" beim Worker. Steht dort jetzt `avx2` oder `avx512f` statt
|
||
`sse4_2`, hat es geklappt und die amberfarbene Warnung verschwindet.
|
||
Auf der Kommandozeile: `grep -o avx2 /proc/cpuinfo | head -1`.
|
||
|
||
<details>
|
||
<summary>Nachteile von <code>host</code> — der Vollständigkeit halber</summary>
|
||
|
||
Die VM sieht dann die echte CPU. Dadurch lässt sie sich nicht mehr auf einen
|
||
Wirt mit anderem Prozessor **live** verschieben. In einem Heim-Cluster mit
|
||
einem einzigen Wirt ist das ohne Bedeutung. Wer mehrere Wirte hat und
|
||
Live-Migration nutzt, wählt statt `host` das neueste Modell, das **alle**
|
||
Wirte beherrschen (z. B. `x86-64-v3` — das enthält AVX2).
|
||
|
||
</details>
|
||
|
||
**Kein AVX2 möglich?** Dann zwei Auswege, beide im UI:
|
||
- **4K nicht komprimieren** (Einstellungen → Verarbeitung → Preset für 4K-UHD →
|
||
„Nicht komprimieren"). Die verlustfreie Datei bleibt stehen: beste Qualität,
|
||
20–100 GB je Film. Der Einrichtungs-Assistent wählt das bei schwacher CPU
|
||
von selbst.
|
||
- **Andere Maschine komprimieren lassen** — siehe
|
||
[Weitere Maschinen als Worker](#weitere-maschinen-als-worker).
|
||
|
||
---
|
||
|
||
## Der Alltag
|
||
|
||
### Rippen
|
||
|
||
Disc einlegen. Rippy erkennt sie, zeigt Titel und Poster, du wählst das Ziel —
|
||
oder du stellst die **Vollautomatik** an (Einstellungen → Ripping) und es
|
||
läuft ohne Nachfrage los.
|
||
|
||
- **Alle Tonspuren und Untertitel bleiben erhalten** (wichtig für Anime/O-Ton).
|
||
- **Nur Hauptfilm** auf Wunsch — der längste Titel, Extras bleiben weg.
|
||
- **Serien:** Serienname + Staffel angeben → Ablage `<Serie>/Season NN`, und
|
||
die Episoden werden per Laufzeitabgleich (TMDB) zu „Serie S01E02.mkv"
|
||
benannt. Nur bei eindeutiger Zuordnung, sonst bleiben die Namen — mit Log.
|
||
- **Audio-CDs** laufen über abcde zu FLAC mit MusicBrainz-Tags.
|
||
- Schon gerippte Discs erkennt Rippy am Fingerabdruck und warnt.
|
||
- Vor dem Start wird der freie Platz gegen die Disc-Größe geprüft.
|
||
|
||
### Kompression
|
||
|
||
Ein **eigenes Preset je Disc-Typ** (Einstellungen → Verarbeitung) — Rippy
|
||
erkennt den Typ selbst. Das ist wichtig, weil ein 1080p-Preset eine 4K-UHD
|
||
stillschweigend herunterrechnet und eine DVD sinnlos hochskaliert.
|
||
|
||
Jeder Typ kann auch auf **„Nicht komprimieren"** stehen: dann bleibt der
|
||
verlustfreie Rip liegen. Sinnvoll für 4K, wenn die Ablage groß genug ist.
|
||
|
||
Die Rohdatei wird erst nach erfolgreicher Kompression gelöscht („Original
|
||
behalten" als Option). Fehlgeschlagene Kompressionen lassen sich ohne
|
||
Neu-Rip erneut anstoßen.
|
||
|
||
### Ablage & Media-Server
|
||
|
||
Einstellungen → Ripping: dein System wählen (Jellyfin, Emby, Kodi, Plex oder
|
||
keins). Fertige Rips heißen dann „Titel (Jahr)"; für Jellyfin/Emby/Kodi legt
|
||
Rippy zusätzlich `movie.nfo` + `poster.jpg` dazu. Bei **Jellyfin/Emby** mit
|
||
Server-URL + API-Key stößt Rippy nach jedem Rip sofort einen
|
||
Bibliotheks-Scan an — Disc rein, Film erscheint im Server.
|
||
|
||
**NAS-Freigaben** hängst du unter Einstellungen → Speicherziele direkt aus dem
|
||
UI ein (NFS/SMB). Sie erscheinen sofort in der Ziel-Auswahl und werden beim
|
||
Start automatisch wieder verbunden.
|
||
⚠️ Zugangsdaten liegen unverschlüsselt in der lokalen Datenbank — bewusster
|
||
Heimnetz-Kompromiss. Lege fürs NAS einen eigenen, eingeschränkten Benutzer an.
|
||
|
||
### Benachrichtigungen
|
||
|
||
Einstellungen → Benachrichtigungen: eine Webhook-URL eintragen, „Test senden"
|
||
drücken, speichern. Rippy erkennt den Dienst an der URL selbst:
|
||
|
||
| Dienst | URL-Beispiel |
|
||
|---|---|
|
||
| Discord | `https://discord.com/api/webhooks/…` |
|
||
| Slack | `https://hooks.slack.com/services/…` |
|
||
| ntfy (Handy-Push) | `https://ntfy.sh/mein-geheimes-thema` |
|
||
| Eigenes (Home Assistant, n8n, …) | beliebige HTTPS-URL |
|
||
|
||
---
|
||
|
||
## 4K-UHD
|
||
|
||
4K braucht **zwei** Dinge, die normale BD/DVD nicht brauchen: ein
|
||
**LibreDrive-fähiges Laufwerk** (MakeMKV-Forum: „Ultimate UHD Drives Flashing
|
||
Guide") **und** den **Schlüssel dieser Pressung**.
|
||
|
||
**Der Schlüssel ist die eigentliche Hürde — aus einem überraschenden Grund.**
|
||
Am 25.07.2026 auf beiden Maschinen gemessen (Akira UHD, MKB v76, Pressung
|
||
Dezember 2020): Laufwerk und MakeMKV waren in Ordnung — „Using LibreDrive mode
|
||
(v06.3)", die Disc wurde gelesen — und trotzdem kam „The volume key is unknown
|
||
for this disc".
|
||
|
||
> **`makemkvcon` unter Linux holt Disc-Schlüssel nie aus dem Netz.
|
||
> Die Windows-Version tut es.**
|
||
|
||
Gemessen: Linux baute in keinem einzigen Lauf eine Verbindung nach draußen auf
|
||
— geprüft mit leerem und gefülltem Schlüsselspeicher, mit und ohne `--noscan`,
|
||
mit `dev:` und `disc:`, und mit erzwungener frischer Prüfung. Dieselbe Disc am
|
||
selben Laufwerk unter Windows: „Lade aktuelle HK …", Verbindung zum
|
||
Schlüssel-Server, Disc geht auf. **Ein MakeMKV-Update ändert daran nichts, und
|
||
es ist kein Fehler in Rippy.**
|
||
|
||
**Der Weg drumherum** (Einstellungen → System):
|
||
|
||
1. MakeMKV auf einem **Windows-PC** installieren (gleicher Beta-Key).
|
||
2. Laufwerk anstecken, Disc **einmal öffnen** — dabei lädt MakeMKV die
|
||
Schlüssel nach.
|
||
3. In MakeMKV unter *Preferences → General* das „MakeMKV data directory"
|
||
nachschlagen und die Datei **`_private_data.tar`** daraus bei Rippy
|
||
hochladen.
|
||
|
||
Rippy zeigt an, **wie viele Disc-Schlüssel** dieser Worker kennt. Steht dort 0,
|
||
scheitert jede unbekannte UHD. Für neue Discs den Schritt gelegentlich
|
||
wiederholen. Rippy prüft die Datei und lehnt sie ab, wenn kein einziger
|
||
Schlüssel drinsteckt — sonst ändert sich nichts und niemand versteht, warum.
|
||
|
||
**Kennt MakeMKV die Pressung selbst nicht**, bleibt die **`KEYDB.cfg`** als
|
||
Notnagel (gleicher Tab). Und: **AACS-Dumps herunterladen** — den Dump legt
|
||
MakeMKV bei jeder unbekannten Disc selbst ab, und genau den braucht man, wenn
|
||
man im MakeMKV-Forum um den Schlüssel für eine neue Pressung bittet.
|
||
|
||
> ⚠️ **Rippy liefert keine Disc-Schlüssel mit, lädt keine herunter und
|
||
> verteilt keine.** Rippy hält nur den Platz für eine Datei bereit, die du
|
||
> selbst mitbringst, und zeigt ehrlich an, was dort liegt. Der
|
||
> MakeMKV-**Beta-Key** ist die Lizenz für die *Software* — zwei völlig
|
||
> verschiedene Dinge.
|
||
|
||
⚠️ UHD-Rohdaten sind bis 100 GB groß. Ist die Platte zu klein, lege das
|
||
**Arbeitsverzeichnis** (Einstellungen → Verarbeitung) auf eine eingehängte
|
||
Freigabe. Rippy bricht sonst **vor** dem Rip mit Klartext ab statt nach 40 GB
|
||
mit voller Platte.
|
||
|
||
---
|
||
|
||
## Weitere Maschinen als Worker
|
||
|
||
Die Kompression läuft als eigener Task auf der Queue `transcode` — **jede**
|
||
Maschine im Netz kann sie übernehmen. Einstellungen → Worker zeigt für beide
|
||
Varianten einen Copy-Paste-Befehl:
|
||
|
||
- **Windows (nativ, ohne Docker)** — braucht nur Python. Der Installer kommt
|
||
als fertige `.exe` von Rippy selbst; Worker-Code und HandBrake holt er zur
|
||
Laufzeit.
|
||
- **Linux (Docker)** — `deploy/remote-transcode-worker.yml`.
|
||
|
||
Rippy zeigt für jeden Worker an, **was er wirklich kann**: Encoder, Kernzahl,
|
||
Vektorbefehle. Für einen **GPU-Worker** wichtig: das Bild braucht ein
|
||
HandBrake mit `nvenc_*` bzw. `qsv_*` — die Anzeige nennt HandBrakes
|
||
ungefilterte Auskunft, damit du das nachprüfen kannst. Das mitgelieferte
|
||
Linux-Worker-Bild hat **keinen** Hardware-Encoder.
|
||
|
||
Ohne Zusatz-Worker macht der eingebaute CPU-Worker alles selbst — Rippy bleibt
|
||
All-in-one.
|
||
|
||
---
|
||
|
||
## Für Fortgeschrittene
|
||
|
||
<details>
|
||
<summary><b>Umgebungsvariablen (.env)</b></summary>
|
||
|
||
`install.sh` füllt die hostabhängigen Werte selbst. Alles hier ist optional —
|
||
UI-Einstellungen überstimmen die Env-Variablen.
|
||
|
||
| Variable | Zweck |
|
||
|---|---|
|
||
| `TMDB_API_KEY` | Metadaten (deutsche Texte). Bequemer im Assistenten — beide Key-Arten gehen (v3-Schlüssel und v4-Token) |
|
||
| `OMDB_API_KEY` | zweite Metadaten-Quelle (Fallback) |
|
||
| `THETVDB_API_KEY` | Serien-Fallback |
|
||
| `WORKER_NAME` | Anzeigename des eingebauten Workers (Standard `rippy-hauptworker`) |
|
||
| `MAKEMKV_APP_KEY` | MakeMKV-Beta-Key. Bequemer im UI unter Einstellungen → System — gilt ab dem nächsten Rip, ohne Rebuild |
|
||
| `MAKEMKV_VERSION` | MakeMKV-Version für den Image-Build |
|
||
| `MAKEMKV_URL_BASE` | Download-Quelle für den Build. Normalerweise **nichts eintragen** — der Standard `makemkv.com/download` liefert (am 25.07.2026 mit HTTP 200 geprüft; `/download/old` gibt 525, ein web.archive.org-Schnappschuss 404) |
|
||
| `MAKEMKV_URL_FALLBACK` | zweite Quelle, die bei Fehlschlag der ersten **automatisch** versucht wird. Leer = keine. Trage nur ein, was du selbst geprüft hast: eine Adresse, die nicht liefert, lässt die Konfiguration gesund aussehen und den Build später scheitern |
|
||
| `MAKEMKV_DATA_HOST` | Host-Verzeichnis für MakeMKVs Daten (Standard `/srv/rippy/makemkv`) — Schlüsselspeicher, `KEYDB.cfg`, AACS-Dumps. Persistent, überlebt jeden Rebuild |
|
||
| `OPTICAL_SR` / `OPTICAL_SG` | Geräteknoten des Laufwerks. **Findet `install.sh` selbst** |
|
||
| `POSTGRES_PASSWORD` | DB-Passwort (Standard `rippy`) |
|
||
|
||
</details>
|
||
|
||
<details>
|
||
<summary><b>Installation ohne install.sh (von Hand)</b></summary>
|
||
|
||
Falls du jeden Schritt selbst machen willst:
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
mkdir -p /srv/rippy/media /srv/rippy/makemkv
|
||
|
||
# Laufwerksknoten ermitteln — die sg-Nummer ist je Host anders!
|
||
lsscsi -g # zeigt Modell + zugehoerigen /dev/sgN
|
||
# in die .env: OPTICAL_SR=/dev/sr0 und OPTICAL_SG=/dev/sgN
|
||
|
||
# Nur falls 'docker compose up' meldet:
|
||
# "path ... is mounted on / but it is not a shared mount"
|
||
mount --bind /srv/rippy/media /srv/rippy/media
|
||
mount --make-rshared /srv/rippy/media # neustart-fest als systemd-.mount-Unit
|
||
|
||
docker compose up -d --build
|
||
```
|
||
|
||
Braucht klassisches Linux-Docker mit `SYS_ADMIN` — nicht Docker Desktop,
|
||
rootless oder Podman. Die Mount-Propagation ist nur für das Einhängen von
|
||
NAS-Freigaben **aus dem UI** nötig; Freigaben auf dem Host einhängen geht immer.
|
||
|
||
</details>
|
||
|
||
<details>
|
||
<summary><b>Wie es intern funktioniert</b></summary>
|
||
|
||
1. **Disc-Wache** — ioctl-Polling, kein udev. Im Container läuft kein udevd,
|
||
die udev-Datenbank ist leer; `udevadm info` liefert dort prinzipbedingt
|
||
nichts.
|
||
2. **Rip** — MakeMKV, verlustfrei. Der einzige Weg durch AACS: HandBrake kann
|
||
verschlüsselte Discs nicht lesen, deshalb sind es zwingend zwei Stufen.
|
||
3. **Kompression** — HandBrake als eigener Celery-Task auf eigener Queue,
|
||
deshalb an andere Maschinen routbar.
|
||
4. **Metadaten** — Volume-Label → TMDB → OMDb → MyAnimeList, mit
|
||
Ähnlichkeits-Bewertung und Korrektur-Popup an der Disc-Karte.
|
||
|
||
</details>
|
||
|
||
<details>
|
||
<summary><b>Härtung für exponierte Netze</b></summary>
|
||
|
||
Rippy ist bewusst **Heimnetz-only**: keine Authentifizierung, und Redis +
|
||
PostgreSQL veröffentlichen Ports für Remote-Worker. Im vertrauten LAN ein
|
||
akzeptierter Kompromiss — **exponiere Rippy niemals ungeschützt an ein
|
||
öffentliches Netz.**
|
||
|
||
- **Zugriff kapseln:** UI und API (`:8000`) hinter einen Reverse-Proxy mit Auth
|
||
oder nur über VPN erreichbar machen.
|
||
- **DB/Broker abschotten:** starkes `POSTGRES_PASSWORD`; die Ports
|
||
`5432`/`6379` nur an ein internes/VPN-Interface binden statt an `0.0.0.0`;
|
||
Redis mit `--requirepass` starten und das Passwort in `REDIS_URL` ergänzen.
|
||
- **CORS:** `main.py` erlaubt `*` (nötig, weil UI und API getrennte Ports
|
||
sind) — hinter einem Proxy auf die echte UI-Herkunft einschränken.
|
||
- **NAS-Zugangsdaten** liegen im Klartext in der DB — ein weiterer Grund, den
|
||
DB-Port nie offen ins unsichere Netz zu hängen.
|
||
|
||
</details>
|
||
|
||
<details>
|
||
<summary><b>Updates der Werkzeuge</b></summary>
|
||
|
||
„Auf Updates prüfen" (Einstellungen → System) vergleicht mit makemkv.com und
|
||
den offiziellen HandBrake-Releases, 12 h gecacht.
|
||
|
||
**MakeMKV** aktualisieren: `MAKEMKV_VERSION=x.y.z` in die `.env`, dann
|
||
`sudo ./install.sh`. Der Beta-Key wechselt etwa monatlich (Forum-Thread
|
||
t=1053) und wird im UI gepflegt — ohne Rebuild.
|
||
|
||
**HandBrake** kommt im Docker-Worker bewusst aus Debian (stabil, hinkt der
|
||
offiziellen Version hinterher); der native Windows-Worker nutzt die aktuelle.
|
||
|
||
⚠️ Ein MakeMKV-Update hilft **nicht** gegen „The volume key is unknown" —
|
||
MakeMKV liefert überhaupt keine Disc-Schlüssel mit, es holt sie zur Laufzeit,
|
||
und die Linux-Version holt sie nie. Siehe [4K-UHD](#4k-uhd).
|
||
|
||
</details>
|
||
|
||
---
|
||
|
||
## Entwicklung
|
||
|
||
CI („Ampel") läuft bei jedem Push: Ruff, pytest, Vite-Build. Es gibt genau
|
||
einen Branch, `main` — die Ampel prüft nur, deployt wird direkt aus `main`.
|
||
Rot heißt: nicht deployen.
|
||
|
||
Regeln für Beiträge: [AGENTS.md](AGENTS.md) · Konzept: [KONZEPT.md](KONZEPT.md) ·
|
||
Fahrplan: [ROADMAP.md](ROADMAP.md) · Stand: [SAVEPOINT.md](SAVEPOINT.md)
|