# Jellyfin Server — Docker Services ## Host - **VM / alias**: jellyfin - **IP**: `192.168.88.10` - **SSH**: `jgitta@192.168.88.10` (alias: `jellyfin`) - **Portainer endpoint ID**: 4 - **Compose files**: managed via Portainer (stack IDs below); source of truth is Gitea `jgitta/homelab-configs` --- ## Stacks | Stack | Portainer ID | Gitea Path | |---|---|---| | arr-stack | 35 | `jellyfin/arr-stack/docker-compose.yml` | | portainer-agent | 36 | `jellyfin/portainer-agent/` | | node-exporter | 44 | `jellyfin/node-exporter/` | --- ## arr-stack Services | Container | Image | Port | Config Path | |---|---|---|---| | radarr | lscr.io/linuxserver/radarr:latest | 7878 | /srv/docker/radarr/config | | sonarr | lscr.io/linuxserver/sonarr:latest | 8989 | /srv/docker/sonarr/config | | prowlarr | lscr.io/linuxserver/prowlarr:latest | 9696 | /srv/docker/prowlarr/config | | flaresolverr | ghcr.io/flaresolverr/flaresolverr:latest | 8191 | — | | watchtower | containrrr/watchtower | — | see below | Media volume: `/mnt/media` on jellyfin host → mounted as `/data` in radarr/sonarr. --- ## Watchtower - Runs inside arr-stack on jellyfin (Portainer stack 35) - Schedule: `0 0 4 * * *` — runs at 4:00 AM daily - Notifications: email via Fastmail SMTP to jgitta@jgitta.com - Cleanup: enabled (removes old images after update) - Rolling restarts: enabled with 30s timeout, 60s wait before stopping ### lscr.io Authentication (fix applied 2026-05-11) **Problem**: Watchtower was hitting lscr.io's rate limiter on unauthenticated pulls. radarr, sonarr, and prowlarr all use `lscr.io/linuxserver/` images; when Watchtower checks them concurrently at 4 AM the burst briefly exceeded the anonymous quota. Error appeared in email notifications as: ``` Unable to update container "/radarr": Error response from daemon: toomanyrequests: retry-after: 835.12µs, allowed: 44000/minute. Proceeding to next. ``` Observed on: 2026-05-08 and 2026-05-11. **Fix**: 1. Logged in to lscr.io on the jellyfin host using the GitHub PAT (credentials.md): ``` echo | docker login lscr.io -u jgitta --password-stdin ``` Creates `/home/jgitta/.docker/config.json` with lscr.io auth token. 2. Mounted that config into the Watchtower container (in docker-compose.yml): ```yaml volumes: - /var/run/docker.sock:/var/run/docker.sock - /home/jgitta/.docker/config.json:/config.json:ro ``` Watchtower reads `/config.json` inside the container for registry credentials. 3. Updated Gitea (`jellyfin/arr-stack/docker-compose.yml`) and redeployed via Portainer. **If GitHub PAT expires**: Re-run the `docker login lscr.io` command on jellyfin with the new token. No compose changes needed — the mounted file updates automatically. The PAT expiry date is tracked in credentials.md / github.com/settings/tokens.