stacks/media/README.md

# media

Jellyfin + the *arr set + qbittorrent behind gluetun. Nothing in this
stack ever talks to the internet directly without going through the VPN
container first (firewall rules in gluetun enforce it).

See also: mercemay.top/src/homelab-compose/

## Services

| service     | port  | reverse-proxy host       |
|-------------|-------|--------------------------|
| jellyfin    | 8096  | jellyfin.home.arpa       |
| sonarr      | 8989  | sonarr.home.arpa         |
| radarr      | 7878  | radarr.home.arpa         |
| prowlarr    | 9696  | prowlarr.home.arpa       |
| bazarr      | 6767  | bazarr.home.arpa         |
| qbittorrent | 8080  | qbt.home.arpa (via 127)  |
| gluetun     | -     | -                        |

qbittorrent is `network_mode: service:gluetun`, so the only way its
port is reachable is the 127.0.0.1 publish on the host (which Caddy
proxies to on `qbt.home.arpa`).

## Storage layout

```
/mnt/tank/media/
  tv/        # sonarr
  movies/    # radarr
  music/     # jellyfin only
  downloads/
    incomplete/
    complete/
```

The volumes are bind-mounted with `UMASK=002` so the `abc` user in
LinuxServer.io images can write them.

## First run

1. `cp media.env.example media.env` and fill in Mullvad/other VPN values.
2. `docker compose up -d gluetun`
3. Wait for `docker compose logs gluetun` to confirm the tunnel is up.
4. `docker compose up -d` for the rest.
5. Sign in to each *arr UI once to replace the placeholder api keys
   (the config.xml files generate a real key on first boot if the
   placeholder is present).

## Hardware transcoding

Intel quicksync is wired in `compose.override.yml` via `/dev/dri`
passthrough and the render group. On the Jellyfin side enable "Intel
QuickSync" in Dashboard > Playback > Transcoding.