Post

Setting up *ARR stack

Setting up *ARR stack

Guide to setup *ARR stack - self hosted streaming platform

Arr is a bunch of services made by servarr org. The services basically allows to easily add movies / TV shoes to your media server. Not just that here i have gived some services which will fetch the movie or series you want put it to download. When download is completed it adds it to the media server and download the caption for it all automatically.

Index

File Structure

For storing all the config file for each service that we are using

1
2
3
4
5
6
7
8
9
10
11
12
13
config
├── bazarr
├── emby
├── gluetun
├── jackett
├── jellyfin
├── plex
├── prowlarr
├── qbittorrent
├── radarr
├── sonarr
├── unpackerr
└── watchstate

For storing all the media file,
The downloading media will be there in the torrents or usenet (whatever you are using).
The completed media will be moved in the media directory by readarr or sonarr.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
data
├── incomplete
│   ├── movies
│   └── tv
├── media
│   ├── books
│   ├── movies
│   └── tv
├── torrents
│   ├── books
│   ├── incomplete
│   ├── movies
│   └── tv
└── usenet
    ├── books
    ├── incomplete
    ├── movies
    └── tv

Arr Services

Radarr

Its use to add, manage and remove movies. It searches the queried movie to the provided indexer and starts download via the download manager and moniters till its over downloading.

1
2
3
4
5
6
7
8
9
10
11
12
13
radarr:
  image: linuxserver/radarr
  user: ${UID}:${GID}
  restart: always
  ports:
    - "${PORT_RADARR}:7878"
  environment:
    - PGID=${GID}
    - PUID=${UID}
    - TZ=${TIMEZONE:?err}
  volumes:
    - ${CONFIG}/radarr:/config
    - ${DATA}:/data

Sonarr

Its use to add, manage and remove tv shows (and web series). It searches the queried show or series to the provided indexer and starts download via the download manager and moniters till its over downloading.

1
2
3
4
5
6
7
8
9
10
11
12
13
sonarr:
   image: linuxserver/sonarr
   user: ${UID}:${GID}
   restart: always
   ports:
     - "${PORT_SONARR}:8989"
   environment:
     - PGID=${GID}
     - PUID=${UID}
     - TZ=${TIMEZONE:?err}
   volumes:
     - ${CONFIG}/sonarr:/config
     - ${DATA}:/data

Arr indexer manager

Prowlarr

This service allows you to add indexer to Radarr and Sonarr.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
prowlarr:
  image: linuxserver/prowlarr
  user: ${UID}:${GID}
  restart: always
  ports:
    - "${PORT_PROWLARR}:9696"
  cap_add:
    - NET_ADMIN
  environment:
    - PGID=${GID}
    - PUID=${UID}
    - TZ=${TIMEZONE:?err}
  volumes:
    - ${CONFIG}/prowlarr:/config
    - ${DATA}:/data

Flaresolver

This is used to solve the cloudflare capcha. (currently not functional)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
flaresolverr:
  image: ghcr.io/flaresolverr/flaresolverr:latest
  user: ${UID}:${GID}
  restart: unless-stopped
  ports:
    - "${PORT_FLARESOL}:8191"
  environment:
    - PGID=${GID}
    - PUID=${UID}
    - LOG_LEVEL=debug
    - LOG_HTML=true
    # Enables hcaptcha-solver => https://github.com/JimmyLaurent/hcaptcha-solver
    - CAPTCHA_SOLVER=hcaptcha-solver
    # Enables CaptchaHarvester => https://github.com/NoahCardoza/CaptchaHarvester
    # - CAPTCHA_SOLVER=harvester
    # - HARVESTER_ENDPOINT=https://127.0.0.1:5000/token
    - TZ=${TIMEZONE:?err}

Jackett

This is another service that lets you add idexer but you have to import it manually to redarr and sonarr.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
jackett:
    image: lscr.io/linuxserver/jackett:latest
    user: ${UID}:${GID}
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=${TIMEZONE:?err}
      #- AUTO_UPDATE=true #optional
      #- RUN_OPTS= #optional
    volumes:
      - ${CONFIG}/jackett:/config
      - ${DATA}:/data
    ports:
      - ${PORT_JACKETT}:9117
    restart: unless-stopped

Download manager

Qbittorrent

