- llm.py: Text-Modell auf x-ai/grok-4.3 - telegram_bot.py: Fortschritts-Logik auf asyncio.wait_for + shield (15s Timeout) - monitor.py: Hermes-Healthchecks (CT151), Alert-Dedup, EXPECTED_STOPPED erweitert - core/loki_client.py: zentrale ERROR_EXCLUDE_RE fuer transiente cloudflared/QUIC-Flaps - Doku: JELLYFIN.md, infrastructure/STATE.md, hardware-ai-local-coding.md, sessions/ Bis 21.06. uncommittete Live-Edits, gesichert in backup/live-state-20260621. Ref #123.
197 lines
6.8 KiB
Markdown
197 lines
6.8 KiB
Markdown
# Jellyfin Server
|
||
|
||
## Zugang
|
||
|
||
| Feld | Wert |
|
||
|------|------|
|
||
| Host | `192.168.178.149` (lokal) / `100.77.105.3` (Tailscale) |
|
||
| Port | `8096` |
|
||
| Hostname | `debian-jellyfin-homeassistent` |
|
||
| OS-User | `michael` / PW: `astral66` |
|
||
| Version | 10.9.11 |
|
||
| API-Key | `7285b4a8793541648bf156599ae05b43` (App: `homelab-ai`) |
|
||
| Admin-User | `admin` |
|
||
| Admin-PW | `astral66` |
|
||
|
||
**SSH-Zugang** (nur aus dem lokalen 192.168.178.x Netz, z.B. via pve3):
|
||
```bash
|
||
sshpass -p 'astral66' ssh -o StrictHostKeyChecking=no michael@192.168.178.149
|
||
```
|
||
Von außen via Tailscale nur HTTP API erreichbar (Tailscale SSH erfordert Browser-Authentifizierung).
|
||
|
||
## Netzwerk / Infrastruktur
|
||
|
||
```
|
||
Internet
|
||
└── Fritz!Box (192.168.178.1)
|
||
├── Jellyfin-Server 192.168.178.149 (debian-jellyfin-homeassistent)
|
||
├── NAS/Windows 192.168.178.170 (Share: "Medien")
|
||
├── Synology NAS 192.168.178.94 (Share: "Filme" = Jellyfin Quelle, Share: "Michael")
|
||
└── pve3 192.168.178.250 (= pve-mu-3, Tailscale: 100.109.101.12)
|
||
```
|
||
|
||
### NAS-Zugriff auf dem Jellyfin-Server
|
||
|
||
Der Jellyfin-Server mountet den Share `Medien` von **192.168.178.170** (Windows-Maschine) an drei Stellen:
|
||
|
||
| Mount-Punkt | Zweck |
|
||
|-------------|-------|
|
||
| `/mnt/nas/` | Haupt-NAS-Zugriff (user michael) |
|
||
| `/mnt/nas_filme/` | Gleicher Share, als root gemountet (automount) |
|
||
| `/srv/media/` | Gleicher Share, als root gemountet |
|
||
|
||
**Wichtige Ordner auf dem NAS (192.168.178.170/Medien):**
|
||
|
||
| Pfad | Inhalt |
|
||
|------|--------|
|
||
| `/mnt/nas/Recorded TV/` | ~700+ Jellyfin-Quelldateien (`.mp4`) |
|
||
| `/mnt/nas/Filme zum nachbearbeiten/` | Staging-Ordner: neue SaveTV-Filme warten hier auf Umbenennung/Einpflege |
|
||
| `/mnt/nas/Filme umbenennen Eigangsordner/` | Eingangs-Ordner für Batch-Umbenennung |
|
||
| `/mnt/nas/Heimatfilme/` | Private Heimvideos |
|
||
|
||
### Synology NAS (192.168.178.94)
|
||
|
||
Auf pve3 (192.168.178.250 / Tailscale 100.109.101.12) gemountet:
|
||
```bash
|
||
# Zugriff von pve3 (100.109.101.12):
|
||
ls /mnt/synology/ # Michael-Share (Michas Datenspeicher)
|
||
# enthält u.a.: Filme/, Heimatfilme/, Backups/, Musik/, ...
|
||
```
|
||
|
||
SMB-Shares auf der Synology:
|
||
- `Filme` – Jellyfin Quelle (benötigt eigene Credentials)
|
||
- `Michael` – Michas Datenspeicher (User: Orbitalo, PW: astral66)
|
||
- `Mila` – Milas Datenspeicher
|
||
|
||
## Bibliotheken
|
||
|
||
| Name | Typ | Quellpfad (auf Jellyfin-Server) |
|
||
|------|-----|-------------------------------|
|
||
| Filme | movies | `/srv/media/Recorded TV/` |
|
||
|
||
Aktuell ~718 Filme im Bestand.
|
||
|
||
## API-Nutzung
|
||
|
||
```bash
|
||
API_KEY="7285b4a8793541648bf156599ae05b43"
|
||
JF="http://100.77.105.3:8096" # via Tailscale (von pve-hetzner aus)
|
||
# oder: JF="http://192.168.178.149:8096" # lokal
|
||
|
||
# Anzahl Filme
|
||
curl -s "$JF/Items/Counts?api_key=$API_KEY"
|
||
|
||
# Alle Filme (Name + Pfad)
|
||
curl -s "$JF/Items?api_key=$API_KEY&IncludeItemTypes=Movie&Recursive=true&Fields=Name,Path&Limit=1000"
|
||
|
||
# Film suchen
|
||
curl -s "$JF/Items?api_key=$API_KEY&SearchTerm=Matrix&IncludeItemTypes=Movie&Recursive=true"
|
||
```
|
||
|
||
**Erreichbarkeit:** Tailscale-IP `100.77.105.3` ist von pve-hetzner aus direkt nutzbar (kein Hop nötig).
|
||
|
||
## Save.TV → Jellyfin Workflow
|
||
|
||
```
|
||
Save.TV (Cloud-Recorder)
|
||
└── CT 116 auf pve-hetzner
|
||
└── savetv_auto_download.py (Cron */30 * * * *)
|
||
→ lädt Kinofilme nach /mnt/savetv/ (auf pve-hetzner)
|
||
→ 1 Film gleichzeitig, 48h + TID-Jitter nach Aufnahme
|
||
└── savetv_sync.py
|
||
→ kopiert Dateien von Hetzner via HTTP-API
|
||
→ Ziel: /mnt/nas/Filme zum nachbearbeiten/ (auf NAS 192.168.178.170)
|
||
→ Wartezeit: 24h nach Download
|
||
└── Manuell: Umbenennen + in "Recorded TV" verschieben
|
||
→ Jellyfin scannt automatisch und nimmt Film auf
|
||
```
|
||
|
||
## Staging-Ordner „Filme zum nachbearbeiten"
|
||
|
||
**Zugriff:**
|
||
```bash
|
||
# Von pve3 (100.109.101.12) via pve-hetzner:
|
||
sshpass -p 'astral66' ssh michael@192.168.178.149 'ls "/mnt/nas/Filme zum nachbearbeiten/"'
|
||
|
||
# Vergleich mit Jellyfin (Duplikat-Check):
|
||
# 1. JF-Filme holen:
|
||
curl -s "http://100.77.105.3:8096/Items?api_key=7285b4a8793541648bf156599ae05b43&IncludeItemTypes=Movie&Recursive=true&Fields=Name&Limit=1000"
|
||
# 2. Liste "Filme zum nachbearbeiten" holen (via michael@192.168.178.149)
|
||
# 3. Titelnamen normieren (Jahreszahl entfernen, Kleinschreibung) und vergleichen
|
||
```
|
||
|
||
**Stand 06.04.2026:** 53 Filme im Staging-Ordner, davon **17 bereits in Jellyfin** (Duplikate):
|
||
- 12 Monkeys, Angel Has Fallen, Bullet Train, Children of Men, Der mit dem Wolf tanzt,
|
||
Die Frau in Blau (2023+2025), Die Spezialistin, Kill the Boss, Mile 22,
|
||
No Turning Back, No Way Up, On the Line, Parker, Salt,
|
||
Stirb langsam, Stirb langsam 2
|
||
|
||
## Benutzer
|
||
|
||
| Name | Admin |
|
||
|------|-------|
|
||
| admin | ja |
|
||
| Hans | ja (alt) |
|
||
| karsten | nein |
|
||
| Holger | nein |
|
||
| Peter | nein |
|
||
| Klemens | nein |
|
||
| michael ec | nein |
|
||
| Ralf | nein |
|
||
| rolf | nein |
|
||
| wilfrid | nein |
|
||
|
||
## Troubleshooting: Details fehlen / Remote-Zugriff wirkt kaputt
|
||
|
||
Stand: 2026-05-16
|
||
|
||
Symptom:
|
||
- Filmübersicht ist erreichbar, aber Detailseiten/Filmdetails werden im Client nicht angezeigt.
|
||
- Zugriff über Tailscale-IP `100.77.105.3:8096` hängt oder läuft in Timeouts.
|
||
|
||
Befund vom 2026-05-16:
|
||
- Jellyfin selbst war lokal gesund:
|
||
- `http://192.168.178.149:8096/health` -> `Healthy`
|
||
- API `/Items/Counts` lieferte `897` Filme.
|
||
- Beispiel-Film `2 Guns` hatte Beschreibung, Genres, TMDB/IMDB IDs und Bilder.
|
||
- Medien-Mounts waren aktiv:
|
||
- `/mnt/nas`
|
||
- `/srv/media`
|
||
- Docker-Container `jellyfin` war `healthy`.
|
||
- Ursache war Tailscale auf dem Jellyfin-Host:
|
||
- `tailscale ip -4` meldete zuerst `no current Tailscale IPs; state: NeedsLogin`
|
||
- `tailscale status` meldete `Logged out`.
|
||
- Nach Re-Login war `100.77.105.3` wieder aktiv und `http://100.77.105.3:8096/health` antwortete wieder `Healthy`.
|
||
- Danach waren die Filmdetails im Client wieder sichtbar.
|
||
|
||
Schnelltest:
|
||
```bash
|
||
# Von pve3 lokal im LAN:
|
||
curl -sS http://192.168.178.149:8096/health
|
||
|
||
# Von CT 116 / Hausmeister oder einem Tailscale-Host:
|
||
curl -sS http://100.77.105.3:8096/health
|
||
curl -sS "http://100.77.105.3:8096/Items/Counts?api_key=7285b4a8793541648bf156599ae05b43"
|
||
```
|
||
|
||
Fix:
|
||
1. Auf dem Jellyfin-Host Tailscale-Status prüfen:
|
||
```bash
|
||
tailscale ip -4
|
||
tailscale status --self
|
||
```
|
||
2. Wenn `NeedsLogin` oder `Logged out`: Tailscale neu anmelden.
|
||
3. Danach erneut prüfen:
|
||
```bash
|
||
curl -sS http://100.77.105.3:8096/health
|
||
```
|
||
4. Im Browser Jellyfin hart neu laden oder neu einloggen, falls der Webclient alte kaputte API-Antworten gecacht hat.
|
||
|
||
Wichtig:
|
||
- Fehlende Details bedeuten nicht automatisch kaputte Jellyfin-Datenbank oder fehlende Metadaten.
|
||
- Erst lokale API gegen `192.168.178.149:8096` prüfen, dann Tailscale/Cloudflare-Zugriff.
|
||
- `systemctl is-active jellyfin` kann irreführend sein, weil Jellyfin hier im Docker-Container läuft. Aussagekräftiger ist:
|
||
```bash
|
||
docker ps | grep jellyfin
|
||
curl -sS http://127.0.0.1:8096/health
|
||
```
|