Skip to content

g1ronn1mo/arr-new

 
 

Repository files navigation

arr-new

Docker Compose stack for Radarr, Sonarr, Bazarr, SABnzbd, Prowlarr, Profilarr, Configarr, Jellyseerr (Seerr), and Jellyfin. Download clients and indexers use Gluetun with Mullvad WireGuard; Jellyfin stays on the default bridge with ports exposed for LAN streaming.

Requirements

  • Docker with Compose v2.
  • CONFIG_ROOT and DATA_ROOT in .env (defaults './config' and './data'). Relative values resolve from the compose project directory when you use a project-local .env; prefer absolute paths (e.g. CONFIG_ROOT='/home/you/arr-new/config') or always run ./bin/stack up -d so bind mounts never point at an empty directory.
  • PUID / PGID: match id -u and id -g on the host unless you use PUID=0 / PGID=0 (root in containers, weaker isolation). Compose fix-bind-perms chowns CONFIG_ROOT and DATA_ROOT to that pair. Faster manual fix: ./bin/fix-bindmount-permissions.sh --data-top-only.

Quick start

  1. Copy and edit the environment file:

    cp .env.example .env
  2. Set Mullvad WireGuard in .env: WIREGUARD_PRIVATE_KEY, WIREGUARD_ADDRESSES. Optional: SERVER_COUNTRIES, SERVER_CITIES, VPN_TYPE, VPN_SERVICE_PROVIDER (defaults to mullvad).

  3. Set CONFIG_ROOT and DATA_ROOT to absolute host paths. Set TZ, PUID, and PGID.

  4. If Gluetun cannot reach the LAN or other services, set FIREWALL_OUTBOUND_SUBNETS (include your LAN CIDR). If indexers fail DNS through the VPN, set DNS_UNBLOCK_HOSTNAMES (comma-separated hostnames).

  5. Optional: prepare library folders — see Storage layout.

  6. Start the stack:

    ./bin/stack up -d

Services and ports

VPN-routed apps exit through Gluetun. Published ports are on the gluetun container:

Port Service
8080 SABnzbd
7878 Radarr
8989 Sonarr
6767 Bazarr
9696 Prowlarr
6868 Profilarr
5055 Jellyseerr

Gluetun also exposes 9090/tcp; nothing in this compose file uses it by default.

Jellyfin uses 8096/tcp (HTTP) and 7359/udp (discovery) on its own container.

Configarr has no web UI/port in this stack. It runs as an on-demand worker container.

Reverse proxy (optional)

The reverse-proxy service runs nginx with network_mode: host, listens on 8888, and routes by Host to localhost on the same ports Gluetun and Jellyfin already publish (with X-Forwarded-* headers for Seerr and others).

  1. Add static hostnames (replace the IP with this machine’s LAN address):

    192.168.178.x seerr.arr.local radarr.arr.local sonarr.arr.local bazarr.arr.local
    192.168.178.x sabnzbd.arr.local prowlarr.arr.local profilarr.arr.local jellyfin.arr.local
    
  2. Open apps at http://<name>.arr.local:8888 (example: http://seerr.arr.local:8888).

  3. In SeerrSettings → General → Application URL, use the same URL you type in the browser, including :8888.

  4. Config lives in config/reverse-proxy/conf.d/arr-stack.conf. For port 80, change listen 8888 to listen 80 everywhere in that file (avoid conflicts with another web server).

Direct access on :5055, :7878, and so on still works without the proxy.

Networking notes

FIREWALL_OUTBOUND_SUBNETS defaults to Docker bridge ranges (172.17.0.0/16, 172.18.0.0/16). Add your LAN (e.g. 192.168.178.0/24) if Jellyseerr must reach Jellyfin on the host or another machine; otherwise Jellyfin login during setup may fail with 404 on POST /api/v1/auth/jellyfin. GET /api/v1/auth/me returning 403 when logged out is normal. DNS_UNBLOCK_HOSTNAMES is empty by default; set it if indexers need DNS outside the VPN tunnel.

host.docker.internal is available inside Gluetun to reach the host when needed.

Storage layout

Use one host share (or directory) for DATA_ROOT — in this example it is called data. Folders are all lowercase so paths match on Linux (case-sensitive). This matches the spirit of the TRaSH Docker folder guide: downloads live under torrents and usenet; libraries (what you give Jellyfin, Plex, or Emby) live under media.

data
├── torrents
│   ├── books
│   ├── movies
│   ├── music
│   └── tv
├── usenet
│   ├── incomplete
│   └── complete
│       ├── books
│       ├── movies
│       ├── music
│       └── tv
└── media
    ├── books
    ├── movies
    ├── music
    └── tv

In containers the same tree appears under /data (compose bind-mounts DATA_ROOT/data for *Arr and SABnzbd). Jellyfin also mounts DATA_ROOT/data, so paths like /data/media/movies match everywhere.

Bootstrap (bootstrap-media-paths.sh)