A torrent download manager. Let you download the magnet link and the .torrent file given my the arr services.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
qbittorrent:
  image: linuxserver/qbittorrent
  user: ${UID}:${GID}
  restart: unless-stopped
  volumes:
    - ${CONFIG}/qbittorrent:/config
    - ${DATA}:/data
  environment:
    - PUID=${PUID}
    - PGID=${GUID}
    - TZ=${TIMEZONE:?err}
    - WEBUI_PORT=${PORT_QBIT}
  ports:
    - "${PORT_QBIT}:${PORT_QBIT}"
    - 6881:6881 # BitTorrent
    - 6881:6881/udp

Media Playback Server

Plex

A web server for streaming the media that you downloaded. The mobile client of it and transcoding is paid.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
plex:
  image: plexinc/pms-docker:latest # Set specific: plexinc/pms-docker:1.40.2.8395-c67dce28e
  ports:
    - ${PORT_PLEX}:32400/tcp
    - 8324:8324/tcp
    - 32469:32469/tcp
    - 1900:1900/udp
    - 32410:32410/udp
    - 32412:32412/udp
    - 32413:32413/udp
    - 32414:32414/udp
  environment:
    - PUID=${PUID}
    - PGID=${GUID}
    - TZ=${TIMEZONE:?err} # Change this to match your server's timezone
    #- PLEX_CLAIM=${CLAIM_KEY}
    - ADVERTISE_IP="${ADV_IP}"
  hostname: ${HOSTNAME}
  volumes:
    - ${CONFIG}/plex:/config
    #- ${DATA}/media:/media
    - ${DATA}:/data
  restart: unless-stopped

Emby

Another web server for streaming media which was previously open source but no longer so. Its mostly free but some features like download in android is paid.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
emby:
  image: emby/embyserver
  hostname: ${HOSTNAME}
  # runtime: nvidia # Expose NVIDIA GPUs
  # network_mode: host # Enable DLNA and Wake-on-Lan
  environment:
    - UID=${PUID} # The UID to run emby as (default: 2)
    - GID=${PGID} # The GID to run emby as (default 2)
  volumes:
    - ${CONFIG}/emby:/config # Configuration directory
    # - ${DATA}/media:/media
    - ${DATA}:/data
  ports:
    - ${PORT_EMBY}:8096 # HTTP port
  # devices:
  #   - /dev/dri:/dev/dri # VAAPI/NVDEC/NVENC render nodes
  restart: always

Jellyfin

Its another one of the web server just the difference being this one is a open source one ironically build over the last open source version of emby but is still maintained by its own community.

1
2
3
4
5
6
7
8
9
10
11
jellyfin:
  image: jellyfin/jellyfin
  user: ${UID}:${GID}
  volumes:
    - ${CONFIG}/jellyfin:/config
    - ${DATA}:/data
  ports:
    - ${PORT_JELLYFIN}:8096
  environment:
    - TZ=${TIMEZONE:?err}
  restart: unless-stopped

Other usefull services

Bazarr

This is a service that monitors the movies and tv shows for their subtitles. If it dosnt have a subtitle it just fetches it from the source you set like open-subtitles, etc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bazarr:
  image: ghcr.io/hotio/bazarr:latest
  restart: unless-stopped
  logging:
    driver: json-file
  ports:
    - "${PORT_BAZARR}:6767"
  environment:
    - PUID=1000
    - PGID=1000
    - TZ=${TIMEZONE:?err}
  volumes:
    - ${CONFIG}/bazarr:/config
    - ${DATA}:/data

Unpackerr

It helps to reformat, unzip and other file tasks on files which is not directly usable or not in the usable structure.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
unpackerr:
  image: golift/unpackerr
  volumes:
    - ${DATA}/torrents:/downloads
    - ${CONFIG}/unpackerr:/config
  environment:
    - TZ=${TIMEZONE:?err}
    - UN_FOLDER_0_PATH=/downloads
    - UN_LOG_FILE=/config/unpackerr.log
    - UN_SONARR_0_URL=http://sonarr:8989
    - UN_SONARR_0_API_KEY=${API_SONARR}
    - UN_RADARR_0_URL=http://radarr:7878
    - UN_RADARR_0_API_KEY=${API_RADARR}
  restart: unless-stopped

Watchstate

It help sync watch state between plex, emby and jellyfin so if you are watching a show or movie in one of the platform and switch to another one you watch state will be updated there too.

