Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 25 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,40 @@
# Media Server

A media server configuration to run Plex, Sonarr, Radarr, and Transmission in Docker and behind Traefik.

A media server configuration to run Jellyfin, Sonarr, Radarr, and qbittorrent in Docker and behind Traefik.

## First run

- install [Docker](https://www.docker.com/)
- install [Docker Compose](https://docs.docker.com/compose/)
- create a [Plex accout](https://www.plex.tv/)
- clone this repository
- create a `web` docker network with `docker network create web`
- clone and setup [the reverse proxy](https://github.com/hkaj/reverse_proxy)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need to rely on this program made by a black hat?

- create a user for your media server, export its `$USER_ID` and `$GROUP_ID`.
- set your TZ as an env var, using this [list](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List), e.g. "Europe/Paris"
- create a folder named `media` in this folder (`dockyard`) owned by $USER_ID:$GROUP_ID from your `media` user.
- get your Plex claim token at https://www.plex.tv/claim/
- create a `web` docker network with `docker network create web`
- run `DOMAIN_NAME="..." PLEX_TOKEN="..." USER_ID="$USER_ID" GROUP_ID="$GROUP_ID" docker-compose up -d`
- if you want to setup a VPN or SOCKS5 proxy to secure qbittorrent traffic, do that and uncomment the corresponding env var in the qbittorrent service
- run `DOMAIN_NAME="..." USER_ID="$USER_ID" GROUP_ID="$GROUP_ID" TZ="$TZ" docker compose up -d`
- profit :)

## Config


### Transmission

We use [Transmission](https://transmissionbt.com/) as the downloader.

- stop transmission's container
- configure basic auth at `media/transmission/config/settings.json` (you will need to touch `rpc-authentication-required`, `rpc-username` and `rpc-password`)
- start transmission's container


### Sonarr

We use [Sonarr](https://sonarr.tv/) to track and manage TV shows.

- setup auto-update and authentication
- connect transmission as a downloader


### Radarr

We use [Radarr](https://radarr.video/) (a clone of Sonarr) to track and manage movies.

- setup auto-update and authentication
- connect transmission as a downloader


### Jackett

We use [Jackett](https://github.com/Jackett/Jackett) as a proxy between private trackers and our other components.
The expected folder structure is:

```
media/
library/ # where jellyfin will look, and where sonarr/radarr will hardlink to
movies/
tv/
torrents/ # where qbittorrent will download content and where sonarr/radarr will hardlink from
movies/
tv/
```

* Configure qbittorrent to download torrents
* To connect to it, check its container logs. It generates a random password upon each start.
* Create a movies and a tv categories in qbittorent
* Configure a download client in sonarr and radarr to use qbittorrent, pass them the above mentioned categories
* Configure indexers in prowlarr
* Configure prowlarr to connect to sonarr and radarr
* Configure Sonarr and Radarr to use hardlinking and avoid copying files in `Settings => Media Management => Importing`
* In Jellyfin, add the opensubtitles plugin
189 changes: 88 additions & 101 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,155 +1,142 @@
version: '2.1'

services:
plex:
image: plexinc/pms-docker:latest
container_name: plex
networks:
- web
environment:
- PLEX_CLAIM="${PLEX_TOKEN}"
- ADVERTISE_IP="https://plex.${DOMAIN_NAME}/"
- PLEX_UID=${USER_ID}
- PLEX_GID=${GROUP_ID}
volumes:
- /etc/localtime:/etc/localtime:ro
- ./media/radarr/movies:/data/movies
- ./media/sonarr/series:/data/tvshows
- ./media/plex/config/:/config
- /tmp/transcode/:/transcode
labels:
- "traefik.enable=true"
- "traefik.backend=plex"
- "traefik.docker.network=web"
- "traefik.frontend.rule=Host:plex.${DOMAIN_NAME}"
- "traefik.port=32400"
depends_on:
- transmission
- sonarr
- radarr

plexpy:
image: linuxserver/plexpy:latest
container_name: plexpy
jellyfin:
image: lscr.io/linuxserver/jellyfin:latest
container_name: jellyfin
networks:
- web
environment:
- PUID=${USER_ID}
- PGID=${GROUP_ID}
- TZ=${TZ}
- JELLYFIN_PublishedServerUrl=https://jellyfin.${DOMAIN_NAME}/
devices:
- /dev/dri:/dev/dri #Required for jellyfin HW transcoding / QuickSync (Intel 8th gen or newer)
volumes:
- ./media/plexpy:/config
- ./media/plex/config/Library/Application\ Support/Plex\ Media\ Server/Logs:/logs:ro
- ./media/library:/library
- ./media/jellyfin/config/:/config
# ports:
# - 8096:8096
labels:
- "traefik.enable=true"
- "traefik.backend=plexpy"
- "traefik.frontend.rule=Host:plexpy.${DOMAIN_NAME}"
- "traefik.port=8181"
- "traefik.docker.network=web"
- "traefik.http.routers.jellyfin.rule=Host(`jellyfin.${DOMAIN_NAME}`)"
- "traefik.http.routers.jellyfin.entrypoints=websecure"
- "traefik.http.routers.jellyfin.tls.certresolver=myresolver"
- "traefik.http.services.jellyfin.loadbalancer.server.port=8096"
depends_on:
- plex

transmission:
image: linuxserver/transmission:latest
container_name: transmission
networks:
- web
environment:
- PUID=${USER_ID}
- PGID=${GROUP_ID}
volumes:
- /etc/localtime:/etc/localtime:ro
- ./media/transmission/config/:/config
- ./media/transmission/downloads/:/downloads
labels:
- "traefik.enable=true"
- "traefik.backend=transmission"
- "traefik.frontend.rule=Host:transmission.${DOMAIN_NAME}"
- "traefik.port=9091"
- "traefik.docker.network=web"
- qbittorrent
- sonarr
- radarr
restart: unless-stopped

sonarr:
image: linuxserver/sonarr:latest
image: lscr.io/linuxserver/sonarr:latest
container_name: sonarr
networks:
- web
volumes:
- /etc/localtime:/etc/localtime:ro
- /dev/rtc:/dev/rtc:ro
- ./media/sonarr/series:/tv
- ./media/sonarr/config:/config
- ./media/transmission/downloads/:/downloads
- ./media/:/media
environment:
- PUID=${USER_ID}
- PGID=${GROUP_ID}
- TZ=${TZ}
labels:
- "traefik.enable=true"
- "traefik.backend=sonarr"
- "traefik.frontend.rule=Host:sonarr.${DOMAIN_NAME}"
- "traefik.port=8989"
- "traefik.docker.network=web"
- "traefik.http.routers.sonarr.rule=Host(`sonarr.${DOMAIN_NAME}`)"
- "traefik.http.routers.sonarr.entrypoints=websecure"
- "traefik.http.routers.sonarr.tls.certresolver=myresolver"
depends_on:
- transmission
- qbittorrent
restart: unless-stopped

radarr:
image: linuxserver/radarr:latest
image: lscr.io/linuxserver/radarr:latest
container_name: radarr
networks:
- web
volumes:
- /etc/localtime:/etc/localtime:ro
- /dev/rtc:/dev/rtc:ro
- ./media/radarr/movies:/movies
- ./media/radarr/config:/config
- ./media/transmission/downloads/:/downloads
- ./media/:/media
environment:
- PUID=${USER_ID}
- PGID=${GROUP_ID}
- TZ=${TZ}
labels:
- "traefik.enable=true"
- "traefik.backend=radarr"
- "traefik.frontend.rule=Host:radarr.${DOMAIN_NAME}"
- "traefik.port=7878"
- "traefik.docker.network=web"
- "traefik.http.routers.radarr.rule=Host(`radarr.${DOMAIN_NAME}`)"
- "traefik.http.routers.radarr.entrypoints=websecure"
- "traefik.http.routers.radarr.tls.certresolver=myresolver"
depends_on:
- transmission
- qbittorrent
restart: unless-stopped

# Proxy to a bunch of public trackers
jackett:
image: linuxserver/jackett:latest
container_name: jackett
networks:
- web
volumes:
- ./media/jackett/config/:/config
- ./media/transmission/downloads/:/downloads
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:latest
container_name: qbittorrent
environment:
- PUID=${USER_ID}
- PGID=${GROUP_ID}
- TZ=${TZ}
- WEBUI_PORT=8080
- TORRENTING_PORT=8694 # port forward in router config
# - "ALL_PROXY=172.17.0.1:1080" # enable to proxy traffic through a SOCKS5 proxy
volumes:
- ./media/qbittorrent/config:/config
- ./media/torrents:/media/torrents
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.backend=jackett"
- "traefik.frontend.rule=Host:jackett.${DOMAIN_NAME}"
- "traefik.port=9117"
- "traefik.docker.network=web"
- "traefik.http.routers.qbittorrent.rule=Host(`qbittorrent.${DOMAIN_NAME}`)"
- "traefik.http.routers.qbittorrent.entrypoints=websecure"
- "traefik.http.routers.qbittorrent.tls.certresolver=myresolver"
- "traefik.http.services.qbittorrent.loadbalancer.server.port=8080"
restart: unless-stopped

ombi:
image: linuxserver/ombi
container_name: ombi
restart: always
networks:
- web
# Prowlarr - manages your Sonarr, Radarr and download client
prowlarr:
image: lscr.io/linuxserver/prowlarr:latest
container_name: prowlarr
environment:
- PUID=${USER_ID}
- PGID=${GROUP_ID}
- TZ=${TZ}
volumes:
- /etc/localtime:/etc/localtime:ro
- ./media/ombi/config:/config
- ./media/prowlarr/config:/config
- ./media/:/media
networks:
- web
# ports:
# - 9696:9696
labels:
- "traefik.enable=true"
- "traefik.http.routers.prowlarr.rule=Host(`prowlarr.${DOMAIN_NAME}`)"
- "traefik.http.routers.prowlarr.entrypoints=websecure"
- "traefik.http.routers.prowlarr.tls.certresolver=myresolver"
restart: unless-stopped

# Flaresolerr - Used as a proxy server to bypass Cloudflare and DDoS-GUARD protection.
flaresolverr:
# DockerHub mirror flaresolverr/flaresolverr:latest
image: ghcr.io/flaresolverr/flaresolverr:latest
container_name: flaresolverr
environment:
- LOG_LEVEL=info
- LOG_HTML=false
- CAPTCHA_SOLVER=none
- TZ=${TZ}
# ports:
# - 8191:8191
networks:
- web
labels:
- "traefik.enable=true"
- "traefik.backend=ombi"
- "traefik.frontend.rule=Host:ombi.${DOMAIN_NAME}"
- "traefik.port=3579"
- "traefik.docker.network=web"
- "traefik.http.routers.flaresolverr.rule=Host(`flaresolverr.${DOMAIN_NAME}`)"
- "traefik.http.routers.flaresolverr.entrypoints=websecure"
- "traefik.http.routers.flaresolverr.tls.certresolver=myresolver"
restart: unless-stopped

networks:
web:
Expand Down