From 7ed139d13416658298a55fdc3ba9d944bcd1bd27 Mon Sep 17 00:00:00 2001 From: code Date: Mon, 2 Nov 2026 17:43:22 +0000 Subject: [PATCH] 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 --- jellyfin/README.md | 101 ++++++++++++++++++++ {jellyfin_dev => jellyfin}/compose.yaml | 3 - {jellyfin_dev => jellyfin}/sample.env | 0 jellyfin_dev/README.md | 75 --------------- {jellyseerr_dev => jellyseerr}/README.md | 27 ++++-- {jellyseerr_dev => jellyseerr}/compose.yaml | 1 + {jellyseerr_dev => jellyseerr}/sample.env | 1 + lidarr_dev/README.md | 13 ++- lidarr_dev/compose.yaml | 2 +- lidarr_dev/sample.env | 1 + qbittorrent/README.md | 16 +++- qbittorrent/compose.yaml | 2 +- qbittorrent/sample.env | 1 + {radarr_dev => radarr}/README.md | 18 ++-- {radarr_dev => radarr}/compose.yaml | 0 {radarr_dev => radarr}/sample.env | 0 readarr_dev/README.md | 13 ++- readarr_dev/compose.yaml | 2 +- readarr_dev/sample.env | 1 + {sonarr_dev => sonarr}/README.md | 21 ++-- {sonarr_dev => sonarr}/compose.yaml | 2 +- {sonarr_dev => sonarr}/sample.env | 1 + whisparr_dev/README.md | 13 ++- whisparr_dev/compose.yaml | 2 +- whisparr_dev/sample.env | 1 + 25 files changed, 193 insertions(+), 124 deletions(-) create mode 100644 jellyfin/README.md rename {jellyfin_dev => jellyfin}/compose.yaml (88%) rename {jellyfin_dev => jellyfin}/sample.env (100%) delete mode 100644 jellyfin_dev/README.md rename {jellyseerr_dev => jellyseerr}/README.md (59%) rename {jellyseerr_dev => jellyseerr}/compose.yaml (91%) rename {jellyseerr_dev => jellyseerr}/sample.env (86%) rename {radarr_dev => radarr}/README.md (63%) rename {radarr_dev => radarr}/compose.yaml (100%) rename {radarr_dev => radarr}/sample.env (100%) rename {sonarr_dev => sonarr}/README.md (59%) rename {sonarr_dev => sonarr}/compose.yaml (90%) rename {sonarr_dev => sonarr}/sample.env (84%) diff --git a/jellyfin/README.md b/jellyfin/README.md new file mode 100644 index 0000000..ed3c2bd --- /dev/null +++ b/jellyfin/README.md @@ -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. diff --git a/jellyfin_dev/compose.yaml b/jellyfin/compose.yaml similarity index 88% rename from jellyfin_dev/compose.yaml rename to jellyfin/compose.yaml index a4bf816..199ebf4 100644 --- a/jellyfin_dev/compose.yaml +++ b/jellyfin/compose.yaml @@ -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: diff --git a/jellyfin_dev/sample.env b/jellyfin/sample.env similarity index 100% rename from jellyfin_dev/sample.env rename to jellyfin/sample.env diff --git a/jellyfin_dev/README.md b/jellyfin_dev/README.md deleted file mode 100644 index c145a00..0000000 --- a/jellyfin_dev/README.md +++ /dev/null @@ -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 diff --git a/jellyseerr_dev/README.md b/jellyseerr/README.md similarity index 59% rename from jellyseerr_dev/README.md rename to jellyseerr/README.md index ddc5d4b..43f9ec8 100644 --- a/jellyseerr_dev/README.md +++ b/jellyseerr/README.md @@ -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. diff --git a/jellyseerr_dev/compose.yaml b/jellyseerr/compose.yaml similarity index 91% rename from jellyseerr_dev/compose.yaml rename to jellyseerr/compose.yaml index b995591..d6c7ecc 100644 --- a/jellyseerr_dev/compose.yaml +++ b/jellyseerr/compose.yaml @@ -8,6 +8,7 @@ services: - PUID=1000 - PGID=1000 - UMASK=002 + - TZ=${TZ:-America/Vancouver} ports: - "${JELLYSEERR_PORT:-5055}:5055" networks: diff --git a/jellyseerr_dev/sample.env b/jellyseerr/sample.env similarity index 86% rename from jellyseerr_dev/sample.env rename to jellyseerr/sample.env index e25cf59..4c0910e 100644 --- a/jellyseerr_dev/sample.env +++ b/jellyseerr/sample.env @@ -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 diff --git a/lidarr_dev/README.md b/lidarr_dev/README.md index e1f8985..7e0e0c8 100644 --- a/lidarr_dev/README.md +++ b/lidarr_dev/README.md @@ -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 `/Artist Name/Album/` +qBittorrent downloads to `/media/downloads/prowlarr` → Lidarr picks it up, renames/tags the files, and moves them into `/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 diff --git a/lidarr_dev/compose.yaml b/lidarr_dev/compose.yaml index 511d5ea..97fe2ef 100644 --- a/lidarr_dev/compose.yaml +++ b/lidarr_dev/compose.yaml @@ -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 diff --git a/lidarr_dev/sample.env b/lidarr_dev/sample.env index f9e3153..8e20255 100644 --- a/lidarr_dev/sample.env +++ b/lidarr_dev/sample.env @@ -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 diff --git a/qbittorrent/README.md b/qbittorrent/README.md index 020af71..2f8c2cb 100644 --- a/qbittorrent/README.md +++ b/qbittorrent/README.md @@ -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 diff --git a/qbittorrent/compose.yaml b/qbittorrent/compose.yaml index 8173073..aa7939b 100644 --- a/qbittorrent/compose.yaml +++ b/qbittorrent/compose.yaml @@ -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 diff --git a/qbittorrent/sample.env b/qbittorrent/sample.env index 1852a6f..7da607f 100644 --- a/qbittorrent/sample.env +++ b/qbittorrent/sample.env @@ -4,3 +4,4 @@ QBT_IMAGE=trigus42/qbittorrentvpn:latest QBT_RESTART=unless-stopped QBT_PORT=8080 QBT_PASS=ChangeThisPassword +QBT_MEDIA=/data/media diff --git a/radarr_dev/README.md b/radarr/README.md similarity index 63% rename from radarr_dev/README.md rename to radarr/README.md index 80bd9eb..453b198 100644 --- a/radarr_dev/README.md +++ b/radarr/README.md @@ -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 `/Movie Name (Year)/` +qBittorrent downloads to `/media/downloads/prowlarr` → Radarr picks it up, renames the file, and moves it into `/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. diff --git a/radarr_dev/compose.yaml b/radarr/compose.yaml similarity index 100% rename from radarr_dev/compose.yaml rename to radarr/compose.yaml diff --git a/radarr_dev/sample.env b/radarr/sample.env similarity index 100% rename from radarr_dev/sample.env rename to radarr/sample.env diff --git a/readarr_dev/README.md b/readarr_dev/README.md index 5218d0c..d995858 100644 --- a/readarr_dev/README.md +++ b/readarr_dev/README.md @@ -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 `/Author Name/Book Name/` +qBittorrent downloads to `/media/downloads/prowlarr` → Readarr picks it up, renames the file, and moves it into `/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 diff --git a/readarr_dev/compose.yaml b/readarr_dev/compose.yaml index 0b6dcc3..88ac3a0 100644 --- a/readarr_dev/compose.yaml +++ b/readarr_dev/compose.yaml @@ -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 diff --git a/readarr_dev/sample.env b/readarr_dev/sample.env index 3779bd6..0c08584 100644 --- a/readarr_dev/sample.env +++ b/readarr_dev/sample.env @@ -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 diff --git a/sonarr_dev/README.md b/sonarr/README.md similarity index 59% rename from sonarr_dev/README.md rename to sonarr/README.md index e2d20bd..ea44929 100644 --- a/sonarr_dev/README.md +++ b/sonarr/README.md @@ -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 `/Series Name/Season XX/` +qBittorrent downloads to `/media/downloads/prowlarr` → Sonarr picks it up, renames the file, and moves it into `/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. diff --git a/sonarr_dev/compose.yaml b/sonarr/compose.yaml similarity index 90% rename from sonarr_dev/compose.yaml rename to sonarr/compose.yaml index 13a1634..f750d81 100644 --- a/sonarr_dev/compose.yaml +++ b/sonarr/compose.yaml @@ -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 diff --git a/sonarr_dev/sample.env b/sonarr/sample.env similarity index 84% rename from sonarr_dev/sample.env rename to sonarr/sample.env index 84173bc..a227d2c 100644 --- a/sonarr_dev/sample.env +++ b/sonarr/sample.env @@ -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 diff --git a/whisparr_dev/README.md b/whisparr_dev/README.md index 2309803..51ee72e 100644 --- a/whisparr_dev/README.md +++ b/whisparr_dev/README.md @@ -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 `/Title (Year)/` +qBittorrent downloads to `/media/downloads/prowlarr` → Whisparr picks it up, renames the file, and moves it into `/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 diff --git a/whisparr_dev/compose.yaml b/whisparr_dev/compose.yaml index 7910dae..190297b 100644 --- a/whisparr_dev/compose.yaml +++ b/whisparr_dev/compose.yaml @@ -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 diff --git a/whisparr_dev/sample.env b/whisparr_dev/sample.env index ac91188..95bde0f 100644 --- a/whisparr_dev/sample.env +++ b/whisparr_dev/sample.env @@ -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