1
2
3
4
5
6
7
8
watchstate:
  image: ghcr.io/arabcoders/watchstate:latest
  user: ${UID}:${GID}
  ports:
    - "${PORT_WATCHSTATE}:8080" # The port which will serve WebUI + API + Webhooks
  volumes:
    - ${CONFIG}/watchstate:/config # mount current directory to container /config directory.
  restart: unless-stopped

Overseerr

Its a server where you can add movies which you need to be added in your service. You can even share access to others and aprove their request.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
overseerr:
  image: "sctx/overseerr:latest"
  environment:
    - PGID=${GID}
    - PUID=${UID}
    - LOG_LEVEL=debug
    - TZ=${TIMEZONE:?err}
  ports:
    - "${PORT_OVERSEERR}:5055"
  volumes:
    - ${DATA}/overseerr:/app/config
    - ${MEDIA}/tv:/mnt/tv
    - ${MEDIA}/movies:/mnt/movies
    - ${MEDIA}/downloads:/downloads
  restart: unless-stopped

VPN

Gluetun

This is a VPN client that connects to your preferred VPN provider. Go to Gluetuns guide for configuring it.

Combined Docker Compose

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
services:
  emby:
    image: emby/embyserver
    hostname: ${HOSTNAME}
    # runtime: nvidia # Expose NVIDIA GPUs
    # network_mode: host # Enable DLNA and Wake-on-Lan
    environment:
      - UID=${PUID} # The UID to run emby as (default: 2)
      - GID=${PGID} # The GID to run emby as (default 2)
    volumes:
      - ${CONFIG}/emby:/config # Configuration directory
      # - ${DATA}/media:/media
      - ${DATA}:/data
    ports:
      - ${PORT_EMBY}:8096 # HTTP port
    # devices:
    #   - /dev/dri:/dev/dri # VAAPI/NVDEC/NVENC render nodes
    restart: always

  qbittorrent:
    image: linuxserver/qbittorrent
    user: ${UID}:${GID}
    restart: unless-stopped
    volumes:
      - ${CONFIG}/qbittorrent:/config
      - ${DATA}:/data
    environment:
      - PUID=${PUID}
      - PGID=${GUID}
      - TZ=${TIMEZONE:?err}
      - WEBUI_PORT=${PORT_QBIT}
    ports:
      - "${PORT_QBIT}:${PORT_QBIT}"
      - 6881:6881 # BitTorrent
      - 6881:6881/udp

  radarr:
    image: linuxserver/radarr
    user: ${UID}:${GID}
    restart: always
    ports:
      - "${PORT_RADARR}:7878"
    environment:
      - PGID=${GID}
      - PUID=${UID}
      - TZ=${TIMEZONE:?err}
    volumes:
      - ${CONFIG}/radarr:/config
      - ${DATA}:/data

  sonarr:
    image: linuxserver/sonarr
    user: ${UID}:${GID}
    restart: always
    ports:
      - "${PORT_SONARR}:8989"
    environment:
      - PGID=${GID}
      - PUID=${UID}
      - TZ=${TIMEZONE:?err}
    volumes:
      - ${CONFIG}/sonarr:/config
      - ${DATA}:/data

  bazarr:
    image: ghcr.io/hotio/bazarr:latest
    restart: unless-stopped
    logging:
      driver: json-file
    ports:
      - "${PORT_BAZARR}:6767"
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=${TIMEZONE:?err}
    volumes:
      - ${CONFIG}/bazarr:/config
      - ${DATA}:/data

  prowlarr:
    image: linuxserver/prowlarr
    user: ${UID}:${GID}
    restart: always
    ports:
      - "${PORT_PROWLARR}:9696"
    cap_add:
      - NET_ADMIN
    environment:
      - PGID=${GID}
      - PUID=${UID}
      - TZ=${TIMEZONE:?err}
    volumes:
      - ${CONFIG}/prowlarr:/config
      - ${DATA}:/data

  flaresolverr:
    image: ghcr.io/flaresolverr/flaresolverr:latest
    user: ${UID}:${GID}
    restart: unless-stopped
    ports:
      - "${PORT_FLARESOL}:8191"
    environment:
      - PGID=${GID}
      - PUID=${UID}
      - LOG_LEVEL=debug
      - LOG_HTML=true
      # Enables hcaptcha-solver => https://github.com/JimmyLaurent/hcaptcha-solver
      - CAPTCHA_SOLVER=hcaptcha-solver
      # Enables CaptchaHarvester => https://github.com/NoahCardoza/CaptchaHarvester
      # - CAPTCHA_SOLVER=harvester
      # - HARVESTER_ENDPOINT=https://127.0.0.1:5000/token
      - TZ=${TIMEZONE:?err}

  jackett:
    image: lscr.io/linuxserver/jackett:latest
    user: ${UID}:${GID}
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=${TIMEZONE:?err}
      #- AUTO_UPDATE=true #optional
      #- RUN_OPTS= #optional
    volumes:
      - ${CONFIG}/jackett:/config
      - ${DATA}:/data
    ports:
      - ${PORT_JACKETT}:9117
    restart: unless-stopped

  overseerr:
    image: "sctx/overseerr:latest"
    environment:
      - PGID=${GID}
      - PUID=${UID}
      - LOG_LEVEL=debug
      - TZ=${TIMEZONE:?err}
    ports:
      - "${PORT_OVERSEERR}:5055"
    volumes:
      - ${DATA}/overseerr:/app/config
      - ${MEDIA}/tv:/mnt/tv
      - ${MEDIA}/movies:/mnt/movies
      - ${MEDIA}/downloads:/downloads
    restart: unless-stopped

  plex:
    image: plexinc/pms-docker:latest # Set specific: plexinc/pms-docker:1.40.2.8395-c67dce28e
    ports:
      - ${PORT_PLEX}:32400/tcp
      - 8324:8324/tcp
      - 32469:32469/tcp
      - 1900:1900/udp
      - 32410:32410/udp
      - 32412:32412/udp
      - 32413:32413/udp
      - 32414:32414/udp
    environment:
      - PUID=${PUID}
      - PGID=${GUID}
      - TZ=${TIMEZONE:?err} # Change this to match your server's timezone
      #- PLEX_CLAIM=${CLAIM_KEY}
      - ADVERTISE_IP="${ADV_IP}"
    hostname: ${HOSTNAME}
    volumes:
      - ${CONFIG}/plex:/config
      #- ${DATA}/media:/media
      - ${DATA}:/data
    restart: unless-stopped

  jellyfin:
    image: jellyfin/jellyfin
    user: ${UID}:${GID}
    volumes:
      - ${CONFIG}/jellyfin:/config
      - ${DATA}:/data
    ports:
      - ${PORT_JELLYFIN}:8096
    environment:
      - TZ=${TIMEZONE:?err}
    restart: unless-stopped

  unpackerr:
    image: golift/unpackerr
    volumes:
      - ${DATA}/torrents:/downloads
      - ${CONFIG}/unpackerr:/config
    environment:
      - TZ=${TIMEZONE:?err}
      - UN_FOLDER_0_PATH=/downloads
      - UN_LOG_FILE=/config/unpackerr.log
      - UN_SONARR_0_URL=http://sonarr:8989
      - UN_SONARR_0_API_KEY=${API_SONARR}
      - UN_RADARR_0_URL=http://radarr:7878
      - UN_RADARR_0_API_KEY=${API_RADARR}
    restart: unless-stopped

  watchstate:
    image: ghcr.io/arabcoders/watchstate:latest
    user: ${UID}:${GID}
    ports:
      - "${PORT_WATCHSTATE}:8080" # The port which will serve WebUI + API + Webhooks
    volumes:
      - ${CONFIG}/watchstate:/config # mount current directory to container /config directory.
    restart: unless-stopped

A sample .env file for the given compose

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# basic system details
TIMEZONE=Asia/Kolkata
HOSTNAME=

# if you want to run application with specific user access
UID=1000
GID=1000

# path to storage
DATA=/path/to/media
MEDIA=/path/to/config

# all ports that you can expose
PORT_EMBY=
PORT_PLEX=
PORT_FLARESOL=
PORT_PROWLARR=
PORT_RADARR=
PORT_SONARR=
PORT_FLOOD=
PORT_QBIT=
PORT_OVERSEERR=

# API keys (you can keep this empty for the first run)
API_RADARR=
API_SONARR=

How to run

1
docker compose up -d

Post installation

  1. Login to all the services via the web port and setup.
  2. Get the API key for radarr and sonarr from settings.
  3. All that to the .env and restart the docker compose.

Sources

  1. trash-guides
  2. WikiArr
This post is licensed under CC BY 4.0 by the author.