media stack: shared /data/media layout, promote sonarr/radarr/jellyfin/jellyseerr

- Promote sonarr, radarr, jellyfin, jellyseerr from _dev
- qBittorrent, Sonarr, Radarr, Lidarr, Readarr, Whisparr mount /data/media
  at /media so paths match across containers (no remote path mappings,
  hardlinks work); downloads go to /media/downloads/prowlarr
- Jellyfin: drop photos (use Immich) and unused internal network, rewrite README
- Jellyseerr: add TZ, document container hostnames and root folders

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
code
2026-11-02 17:43:22 +00:00
co-authored by Claude Opus 5.5
parent f41ca56096
commit 7ed139d134
25 changed files with 193 additions and 124 deletions
+101
View File
@@ -0,0 +1,101 @@
# Jellyfin
## Overview
Jellyfin is a free, open-source media server. It organizes your movies, shows, music and books and streams them to web, mobile and TV clients. In this setup Sonarr and Radarr fill the library; Jellyfin just reads it.
## Project Details
- **Project Repository:** [https://jellyfin.org/](https://jellyfin.org/) ([Docs](https://jellyfin.org/docs/))
- **Container Image:** [jellyfin/jellyfin](https://hub.docker.com/r/jellyfin/jellyfin)
- **Reverse Proxy Port:** `8096`
## Getting Started
Open http://localhost:8096 in your browser and complete the setup wizard:
1. **Create your admin account**
2. **Add media libraries** — point each one at the matching container folder:
| Library type | Folder |
|---|---|
| Movies | `/movies` |
| Shows | `/shows` |
| Music | `/music` |
| Books | `/books` |
3. Finish the wizard. Jellyfin scans the folders and pulls metadata.
For Jellyseerr, create an API key under **Dashboard → API Keys**.
## Environment Variable Notes
| Variable | Description |
|---|---|
| `JELLYFIN_IMAGE` | Container image (default: `jellyfin/jellyfin:latest`) |
| `JELLYFIN_RESTART` | Restart policy (default: `unless-stopped`) |
| `JELLYFIN_PORT` | Published port for the web UI (default: `8096`) |
| `JELLYFIN_URL` | Public URL clients use to reach the server (default: `http://localhost:8096`) — set this to your reverse proxy URL |
| `JELLYFIN_MEDIA` | Shared media root on the host (default: `/data/media`) — the same folder qBittorrent, Sonarr, Radarr and Bazarr use |
| `VOL_PATH` | Base path for persistent data volumes (default: `/data`) |
## Volume Notes
| Volume | Purpose |
|---|---|
| `${VOL_PATH:-/data}/jellyfin/config` | Configuration, database and metadata |
| `${VOL_PATH:-/data}/jellyfin/cache` | Transcode and image cache |
| `${JELLYFIN_MEDIA:-/data/media}/movies` → `/movies` | Movies (Radarr root folder `/media/movies`) |
| `${JELLYFIN_MEDIA:-/data/media}/shows` → `/shows` | TV shows (Sonarr root folder `/media/shows`) |
| `${JELLYFIN_MEDIA:-/data/media}/music` → `/music` | Music |
| `${JELLYFIN_MEDIA:-/data/media}/books` → `/books` | Books |
Jellyfin mounts only the library subfolders, not `/data/media/downloads`, so half-finished downloads never show up in the library.
## Network Notes
Requires an external `proxy` network. Create it once with:
```bash
docker network create proxy
```
Jellyseerr reaches Jellyfin at `http://jellyfin:8096` over the `proxy` network.
## Docker Run
```bash
docker run -d \
--name=jellyfin \
-e JELLYFIN_PublishedServerUrl=http://localhost:8096 \
-p 8096:8096 \
-v ${VOL_PATH:-/data}/jellyfin/cache:/cache \
-v ${VOL_PATH:-/data}/jellyfin/config:/config \
-v ${JELLYFIN_MEDIA:-/data/media}/books:/books \
-v ${JELLYFIN_MEDIA:-/data/media}/movies:/movies \
-v ${JELLYFIN_MEDIA:-/data/media}/music:/music \
-v ${JELLYFIN_MEDIA:-/data/media}/shows:/shows \
--network proxy \
--restart unless-stopped \
jellyfin/jellyfin:latest
```
## Additional Notes / Gotchas
- **Create the library folders first.** If `/data/media/movies` etc. don't exist, Docker creates them owned by root and Sonarr/Radarr (PUID 1000) can't write to them:
```bash
mkdir -p /data/media/{downloads/prowlarr,movies,shows,music,books}
chown -R 1000:1000 /data/media
```
- **Only port 8096 is published.** HTTPS (8920) is handled by Nginx Proxy Manager. Local network auto-discovery (UDP 1900/7359) won't work through the bridge network, so add the server to clients by URL.
- **Photos** are left out on purpose — use the Immich stack for photo libraries.
- **Hardware transcoding** needs the GPU passed into the container (e.g. `devices: [/dev/dri:/dev/dri]` for Intel/AMD). It's not included by default.
## Dockhand Stack, Deploy from Git
- **Cookbooks Repository**
- **stackname:** jellyfin
- **Compose file path:** jellyfin/compose.yaml
- **Additional env file (optional):** jellyfin/sample.env
Load `jellyfin/sample.env` into the Environment variables in Dockhand, then create the Stack.
@@ -8,7 +8,6 @@ services:
- ${JELLYFIN_MEDIA:-/data/media}/books:/books
- ${JELLYFIN_MEDIA:-/data/media}/movies:/movies
- ${JELLYFIN_MEDIA:-/data/media}/music:/music
- ${JELLYFIN_MEDIA:-/data/media}/photos:/photos
- ${JELLYFIN_MEDIA:-/data/media}/shows:/shows
environment:
- JELLYFIN_PublishedServerUrl=${JELLYFIN_URL:-http://localhost:8096}
@@ -16,9 +15,7 @@ services:
- "${JELLYFIN_PORT:-8096}:8096"
networks:
- proxy
- internal
networks:
proxy:
external: true
internal:
-75
View File
@@ -1,75 +0,0 @@
# Jellyfin
## Overview
* [DockerHub jellyfin](https://hub.docker.com/r/jellyfin/jellyfin)
* [Docs](https://jellyfin.org/docs/)
### Ports
* 8096/tcp is used by default for HTTP traffic. You can change this in the dashboard.
* 8920/tcp is used by default for HTTPS traffic. You can change this in the dashboard.
* 1900/udp is used for service auto-discovery. This is not configurable.
* 7359/udp is also used for auto-discovery. This is not configurable.
## Project Details
- **Container Image:** [jellyfin/jellyfin:latest](https://hub.docker.com/r/jellyfin/jellyfin)
- **Reverse Proxy Port:** `8096`
## Getting Started
1. Start the container: `docker compose up -d`
2. Open http://localhost:8096 in your browser
3. Follow the initial setup wizard to configure the application
## Environment Variable Notes
JELLYFIN_URL – default: http://localhost:8096
JELLYFIN_PORT – default: 8096
JELLYFIN_MEDIA – default: /data/media – shared media library, same one used by Radarr, Bazarr, etc.
## Volume Notes
/cache – host path /data/jellyfin/cache
/config – host path /data/jellyfin/config
/books – host path ${JELLYFIN_MEDIA:-/data/media}/books
/movies – host path ${JELLYFIN_MEDIA:-/data/media}/movies
/music – host path ${JELLYFIN_MEDIA:-/data/media}/music
/photos – host path ${JELLYFIN_MEDIA:-/data/media}/photos
/shows – host path ${JELLYFIN_MEDIA:-/data/media}/shows
## Network Notes
Requires proxy network
## Docker Run
```bash
docker run -d \
--name jellyfin \
-p 8096:8096 \
-v /data/jellyfin/cache:/cache \
-v /data/jellyfin/config:/config \
-v /data/media/books:/books \
-v /data/media/movies:/movies \
-v /data/media/music:/music \
jellyfin/jellyfin:latest
```
See compose.yaml for the full set of environment variables.
## Additional Notes / Gotchas
Nothing specific to this stack so far.
## Dockhand Stack, Deploy from Git
Cookbooks Repository
stackname: jellyfin_dev
Compose file path: jellyfin_dev/compose.yaml
Additional env file (optional): jellyfin_dev/sample.env
Then "Load" jellyfin_dev/sample.env into the Environmental variables in dockhand
Create the Stack
@@ -15,8 +15,17 @@ Jellyseerr is a free and open-source request management system for your Jellyfin
Open http://localhost:5055 in your browser and complete the initial setup:
1. **Create your admin account**
2. **Connect your media server** — select Jellyfin or Emby, enter server URL and API key
3. **Connect Sonarr and Radarr** — Jellyseerr needs these to handle requests
2. **Connect Jellyfin** — sign in with your Jellyfin admin account. Server URL: `http://jellyfin:8096` (container name on the `proxy` network). Then pick which libraries to sync (Movies, Shows)
3. **Connect Radarr and Sonarr** — get each API key from **Settings → General** in the app:
| | Radarr | Sonarr |
|---|---|---|
| Hostname | `radarr` | `sonarr` |
| Port | `7878` | `8989` |
| Root Folder | `/media/movies` | `/media/shows` |
| Quality Profile | pick one | pick one |
Tick **Default Server** on each, click **Test**, then **Save**
4. Users can now browse your library and submit requests via the Jellyseerr UI
### Request flow
@@ -30,6 +39,7 @@ User submits a request → approved (auto or manual) → Jellyseerr sends it to
| `JELLYSEERR_IMAGE` | Container image (default: `ghcr.io/hotio/jellyseerr:release`) |
| `JELLYSEERR_RESTART` | Restart policy (default: `unless-stopped`) |
| `JELLYSEERR_PORT` | Published port for the web UI (default: `5055`) |
| `TZ` | Container timezone (default: `America/Vancouver`) |
| `VOL_PATH` | Base path for persistent data volumes (default: `/data`) |
## Volume Notes
@@ -54,6 +64,7 @@ docker run -d \
-e PUID=1000 \
-e PGID=1000 \
-e UMASK=002 \
-e TZ=America/Vancouver \
-p 5055:5055 \
-v ${VOL_PATH:-/data}/jellyseerr/config:/config \
--network proxy \
@@ -63,13 +74,15 @@ docker run -d \
## Additional Notes / Gotchas
Nothing specific to this stack so far.
- Jellyseerr doesn't mount any media. It only talks to Jellyfin, Sonarr and Radarr over their APIs, so it needs just `/config`.
- The root folders entered here are paths *inside the Sonarr/Radarr containers* (`/media/shows`, `/media/movies`), not host paths.
- Use container names (`jellyfin`, `sonarr`, `radarr`), not `localhost`. Inside the container, `localhost` is Jellyseerr itself.
## Dockhand Stack, Deploy from Git
- **Cookbooks Repository**
- **stackname:** jellyseerr_dev
- **Compose file path:** jellyseerr_dev/compose.yaml
- **Additional env file (optional):** jellyseerr_dev/sample.env
- **stackname:** jellyseerr
- **Compose file path:** jellyseerr/compose.yaml
- **Additional env file (optional):** jellyseerr/sample.env
Load `jellyseerr_dev/sample.env` into the Environment variables in Dockhand, then create the Stack.
Load `jellyseerr/sample.env` into the Environment variables in Dockhand, then create the Stack.
@@ -8,6 +8,7 @@ services:
- PUID=1000
- PGID=1000
- UMASK=002
- TZ=${TZ:-America/Vancouver}
ports:
- "${JELLYSEERR_PORT:-5055}:5055"
networks:
@@ -1,5 +1,6 @@
# Jellyseerr
VOL_PATH=/data
TZ=America/Vancouver
JELLYSEERR_IMAGE=ghcr.io/hotio/jellyseerr:release
JELLYSEERR_PORT=5055
JELLYSEERR_RESTART=unless-stopped
+8 -5
View File
@@ -20,13 +20,13 @@ Open http://localhost:8686 in your browser and complete the initial setup wizard
Once the wizard finishes, Lidarr displays **"No artists found"**. To populate your library:
- Go to **Settings → Media Management** and add a **Root Folder** (e.g., `/music`) — this is where your organized music library will live
- Go to **Settings → Media Management** and add a **Root Folder** (e.g., `/media/music`) — this is where your organized music library will live
- Click **Add an artist** and search by name — Lidarr fetches metadata, discography, and album art
- Lidarr cross-references your Root Folder for any existing files and matches them to the artist's catalog
### Download flow
qBittorrent downloads to its own directory → Lidarr picks it up, renames/tags the files, and moves them into `<Root Folder>/Artist Name/Album/`
qBittorrent downloads to `/media/downloads/prowlarr` → Lidarr picks it up, renames/tags the files, and moves them into `<Root Folder>/Artist Name/Album/`
### Spotify playlist import
@@ -40,6 +40,7 @@ Lidarr doesn't natively import Spotify playlists. Use a community tool like [Spo
| `LIDARR_RESTART` | Restart policy (default: `unless-stopped`) |
| `LIDARR_PORT` | Published port for the web UI (default: `8686`) |
| `VOL_PATH` | Base path for persistent data volumes (default: `/data`) |
| `LIDARR_MEDIA` | Shared media root on the host (default: `/data/media`), mounted at `/media`. Must be the same folder qBittorrent, Sonarr, Radarr and Jellyfin use |
| `TZ` | Container timezone (default: `America/Vancouver`) |
## Volume Notes
@@ -47,7 +48,7 @@ Lidarr doesn't natively import Spotify playlists. Use a community tool like [Spo
| Volume | Purpose |
|---|---|
| `${VOL_PATH:-/data}/lidarr/config` | Application configuration and database |
| `${VOL_PATH:-/data}/lidarr/data` | Download client data and working directory |
| `${LIDARR_MEDIA:-/data/media}` → `/media` | Shared media root: downloads in `/media/downloads`, library in `/media/music` |
## Network Notes
@@ -68,7 +69,7 @@ docker run -d \
-e TZ=America/Vancouver \
-p 8686:8686 \
-v ${VOL_PATH:-/data}/lidarr/config:/config \
-v ${VOL_PATH:-/data}/lidarr/data:/data \
-v ${LIDARR_MEDIA:-/data/media}:/media \
--network proxy \
--restart unless-stopped \
ghcr.io/hotio/lidarr:release
@@ -76,7 +77,9 @@ docker run -d \
## Additional Notes / Gotchas
Nothing specific to this stack so far.
- **One shared media folder.** qBittorrent, Sonarr, Radarr, Lidarr and Jellyfin all use `/data/media` on the host, mounted at `/media`, so a download has the same path in every container: no Remote Path Mapping needed, and imports can use hardlinks. Enable **Settings → Media Management → Use Hardlinks instead of Copy**.
- **Layout:** `/data/media/downloads/prowlarr` (qBittorrent category `prowlarr`), `/data/media/music` (Lidarr root, Jellyfin's `/music` library).
- In the qBittorrent download client settings, set **Category** to `prowlarr`.
## Dockhand Stack, Deploy from Git
+1 -1
View File
@@ -4,7 +4,7 @@ services:
restart: ${LIDARR_RESTART:-unless-stopped}
volumes:
- ${VOL_PATH:-/data}/lidarr/config:/config
- ${VOL_PATH:-/data}/lidarr/data:/data
- ${LIDARR_MEDIA:-/data/media}:/media
environment:
- PUID=1000
- PGID=1000
+1
View File
@@ -4,3 +4,4 @@ LIDARR_IMAGE=ghcr.io/hotio/lidarr:release
TZ=America/Vancouver
LIDARR_PORT=8686
LIDARR_RESTART=unless-stopped
LIDARR_MEDIA=/data/media
+14 -2
View File
@@ -25,11 +25,12 @@ BitTorrent client with a full-featured web UI.
QBT_PASS – default: ChangeThisPassword
QBT_PORT – default: 8080
QBT_MEDIA – default: /data/media (shared media root, also mounted by Sonarr, Radarr and Jellyfin)
## Volume Notes
/config – host path /data/qbit/config
/downloads – host path /data/qbit/downloads
/media – host path /data/media (downloads go to /media/downloads)
/incomplete – host path /data/qbit/incomplete
/dev/net/tun – host path /dev/net/tun
@@ -44,7 +45,7 @@ docker run -d \
--name qbittorrent \
-p 8080:8080 \
-v /data/qbit/config:/config \
-v /data/qbit/downloads:/downloads \
-v /data/media:/media \
-v /data/qbit/incomplete:/incomplete \
-v /dev/net/tun:/dev/net/tun \
trigus42/qbittorrentvpn:latest
@@ -56,6 +57,17 @@ See compose.yaml for the full set of environment variables.
Check the container logs on first start for the temporary web UI password.
### Shared media folder (for Sonarr / Radarr / Jellyfin)
`/data/media` on the host is mounted at `/media` in qBittorrent, Sonarr and Radarr, so a file has the same path in every container. Imports then work without Remote Path Mappings, and can use hardlinks instead of copying.
In qBittorrent, set:
- **Options → Downloads → Default Save Path:** `/media/downloads`
- **Category `prowlarr`** (right-click Categories → Add): save path `/media/downloads/prowlarr`
Then in Sonarr/Radarr set the qBittorrent download client's **Category** to `prowlarr`.
## Dockhand Stack, Deploy from Git
Cookbooks Repository
+1 -1
View File
@@ -4,7 +4,7 @@ services:
restart: ${QBT_RESTART:-unless-stopped}
volumes:
- ${VOL_PATH:-/data}/qbit/config:/config
- ${VOL_PATH:-/data}/qbit/downloads:/downloads
- ${QBT_MEDIA:-/data/media}:/media
- ${VOL_PATH:-/data}/qbit/incomplete:/incomplete
- ${VOL_PATH:-/data}/qbit/watched:/watched
- /dev/net/tun:/dev/net/tun
+1
View File
@@ -4,3 +4,4 @@ QBT_IMAGE=trigus42/qbittorrentvpn:latest
QBT_RESTART=unless-stopped
QBT_PORT=8080
QBT_PASS=ChangeThisPassword
QBT_MEDIA=/data/media
+10 -8
View File
@@ -26,7 +26,7 @@ Once the wizard finishes, you'll see an empty library. To populate it:
### Download flow
qBittorrent downloads to its own directory → Radarr picks it up, renames the file, and moves it into `<Root Folder>/Movie Name (Year)/`
qBittorrent downloads to `/media/downloads/prowlarr` → Radarr picks it up, renames the file, and moves it into `<Root Folder>/Movie Name (Year)/`
## Environment Variable Notes
@@ -36,7 +36,7 @@ qBittorrent downloads to its own directory → Radarr picks it up, renames the f
| `RADARR_RESTART` | Restart policy (default: `unless-stopped`) |
| `RADARR_PORT` | Published port for the web UI (default: `7878`) |
| `VOL_PATH` | Base path for persistent data volumes (default: `/data`) |
| `RADARR_MEDIA` | Path to the shared media library (default: `/data/media`) — point this at the same library used by Sonarr, Bazarr, and Jellyfin/etc. so downloads land in the shared library |
| `RADARR_MEDIA` | Shared media root on the host (default: `/data/media`), mounted at `/media`. Must be the same folder qBittorrent, Sonarr and Jellyfin use |
| `TZ` | Container timezone (default: `America/Vancouver`) |
## Volume Notes
@@ -44,7 +44,7 @@ qBittorrent downloads to its own directory → Radarr picks it up, renames the f
| Volume | Purpose |
|---|---|
| `${VOL_PATH:-/data}/radarr/config` | Application configuration and database |
| `${RADARR_MEDIA:-/data/media}` | Shared media library, kept separate from `VOL_PATH` since it's typically the same library mounted into Sonarr, Bazarr, and Jellyfin/etc. |
| `${RADARR_MEDIA:-/data/media}` → `/media` | Shared media library, kept separate from `VOL_PATH` since it's typically mounted into Sonarr, Radarr, Bazarr, and Jellyfin/etc. |
## Network Notes
@@ -73,13 +73,15 @@ docker run -d \
## Additional Notes / Gotchas
Nothing specific to this stack so far.
- **One shared media folder.** qBittorrent, Sonarr, Radarr and Jellyfin all use `/data/media` on the host. qBittorrent, Sonarr and Radarr mount it at `/media`, so a download has the same path in every container: no Remote Path Mapping needed, and imports can use hardlinks (instant, no extra disk space). Enable **Settings → Media Management → Use Hardlinks instead of Copy**.
- **Layout:** `/data/media/downloads/prowlarr` (qBittorrent category `prowlarr`), `/data/media/shows` (Sonarr), `/data/media/movies` (Radarr). The `shows`/`movies` names match the Jellyfin stack's library mounts.
- In the qBittorrent download client settings, set **Category** to `prowlarr`.
## Dockhand Stack, Deploy from Git
- **Cookbooks Repository**
- **stackname:** radarr_dev
- **Compose file path:** radarr_dev/compose.yaml
- **Additional env file (optional):** radarr_dev/sample.env
- **stackname:** radarr
- **Compose file path:** radarr/compose.yaml
- **Additional env file (optional):** radarr/sample.env
Load `radarr_dev/sample.env` into the Environment variables in Dockhand, then create the Stack.
Load `radarr/sample.env` into the Environment variables in Dockhand, then create the Stack.
+8 -5
View File
@@ -20,13 +20,13 @@ Open http://localhost:8787 in your browser and complete the initial setup wizard
Once the wizard finishes, you'll see an empty library. To populate it:
- Go to **Settings → Media Management** and add a **Root Folder** (e.g., `/books`) — this is where your organized book library will live
- Go to **Settings → Media Management** and add a **Root Folder** (e.g., `/media/books`) — this is where your organized book library will live
- Click **Add Author** and search by name — Readarr fetches metadata, covers, and available editions
- Optionally connect a **List** (Goodreads, etc.) to auto-import authors from your reading lists
### Download flow
qBittorrent downloads to its own directory → Readarr picks it up, renames the file, and moves it into `<Root Folder>/Author Name/Book Name/`
qBittorrent downloads to `/media/downloads/prowlarr` → Readarr picks it up, renames the file, and moves it into `<Root Folder>/Author Name/Book Name/`
## Environment Variable Notes
@@ -36,6 +36,7 @@ qBittorrent downloads to its own directory → Readarr picks it up, renames the
| `READARR_RESTART` | Restart policy (default: `unless-stopped`) |
| `READARR_PORT` | Published port for the web UI (default: `8787`) |
| `VOL_PATH` | Base path for persistent data volumes (default: `/data`) |
| `READARR_MEDIA` | Shared media root on the host (default: `/data/media`), mounted at `/media`. Must be the same folder qBittorrent, Sonarr, Radarr and Jellyfin use |
| `TZ` | Container timezone (default: `America/Vancouver`) |
## Volume Notes
@@ -43,7 +44,7 @@ qBittorrent downloads to its own directory → Readarr picks it up, renames the
| Volume | Purpose |
|---|---|
| `${VOL_PATH:-/data}/readarr/config` | Application configuration and database |
| `${VOL_PATH:-/data}/readarr/data` | Download client data and working directory |
| `${READARR_MEDIA:-/data/media}` → `/media` | Shared media root: downloads in `/media/downloads`, library in `/media/books` |
## Network Notes
@@ -64,7 +65,7 @@ docker run -d \
-e TZ=America/Vancouver \
-p 8787:8787 \
-v ${VOL_PATH:-/data}/readarr/config:/config \
-v ${VOL_PATH:-/data}/readarr/data:/data \
-v ${READARR_MEDIA:-/data/media}:/media \
--network proxy \
--restart unless-stopped \
ghcr.io/hotio/readarr:release
@@ -72,7 +73,9 @@ docker run -d \
## Additional Notes / Gotchas
Nothing specific to this stack so far.
- **One shared media folder.** qBittorrent, Sonarr, Radarr, Readarr and Jellyfin all use `/data/media` on the host, mounted at `/media`, so a download has the same path in every container: no Remote Path Mapping needed, and imports can use hardlinks. Enable **Settings → Media Management → Use Hardlinks instead of Copy**.
- **Layout:** `/data/media/downloads/prowlarr` (qBittorrent category `prowlarr`), `/data/media/books` (Readarr root, Jellyfin's `/books` library).
- In the qBittorrent download client settings, set **Category** to `prowlarr`.
## Dockhand Stack, Deploy from Git
+1 -1
View File
@@ -4,7 +4,7 @@ services:
restart: ${READARR_RESTART:-unless-stopped}
volumes:
- ${VOL_PATH:-/data}/readarr/config:/config
- ${VOL_PATH:-/data}/readarr/data:/data
- ${READARR_MEDIA:-/data/media}:/media
environment:
- PUID=1000
- PGID=1000
+1
View File
@@ -4,3 +4,4 @@ READARR_IMAGE=ghcr.io/hotio/readarr:release
TZ=America/Vancouver
READARR_PORT=8787
READARR_RESTART=unless-stopped
READARR_MEDIA=/data/media
+12 -9
View File
@@ -20,13 +20,13 @@ Open http://localhost:8989 in your browser and complete the initial setup wizard
Once the wizard finishes, you'll see an empty library. To populate it:
- Go to **Settings → Media Management** and add a **Root Folder** (e.g., `/tv`) — this is where your organized TV library will live
- Go to **Settings → Media Management** and add a **Root Folder** (e.g., `/media/shows`) — this is where your organized TV library will live
- Click **Add Series** and search by title — Sonarr fetches metadata, posters, and available releases
- Optionally connect a **List** (Trakt, IMDb, etc.) to auto-import series from your watchlists
### Download flow
qBittorrent downloads to its own directory → Sonarr picks it up, renames the file, and moves it into `<Root Folder>/Series Name/Season XX/`
qBittorrent downloads to `/media/downloads/prowlarr` → Sonarr picks it up, renames the file, and moves it into `<Root Folder>/Series Name/Season XX/`
## Environment Variable Notes
@@ -36,6 +36,7 @@ qBittorrent downloads to its own directory → Sonarr picks it up, renames the f
| `SONARR_RESTART` | Restart policy (default: `unless-stopped`) |
| `SONARR_PORT` | Published port for the web UI (default: `8989`) |
| `VOL_PATH` | Base path for persistent data volumes (default: `/data`) |
| `SONARR_MEDIA` | Shared media root on the host (default: `/data/media`), mounted at `/media`. Must be the same folder qBittorrent, Radarr and Jellyfin use |
| `TZ` | Container timezone (default: `America/Vancouver`) |
## Volume Notes
@@ -43,7 +44,7 @@ qBittorrent downloads to its own directory → Sonarr picks it up, renames the f
| Volume | Purpose |
|---|---|
| `${VOL_PATH:-/data}/sonarr/config` | Application configuration and database |
| `${VOL_PATH:-/data}/sonarr/data` | Download client data and working directory |
| `${SONARR_MEDIA:-/data/media}` → `/media` | Shared media library, kept separate from `VOL_PATH` since it's typically mounted into Sonarr, Radarr, Bazarr, and Jellyfin/etc. |
## Network Notes
@@ -64,7 +65,7 @@ docker run -d \
-e TZ=America/Vancouver \
-p 8989:8989 \
-v ${VOL_PATH:-/data}/sonarr/config:/config \
-v ${VOL_PATH:-/data}/sonarr/data:/data \
-v ${SONARR_MEDIA:-/data/media}:/media \
--network proxy \
--restart unless-stopped \
ghcr.io/hotio/sonarr:release
@@ -72,13 +73,15 @@ docker run -d \
## Additional Notes / Gotchas
Nothing specific to this stack so far.
- **One shared media folder.** qBittorrent, Sonarr, Radarr and Jellyfin all use `/data/media` on the host. qBittorrent, Sonarr and Radarr mount it at `/media`, so a download has the same path in every container: no Remote Path Mapping needed, and imports can use hardlinks (instant, no extra disk space). Enable **Settings → Media Management → Use Hardlinks instead of Copy**.
- **Layout:** `/data/media/downloads/prowlarr` (qBittorrent category `prowlarr`), `/data/media/shows` (Sonarr), `/data/media/movies` (Radarr). The `shows`/`movies` names match the Jellyfin stack's library mounts.
- In the qBittorrent download client settings, set **Category** to `prowlarr`.
## Dockhand Stack, Deploy from Git
- **Cookbooks Repository**
- **stackname:** sonarr_dev
- **Compose file path:** sonarr_dev/compose.yaml
- **Additional env file (optional):** sonarr_dev/sample.env
- **stackname:** sonarr
- **Compose file path:** sonarr/compose.yaml
- **Additional env file (optional):** sonarr/sample.env
Load `sonarr_dev/sample.env` into the Environment variables in Dockhand, then create the Stack.
Load `sonarr/sample.env` into the Environment variables in Dockhand, then create the Stack.
@@ -4,7 +4,7 @@ services:
restart: ${SONARR_RESTART:-unless-stopped}
volumes:
- ${VOL_PATH:-/data}/sonarr/config:/config
- ${VOL_PATH:-/data}/sonarr/data:/data
- ${SONARR_MEDIA:-/data/media}:/media
environment:
- PUID=1000
- PGID=1000
@@ -4,3 +4,4 @@ SONARR_IMAGE=ghcr.io/hotio/sonarr:release
TZ=America/Vancouver
SONARR_PORT=8989
SONARR_RESTART=unless-stopped
SONARR_MEDIA=/data/media
+8 -5
View File
@@ -20,13 +20,13 @@ Open http://localhost:6969 in your browser and complete the initial setup wizard
Once the wizard finishes, you'll see an empty library. To populate it:
- Go to **Settings → Media Management** and add a **Root Folder** (e.g., `/adult`) — this is where your organized library will live
- Go to **Settings → Media Management** and add a **Root Folder** (e.g., `/media/adult`) — this is where your organized library will live
- Click **Add Movie** and search by title — Whisparr fetches metadata and available releases
- Optionally connect a **List** to auto-import from your watchlists
### Download flow
qBittorrent downloads to its own directory → Whisparr picks it up, renames the file, and moves it into `<Root Folder>/Title (Year)/`
qBittorrent downloads to `/media/downloads/prowlarr` → Whisparr picks it up, renames the file, and moves it into `<Root Folder>/Title (Year)/`
## Environment Variable Notes
@@ -36,6 +36,7 @@ qBittorrent downloads to its own directory → Whisparr picks it up, renames the
| `WHISPARR_RESTART` | Restart policy (default: `unless-stopped`) |
| `WHISPARR_PORT` | Published port for the web UI (default: `6969`) |
| `VOL_PATH` | Base path for persistent data volumes (default: `/data`) |
| `WHISPARR_MEDIA` | Shared media root on the host (default: `/data/media`), mounted at `/media`. Must be the same folder qBittorrent, Sonarr, Radarr and Jellyfin use |
| `TZ` | Container timezone (default: `America/Vancouver`) |
## Volume Notes
@@ -43,7 +44,7 @@ qBittorrent downloads to its own directory → Whisparr picks it up, renames the
| Volume | Purpose |
|---|---|
| `${VOL_PATH:-/data}/whisparr/config` | Application configuration and database |
| `${VOL_PATH:-/data}/whisparr/data` | Download client data and working directory |
| `${WHISPARR_MEDIA:-/data/media}` → `/media` | Shared media root: downloads in `/media/downloads`, library in `/media/adult` |
## Network Notes
@@ -64,7 +65,7 @@ docker run -d \
-e TZ=America/Vancouver \
-p 6969:6969 \
-v ${VOL_PATH:-/data}/whisparr/config:/config \
-v ${VOL_PATH:-/data}/whisparr/data:/data \
-v ${WHISPARR_MEDIA:-/data/media}:/media \
--network proxy \
--restart unless-stopped \
ghcr.io/hotio/whisparr:release
@@ -72,7 +73,9 @@ docker run -d \
## Additional Notes / Gotchas
Nothing specific to this stack so far.
- **One shared media folder.** qBittorrent, Sonarr, Radarr, Whisparr and Jellyfin all use `/data/media` on the host, mounted at `/media`, so a download has the same path in every container: no Remote Path Mapping needed, and imports can use hardlinks. Enable **Settings → Media Management → Use Hardlinks instead of Copy**.
- **Layout:** `/data/media/downloads/prowlarr` (qBittorrent category `prowlarr`), `/data/media/adult` (Whisparr root, not mounted by Jellyfin by default).
- In the qBittorrent download client settings, set **Category** to `prowlarr`.
## Dockhand Stack, Deploy from Git
+1 -1
View File
@@ -4,7 +4,7 @@ services:
restart: ${WHISPARR_RESTART:-unless-stopped}
volumes:
- ${VOL_PATH:-/data}/whisparr/config:/config
- ${VOL_PATH:-/data}/whisparr/data:/data
- ${WHISPARR_MEDIA:-/data/media}:/media
environment:
- PUID=1000
- PGID=1000
+1
View File
@@ -4,3 +4,4 @@ WHISPARR_IMAGE=ghcr.io/hotio/whisparr:release
TZ=America/Vancouver
WHISPARR_PORT=6969
WHISPARR_RESTART=unless-stopped
WHISPARR_MEDIA=/data/media