./bin/bootstrap-media-paths.sh creates the torrents, usenet, and media subtree under DATA_ROOT. If Radarr / Sonarr databases exist but RootFolders is empty, it seeds /data/media/movies (Radarr) and /data/media/tv (Sonarr).

RAID / new disk (create-single-data-volume.sh)

bin/create-single-data-volume.sh creates the same tree on a fresh /data volume (see script header for warnings).

*Arr root folders and Jellyfin libraries

Purpose Path inside containers
Radarr movie root /data/media/movies
Sonarr TV root /data/media/tv
Jellyfin (main libraries) /data/media/movies, /data/media/tv, and optionally /data/media/{books,music}

Root folder in Radarr/Sonarr means the library tree only (**/data/media/...**). Do not add /data/usenet/complete/movies (or any .../usenet/...) as a root folder—that path is for SABnzbd output and *Arr imports. If Radarr says “Download client SABnzbd places downloads in the root folder …/usenet/complete/movies”, you have that Usenet path (or a parent of it) registered as a Root Folder. Remove it under SettingsMedia ManagementRoot Folders and keep only /data/media/movies.

Keep completed Usenet output under /data/usenet/complete/... and let *Arr import (hardlink) into /data/media/.... Enable Use Hardlinks instead of Copy in Radarr / SonarrSettingsMedia Management so imports work when usenet and media are on the same filesystem.

SABnzbd (paths inside the container)

Setting Path
Temporary Download Folder /data/usenet/incomplete
Completed Download Folder /data/usenet/complete (the parent of movies / tv / … — not .../complete/movies as the global default)

Categories (optional per-category folder; match names you use in *Arr):

Category Path
movies /data/usenet/complete/movies
tv /data/usenet/complete/tv
music /data/usenet/complete/music
books /data/usenet/complete/books

Use books / music only if you configure download clients and *Arr apps for them; otherwise leave Default or omit those categories.

Radarr’s Download Client category movies only tells SABnzbd which SABnzbd category to use; completed files still land under /data/usenet/complete/movies via the table above, while the movie library remains /data/media/movies—two different paths, which is what *Arr expects.

Torrent clients (optional)

If you add qBittorrent or another client later, point its save paths at /data/torrents/{movies,tv,...} so seeds and incomplete data stay beside usenet and media under one /data tree (same rules for hardlinks into /data/media).

First-time app configuration

Apps behind Gluetun share one network namespace; use http://127.0.0.1:<port> when one container talks to another.

Prowlarr

  1. IndexersAdd indexer → protocol Usenet. Search for Generic Newznab (not a branded preset). Set the indexer URL and API key, then Test and Save. Example (SceneNZBs): URL https://scenenzbs.com, API key from your account on scenenzbs.com.

  2. SettingsApps → add Radarr and Sonarr: base URL http://127.0.0.1:7878 and http://127.0.0.1:8989, with each app’s API key from SettingsGeneralSecurity. Test, Save, then sync indexers when prompted.

Radarr and Sonarr → SABnzbd

In each app: SettingsDownload Clients → add SABnzbd:

  • Host: 127.0.0.1
  • Port: 8080
  • API key: from SABnzbd ConfigGeneral (or security section, depending on version)
  • Category: e.g. movies (Radarr) and tv (Sonarr), matching SABnzbd category names

Test, then Save.

Profilarr manages quality profiles (optional); it does not replace SABnzbd as a download client.

Configarr (optional)

configarr uses config/configarr for config.yml and secrets.yml, and caches repos in config/configarr/repos.

Run it on demand:

./bin/stack run --rm configarr

Helper scripts

Script Purpose
bin/stack Runs docker compose with the repo as cwd. Example: ./bin/stack up -d.
bin/bootstrap-media-paths.sh Creates TRaSH-style media, usenet, torrents trees (lowercase books / movies / music / tv); seeds empty Radarr/Sonarr root folders to /data/media/movies and /data/media/tv when RootFolders is empty.
bin/fix-bindmount-permissions.sh Same chown idea as compose fix-bind-perms; --data-top-only avoids a full recursive DATA_ROOT pass.
bin/create-single-data-volume.sh Destructive, machine-specific: RAID0 from sda + sdb + sdc, mount at '/data', create torrents / usenet / media tree (same layout as above). Runs docker compose down before disk work.
bin/assemble-md0.sh Reassemble existing Linux RAID on sda + sdb, mount ext4 at '/mnt/md0'.
bin/setup-mergerfs-pool.sh Optional mergerfs pool ('/mnt/md0:/mnt/disk-sdc''/mnt/media-pool' by default).
bin/restore-data-from-external.sh Copy data-backup/ from a mounted drive (default '/mnt/external') to '/data'.
bin/prune-usenet-root-folders.sh Removes Radarr / Sonarr Root Folder entries whose path contains usenet (fixes “download client … places downloads in the root folder …/usenet/…”). Requires running radarr / sonarr containers.

Troubleshooting

See TROUBLESHOOTING.md (for example indexer HTTP 429 / rate limits, or Radarr “download to root folder” / usenet paths).

About

New ARR stack 2026

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Shell 100.0%