diff options
| author | Paul Buetow <paul@buetow.org> | 2026-01-31 09:17:59 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-01-31 09:17:59 +0200 |
| commit | e976193b1697fcdc3f4787e9cd43d099b27a0e52 (patch) | |
| tree | d8941bec193483c0eab319c69a749c727be829af | |
| parent | 351cf50a61d727c3633e37ef0792ae7fae44b344 (diff) | |
docs(jellyfin): add deployment summary and configuration overview
Amp-Thread-ID: https://ampcode.com/threads/T-019c12b1-e861-773b-8f74-64b6c2255a5f
Co-authored-by: Amp <amp@ampcode.com>
| -rw-r--r-- | f3s/jellyfin/SUMMARY.md | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/f3s/jellyfin/SUMMARY.md b/f3s/jellyfin/SUMMARY.md new file mode 100644 index 0000000..a3ac82a --- /dev/null +++ b/f3s/jellyfin/SUMMARY.md @@ -0,0 +1,135 @@ +# Jellyfin Deployment Summary + +## Objective +Deploy Jellyfin 10.11.6 (latest stable) with proper reverse proxy configuration through relayd and Traefik, accessible at `https://jellyfin.f3s.buetow.org` and alternate ports 8096/8920 for Android app compatibility. + +## Configuration Implemented + +### 1. Kubernetes Resources +- **Deployment**: Jellyfin server using `jellyfin/jellyfin:latest` image +- **Service**: NodePort service exposing ports 30096 and 30920 for direct internal access +- **PersistentVolumes/Claims**: Three volumes for config, libraries, and data +- **Pod Resources**: 100m CPU request, 256Mi RAM request; 2000m CPU limit, 2Gi RAM limit + +### 2. Reverse Proxy Configuration (relayd) + +#### Frontend Setup +- **TLS Termination**: Relayd listens on ports 443 (IPv4/IPv6) with Let's Encrypt certificates +- **Header Forwarding**: + - `X-Forwarded-For: $REMOTE_ADDR` (client IP) + - `X-Forwarded-Proto: https` (protocol indication) +- **Multiple Ports**: Added separate relay rules for ports 8096 and 8920 to support Android app discovery attempts + +#### Routing Rules +- **Port 443**: Routes to Jellyfin NodePort 30096 via `f3s_jellyfin` backend table +- **Ports 8096/8920**: Dual IPv4/IPv6 relays also forward to NodePort 30096 +- **Host Routing**: Explicit match for `jellyfin.f3s.buetow.org` hostname + +### 3. Jellyfin Network Configuration +- **RequireHttps**: false (TLS handled by relayd) +- **EnableHttps**: false (no self-signed certs) +- **PublicPort**: 443 (external port users connect to) +- **KnownProxies**: + - 10.0.0.0/8 (Kubernetes cluster CIDR) + - 192.168.0.0/16 (relayd/frontend subnet) +- **EnablePublishedServerUriByRequest**: false + +### 4. Certificate Chain +- **Full Chain**: Relayd presents complete certificate chain (leaf + R12 intermediate) +- **Validation**: Confirmed with `openssl s_client` showing 2 certificates +- **Auto-renewal**: Let's Encrypt certificates on relayd + +## Issues Encountered & Solutions + +### Issue 1: Database Migration Failures +- **Problem**: Upgrading from 10.8.13 → 10.11.6 directly caused database corruption +- **Solution**: Requires upgrade path 10.8.13 → 10.10.7 → 10.11.6 +- **Status**: Settled on `jellyfin:latest` (10.11.6) with clean database + +### Issue 2: ConfigMap Read-Only Mount +- **Problem**: Network.xml mounted as read-only ConfigMap; newer Jellyfin versions need to write during migration +- **Solution**: Removed ConfigMap mount, let Jellyfin manage network.xml from PVC +- **Result**: Cleaner configuration, Jellyfin can self-manage settings + +### Issue 3: Android App "Unsupported version or product" Error +- **Root Cause**: + - Missing full certificate chain from relayd → Android app SSL validation failure + - App attempting alternate ports (8096, 8920) that weren't exposed +- **Solution**: + - Added relayd relays for ports 8096 and 8920 + - Ensured full cert chain is presented + - App should now connect to any of the three ports + +### Issue 4: NFS Storage Read-Only (CURRENT BLOCKER) +- **Problem**: `/data/nfs/k3svolumes/jellyfin/*` directories mounted read-only +- **Error**: `chown` and pod writes fail with "Read-only file system" +- **Status**: PVCs remain Pending; pods cannot start +- **Resolution Required**: NFS mount needs to be remounted as read-write on f0/f1/f2 hosts + +## Current Deployment Status + +✅ **Complete** +- Kubernetes manifests fully configured +- ArgoCD Application re-enabled with proper git URL +- Relayd configuration updated and deployed +- Certificate chain verified +- All networking rules in place + +❌ **Blocked** +- PersistentVolumes cannot bind to PVCs (read-only NFS) +- Jellyfin pod remains in Pending state +- Cannot proceed with testing until NFS is writable + +## Next Steps + +1. **Fix NFS Mount** (blocking issue) + ```bash + # On f0, f1, f2 - remount /data with write permissions + doas mount -uw /data + # Or check NFS export configuration + ``` + +2. **Deploy & Test** + - Once NFS is writable, pods will automatically start via ArgoCD + - Test connectivity: `curl https://jellyfin.f3s.buetow.org/System/Info/Public` + - Test Android app with manual URL entry + +3. **Configure Jellyfin** (post-deployment) + - Run setup wizard + - Add media libraries + - Configure transcoding if needed + - Verify Android app can connect + +## Key Files + +- **Deployment**: `jellyfin/helm-chart/templates/deployment.yaml` +- **Persistent Storage**: `jellyfin/helm-chart/templates/persistent-volume.yaml` +- **Relayd Config**: `/home/paul/git/conf/frontends/etc/relayd.conf.tpl` (lines ~15-130) +- **ArgoCD App**: Created via kubectl in services namespace + +## Testing Commands + +```bash +# Check pod status +kubectl get pods -n services -l app=jellyfin-server + +# View logs +kubectl logs -n services -l app=jellyfin-server + +# Test API endpoint +curl https://jellyfin.f3s.buetow.org/System/Info/Public + +# Verify certificate chain +echo | openssl s_client -servername jellyfin.f3s.buetow.org -connect jellyfin.f3s.buetow.org:443 | grep "BEGIN CERTIFICATE" | wc -l +# Should output: 2 + +# Check PVC binding +kubectl get pvc -n services | grep jellyfin +``` + +## Notes + +- Latest version (10.11.6) requires database >= 10.9.11 +- Android app compatibility improved in 10.10.7+ +- Relayd provides full TLS termination, reducing complexity vs. Traefik double-proxy +- NodePort approach bypasses Traefik, avoiding header forwarding issues |
