docs: add jellyfin-services.md with arr-stack and Watchtower lscr.io auth fix

This commit is contained in:
2026-05-11 10:55:20 +00:00
parent 196337da39
commit 113121a765
+75
View File
@@ -0,0 +1,75 @@
# 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 <github_pat> | 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.