# 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.