├── .gitignore ├── .env_sample ├── docker-compose.yml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | -------------------------------------------------------------------------------- /.env_sample: -------------------------------------------------------------------------------- 1 | # ======== directories ======== 2 | CONFIG_DIR=/some/directory/media_server/config 3 | DOWNLOAD_DIR=/some/directory/media_server/downloads 4 | MEDIA_DIR=/some/directory/media_server/media 5 | TV_DIR=/some/directory/media_server/media/TV Shows 6 | MOVIES_DIR=/some/directory/media_server/media/Movies 7 | ### base dir should be a directory that contains both downloads and media to take advantage of hardlinks 8 | BASE_DIR=/some/directory/media_server 9 | 10 | # ======== user ======== 11 | PUID=1000 12 | PGID=1000 13 | TIMEZONE=America/Los_Angeles 14 | 15 | # ======== transmission ======== 16 | TRANS_WEBUI_USER=user 17 | TRANS_WEBUI_PASS=[REPLACEME] 18 | TRANS_WEBUI_PORT=5656 19 | TRANS_CONNECTION_PORT=51413 20 | ### retain torrents for up to this many seconds 21 | TRANS_MAX_RETENTION=2592000 22 | ### retain torrents until they reach this ratio 23 | TRANS_MAX_RATIO=10 24 | 25 | # ======== filebot ======== 26 | FILEBOT_PORT=7676 27 | ### results in file names like "The Expanse - S02E07 - The Seventh Man - HD.mkv" 28 | FILEBOT_FORMAT={plex} - {hd} 29 | ### prefer titles from the last 30 days but fall back to any title if there are none recent enough 30 | FILEBOT_FILTER=any{ age < 30 }{ true } || !model.any{ it.age < 30 && it.age != null } 31 | ### duplicate will fall back to copy if hardlink fails. set to "hardlink" to confirm if hardlinks are working 32 | FILEBOT_ACTION=duplicate 33 | ### filebot will intelligently decide whether or not to replace an existing copy 34 | FILEBOT_CONFLICT=auto 35 | ### defaults to TheTVDB but TheTVDB has been having issues for most of 2020 36 | FILEBOT_SERIES_DB=TheMovieDB::TV 37 | FILEBOT_ANIME_DB=AniDB 38 | FILEBOT_MOVIE_DB=TheMovieDB 39 | FILEBOT_MUSIC_DB=ID3 40 | ### not currently functional 41 | OPEN_SUB_USER=[REPLACEME] 42 | ### not currently functional 43 | OPEN_SUB_PASS=[REPLACEME] 44 | 45 | # ======== nzbget ======== 46 | NZBGET_PORT=7890 47 | NZBGET_WEB_USER= 48 | NZBGET_WEB_PASS= 49 | ### don't change these unless you really know what you're doing 50 | NZBGET_MAIN_DIR=/downloads/nzb 51 | NZBGET_SCRIPT_DIR=/usr/local/bin 52 | 53 | # ======== sonarr ======== 54 | SONARR_PORT=8989 55 | 56 | # ======== radarr ======== 57 | RADARR_PORT=7878 58 | 59 | # ======== bazaar ======== 60 | BAZARR_PORT=6767 61 | 62 | # ======== jackett ======== 63 | JACKETT_PORT=9117 64 | 65 | # ======== plex ======== 66 | ### install trakt and subzero but you might need Kitana to see the UI 67 | PLUGIN_LIST=trakt subzero 68 | PLEX_WEB_PORT=32400 69 | 70 | # ======== tautulli ======== 71 | TAUTULLI_PORT=8181 72 | 73 | # ======== heimdall ======== 74 | HEIMDALL_PORT=8888 75 | HEIMDALL_SSL_PORT=4444 76 | 77 | # ======== wireguard ======== 78 | ### the local network of your host machine to allow access to the service from the local network. required for VPN port forwarding. 79 | LOCAL_NETWORK=192.168.0.0/24 80 | 81 | # ======== letsencrypt ======== 82 | ### a domain like "somedomain.com" 83 | LE_HOSTNAME=[REPLACEME] 84 | ### an email at your above domain like "me@somedomain.com" 85 | LE_EMAIL=[REPLACEME] 86 | ### a comma separated list of subdomains to set up letsencrypt certs for 87 | LE_SUBDOMAINS=r,s,t,n,p,m,u,h,b 88 | NGINX_USER=user 89 | ### not currently functional 90 | NGINX_PASS=[REPLACEME] 91 | 92 | # ======== netdata ======== 93 | NETDATA_PORT=19999 94 | 95 | # ======== portainer ======== 96 | PORTAINER_PORT=9000 97 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | # _ _ 2 | # __ _| |__ ___ ___| |_ 3 | # / _` | '_ \ / _ \/ __| __/ 4 | # | (_| | | | | (_) \__ \ |_ 5 | # \__, |_| |_|\___/|___/\__| 6 | # |___/ / _ \ 7 | # (¯\| o (@) |/¯) 8 | # \_ .___. _/ 9 | # / !_! \ 10 | # /_.--._.--._\ 11 | 12 | version: "3" 13 | 14 | services: 15 | # wireguard: 16 | # image: ghostserverd/wireguard 17 | # container_name: wireguard 18 | # restart: always 19 | # privileged: true 20 | # sysctls: 21 | # - "net.ipv6.conf.all.disable_ipv6=0" 22 | # - "net.ipv6.conf.default.forwarding=1" 23 | # - "net.ipv6.conf.all.forwarding=1" 24 | # - "net.ipv4.ip_forward=1" 25 | # cap_add: 26 | # - NET_ADMIN 27 | # - SYS_MODULE 28 | # networks: 29 | # default: 30 | # aliases: 31 | # - nzbget 32 | # - transmission 33 | # ports: 34 | # - "${NZBGET_PORT}:6789" 35 | # - "${TRANS_WEBUI_PORT}:${TRANS_WEBUI_PORT}" 36 | # # TRANS_CONNECTION_PORT may need to be port forwarded by your VPN 37 | # - "${TRANS_CONNECTION_PORT}:${TRANS_CONNECTION_PORT}" 38 | # - "${TRANS_CONNECTION_PORT}:${TRANS_CONNECTION_PORT}/udp" 39 | # environment: 40 | # - LOCAL_NETWORK=${LOCAL_NETWORK} 41 | # # NETWORK_NAME is not needed unless you are mounting docker.sock to write /etc/hosts 42 | # # - NETWORK_NAME=${NETWORK_NAME} 43 | # # this is required unless you are mounting docker.sock to write /etc/hosts 44 | # - IPTABLES_MASQ=0 45 | # # space separated list of docker service names to make addressable 46 | # - SERVICE_NAMES=filebot sonarr radarr bazarr jackett heimdall tautulli plex 47 | # # local TLD to use when routing DNS requests which requires aliases for each service to be addressable from within the wireguard network 48 | # # - LOCAL_TLD=ghost 49 | # volumes: 50 | # - ${CONFIG_DIR}/wireguard:/etc/wireguard 51 | # - /lib/modules:/lib/modules 52 | # # this is no longer necessary but if enabled, will cause the /etc/hosts file to be written with all available services 53 | # # - /var/run/docker.sock:/var/run/docker.sock:ro 54 | 55 | transmission: 56 | image: ghostserverd/transmission-combustion 57 | container_name: transmission 58 | restart: always 59 | ports: 60 | - "${TRANS_WEBUI_PORT}:5656" 61 | - "${TRANS_CONNECTION_PORT}:51413" 62 | - "${TRANS_CONNECTION_PORT}:51413/udp" 63 | environment: 64 | - PUID=${PUID} 65 | - PGID=${PGID} 66 | - TZ=${TIMEZONE} 67 | - TRANS_WEBUI_USER=${TRANS_WEBUI_USER} 68 | - TRANS_WEBUI_PASS=${TRANS_WEBUI_PASS} 69 | - TRANS_WEBUI_PORT=${TRANS_WEBUI_PORT} 70 | - TRANS_MAX_RETENTION=${TRANS_MAX_RETENTION} 71 | - TRANS_MAX_RATIO=${TRANS_MAX_RATIO} 72 | - TRANS_CONNECTION_PORT=${TRANS_CONNECTION_PORT} 73 | - FILEBOT_PORT=${FILEBOT_PORT} 74 | - SONARR_API_KEY=${SONARR_API_KEY} 75 | - SONARR_PORT=${SONARR_PORT} 76 | - RADARR_API_KEY=${RADARR_API_KEY} 77 | - RADARR_PORT=${RADARR_PORT} 78 | volumes: 79 | - ${CONFIG_DIR}/transmission:/config 80 | - ${DOWNLOAD_DIR}:/downloads 81 | - ${MEDIA_DIR}:/media 82 | 83 | filebot: 84 | image: ghostserverd/filebot:4.9.x 85 | container_name: filebot 86 | restart: always 87 | ports: 88 | - "${FILEBOT_PORT}:${FILEBOT_PORT}" 89 | environment: 90 | - PUID=${PUID} 91 | - PGID=${PGID} 92 | - TZ=${TIMEZONE} 93 | - FILEBOT_PORT=${FILEBOT_PORT} 94 | - FILEBOT_FORMAT=${FILEBOT_FORMAT} 95 | - FILEBOT_FILTER=${FILEBOT_FILTER} 96 | - FILEBOT_ACTION=${FILEBOT_ACTION} 97 | - FILEBOT_CONFLICT=${FILEBOT_CONFLICT} 98 | - FILEBOT_SERIES_DB=${FILEBOT_SERIES_DB} 99 | - FILEBOT_ANIME_DB=${FILEBOT_ANIME_DB} 100 | - FILEBOT_MOVIE_DB=${FILEBOT_MOVIE_DB} 101 | - FILEBOT_MUSIC_DB=${FILEBOT_MUSIC_DB} 102 | - OPEN_SUB_USER=${OPEN_SUB_USER} 103 | - OPEN_SUB_PASS=${OPEN_SUB_PASS} 104 | volumes: 105 | - ${CONFIG_DIR}/filebot:/config 106 | - ${DOWNLOAD_DIR}:/downloads 107 | - ${MEDIA_DIR}:/media 108 | - ${BASE_DIR}:/share 109 | 110 | ### this is how to define the nzbget service to send all traffic through the wireguard container 111 | ### the difference is adding network_mode and removing any port mappings 112 | # nzbget: 113 | # image: ghostserverd/nzbget 114 | # container_name: nzbget 115 | # restart: always 116 | # network_mode: "service:wireguard" 117 | # depends_on: 118 | # - wireguard 119 | # environment: 120 | # - PUID=${PUID} 121 | # - PGID=${PGID} 122 | # - TZ=${TIMEZONE} 123 | # - NZBGET_WEB_USER=${NZBGET_WEB_USER} 124 | # - NZBGET_WEB_PASS=${NZBGET_WEB_PASS} 125 | # - NZBGET_MAIN_DIR=${NZBGET_MAIN_DIR} 126 | # - NZBGET_SCRIPT_DIR=${NZBGET_SCRIPT_DIR} 127 | # - FILEBOT_PORT=${FILEBOT_PORT} 128 | # volumes: 129 | # - ${CONFIG_DIR}/nzbget:/config 130 | # - ${DOWNLOAD_DIR}/nzb:/downloads/nzb 131 | 132 | nzbget: 133 | image: ghostserverd/nzbget 134 | container_name: nzbget 135 | restart: always 136 | ports: 137 | - "${NZBGET_PORT}:6789" 138 | environment: 139 | - PUID=${PUID} 140 | - PGID=${PGID} 141 | - TZ=${TIMEZONE} 142 | - NZBGET_WEB_USER=${NZBGET_WEB_USER} 143 | - NZBGET_WEB_PASS=${NZBGET_WEB_PASS} 144 | - NZBGET_MAIN_DIR=${NZBGET_MAIN_DIR} 145 | - NZBGET_SCRIPT_DIR=${NZBGET_SCRIPT_DIR} 146 | - FILEBOT_PORT=${FILEBOT_PORT} 147 | - SONARR_API_KEY=${SONARR_API_KEY} 148 | - SONARR_PORT=${SONARR_PORT} 149 | - RADARR_API_KEY=${RADARR_API_KEY} 150 | - RADARR_PORT=${RADARR_PORT} 151 | volumes: 152 | - ${CONFIG_DIR}/nzbget:/config 153 | - ${DOWNLOAD_DIR}/nzb:/downloads/nzb 154 | 155 | sonarr: 156 | image: ghostserverd/sonarr 157 | container_name: sonarr 158 | restart: always 159 | ports: 160 | - "${SONARR_PORT}:8989" 161 | environment: 162 | - PUID=${PUID} 163 | - PGID=${PGID} 164 | - TZ=${TIMEZONE} 165 | volumes: 166 | - ${CONFIG_DIR}/sonarr:/config 167 | - ${DOWNLOAD_DIR}:/data/completed/tv/ 168 | - ${TV_DIR}:/tv 169 | 170 | radarr: 171 | image: ghostserverd/radarr 172 | container_name: radarr 173 | restart: always 174 | ports: 175 | - "${RADARR_PORT}:7878" 176 | environment: 177 | - PUID=${PUID} 178 | - PGID=${PGID} 179 | - TZ=${TIMEZONE} 180 | volumes: 181 | - ${CONFIG_DIR}/radarr:/config 182 | - ${DOWNLOAD_DIR}:/data/completed/movies/ 183 | - ${MOVIES_DIR}:/movies 184 | 185 | bazarr: 186 | image: ghostserverd/bazarr 187 | container_name: bazarr 188 | restart: always 189 | ports: 190 | - "${BAZARR_PORT}:6767" 191 | environment: 192 | - PUID=${PUID} 193 | - PGID=${PGID} 194 | - TZ=${TIMEZONE} 195 | volumes: 196 | - ${CONFIG_DIR}/bazarr:/config 197 | - ${TV_DIR}:/tv 198 | - ${MOVIES_DIR}:/movies 199 | 200 | jackett: 201 | image: ghostserverd/jackett 202 | container_name: jackett 203 | restart: always 204 | ports: 205 | - "${JACKETT_PORT}:9117" 206 | environment: 207 | - PUID=${PUID} 208 | - PGID=${PGID} 209 | - TZ=${TIMEZONE} 210 | - JACKETT_KEY=0000 211 | volumes: 212 | - ${CONFIG_DIR}/jackett:/config 213 | - ${CONFIG_DIR}/jackett/downloads:/downloads 214 | 215 | plex: 216 | image: ghostserverd/plex 217 | container_name: plex 218 | restart: always 219 | ports: 220 | - "${PLEX_WEB_PORT}:32400" 221 | - "1900:1900" 222 | - "3005:3005" 223 | - "5353:5353" 224 | - "8324:8324" 225 | - "32410:32410" 226 | - "32412:32412" 227 | - "32413:32413" 228 | - "32414:32414" 229 | - "32469:32469" 230 | environment: 231 | - PUID=${PUID} 232 | - PGID=${PGID} 233 | - TZ=${TIMEZONE} 234 | - VERSION=latest 235 | - PLUGIN_LIST=${PLUGIN_LIST} 236 | volumes: 237 | - ${CONFIG_DIR}/plex:/config 238 | - ${MEDIA_DIR}:/data 239 | devices: 240 | - "/dev/dri/card0:/dev/dri/card0" 241 | - "/dev/dri/renderD128:/dev/dri/renderD128" 242 | 243 | tautulli: 244 | image: ghostserverd/tautulli 245 | container_name: tautulli 246 | restart: always 247 | ports: 248 | - "${TAUTULLI_PORT}:8181" 249 | environment: 250 | - PUID=${PUID} 251 | - PGID=${PGID} 252 | - TZ=${TIMEZONE} 253 | volumes: 254 | - ${CONFIG_DIR}/tautulli:/config 255 | - "${CONFIG_DIR}/plex/Library/Application Support/Plex Media Server/Logs:/logs:ro" 256 | 257 | heimdall: 258 | image: ghostserverd/heimdall 259 | container_name: heimdall 260 | restart: always 261 | environment: 262 | - PUID=${PUID} 263 | - PGID=${PGID} 264 | - TZ=${TIMEZONE} 265 | ports: 266 | - "${HEIMDALL_PORT}:80" 267 | - "${HEIMDALL_SSL_PORT}:443" 268 | volumes: 269 | - ${CONFIG_DIR}/heimdall:/config 270 | 271 | letsencrypt: 272 | image: ghostserverd/letsencrypt 273 | container_name: letsencrypt 274 | ports: 275 | - "443:443" 276 | - "80:80" 277 | volumes: 278 | - ${CONFIG_DIR}/letsencrypt:/config 279 | restart: always 280 | depends_on: 281 | - sonarr 282 | - radarr 283 | - bazarr 284 | - nzbget 285 | - transmission 286 | - plex 287 | - tautulli 288 | - netdata 289 | - heimdall 290 | environment: 291 | - PUID=${PUID} 292 | - PGID=${PGID} 293 | - TZ=${TIMEZONE} 294 | - EMAIL=${LE_EMAIL} 295 | - URL=${LE_HOSTNAME} 296 | - SUBDOMAINS=${LE_SUBDOMAINS} 297 | - NGINX_USER=${NGINX_USER} 298 | - NGINX_PASS=${NGINX_PASS} 299 | 300 | netdata: 301 | image: netdata/netdata 302 | container_name: netdata 303 | hostname: ${LE_HOSTNAME} 304 | ports: 305 | - "${NETDATA_PORT}:19999" 306 | cap_add: 307 | - SYS_PTRACE 308 | security_opt: 309 | - apparmor:unconfined 310 | environment: 311 | - PUID=${PUID} 312 | - PGID=${PGID} 313 | - TZ=${TIMEZONE} 314 | volumes: 315 | - /proc:/host/proc:ro 316 | - /sys:/host/sys:ro 317 | - /var/run/docker.sock:/var/run/docker.sock:rw 318 | 319 | ddclient: 320 | image: linuxserver/ddclient 321 | container_name: ddclient 322 | environment: 323 | - PUID=${PUID} 324 | - PGID=${PGID} 325 | - TZ=${TIMEZONE} 326 | volumes: 327 | - ${CONFIG_DIR}/ddclient:/config 328 | restart: always 329 | 330 | portainer: 331 | image: portainer/portainer-ce 332 | container_name: portainer 333 | restart: always 334 | ports: 335 | - "${PORTAINER_PORT}:9000" 336 | volumes: 337 | - /var/run/docker.sock:/var/run/docker.sock 338 | - ${CONFIG_DIR}/portainer:/data 339 | 340 | watchtower: 341 | image: containrrr/watchtower 342 | container_name: watchtower 343 | command: --cleanup 344 | restart: always 345 | volumes: 346 | - /var/run/docker.sock:/var/run/docker.sock 347 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Automated Media Server 👻 2 | 3 | - [Automated Media Server 👻](#automated-media-server-) 4 | - [About](#about) 5 | - [⚠️ A Note About Torrent Clients](#️-a-note-about-torrent-clients) 6 | - [Network](#network) 7 | - [Installation](#installation) 8 | - [Install Docker](#install-docker) 9 | - [Install Docker Compose](#install-docker-compose) 10 | - [Clone this repo](#clone-this-repo) 11 | - [Build your `.env` file](#build-your-env-file) 12 | - [Directories](#directories) 13 | - [PUID and PGID](#puid-and-pgid) 14 | - [Deploy the mediaserver](#deploy-the-mediaserver) 15 | - [Configuration](#configuration) 16 | - [Configure Jackett](#configure-jackett) 17 | - [Configure Sonarr](#configure-sonarr) 18 | - [Configure Radarr](#configure-radarr) 19 | - [Configure Bazarr](#configure-bazarr) 20 | - [Configure filebot](#configure-filebot) 21 | - [Configure transmission](#configure-transmission) 22 | - [Configure nzbget](#configure-nzbget) 23 | - [Configure Plex](#configure-plex) 24 | - [Reverse proxy / letsencrypt](#reverse-proxy--letsencrypt) 25 | - [VPN networks for transmission, nzbget, and others](#vpn-networks-for-transmission-nzbget-and-others) 26 | - [Why do you need to mount `docker.sock` for the wireguard container](#why-do-you-need-to-mount-dockersock-for-the-wireguard-container) 27 | - [Update: mounting `docker.sock` is no longer necessary](#update-mounting-dockersock-is-no-longer-necessary) 28 | - [Thank You](#thank-you) 29 | - [Linuxserver](#linuxserver) 30 | - [Filebot](#filebot) 31 | - [ASCII word generation](#ascii-word-generation) 32 | - [combustion UI for transmission](#combustion-ui-for-transmission) 33 | - [Donate](#donate) 34 | - [Future Plans](#future-plans) 35 | 36 | ``` 37 | _ _ 38 | __ _| |__ ___ ___| |_ 39 | / _` | '_ \ / _ \/ __| __/ 40 | | (_| | | | | (_) \__ \ |_ 41 | \__, |_| |_|\___/|___/\__| 42 | |___/ / _ \ 43 | (¯\| o (@) |/¯) 44 | \_ .___. _/ 45 | / !_! \ 46 | /_.--._.--._\ 47 | ``` 48 | 49 | --- 50 | 51 | ## About 52 | 53 | This is an automated media server set up in docker containers via docker-compose. The goal of this project is to automate as much of the installation and configuration as possible while maintaining simplicity of the setup (no ansible playbooks or fancy bash scripts) to avoid making it a complete black box. 54 | 55 | The end result of this setup is a media server with the following components 56 | 57 | - `plex` 58 | - `filebot` 59 | - with a web interface for triggering `amc` script 60 | - `transmission` 61 | - configured to call `filebot` container on torrent completion 62 | - with `combustion` web UI 63 | - `nzbget` 64 | - configured to call `filebot` container on nzb completion 65 | - `sonarr` 66 | - `radarr` 67 | - `jackett` 68 | - `bazarr` 69 | - `tautulli` 70 | - configured to look at plex server logs 71 | - `portainer` 72 | - `watchtower` 73 | - `nginx + letsencrypt` 74 | - for reverse proxying to reach your services at \*.domain.tld 75 | - `heimdall` 76 | 77 | The high-level steps for setup are as follows 78 | 79 | 1. Install docker and docker-compose 80 | 2. `docker-compose up` 81 | 3. add an indexer to `jackett` 82 | 4. configure `sonarr` / `radarr` to use the `jackett` indexer 83 | 5. configure `sonarr` / `radarr` to use an `nzb` indexer 84 | 6. configure `sonarr` / `radarr` to use `transmission` as their download client 85 | 7. configure `sonarr` / `radarr` to use `nzbget` as their nzb client 86 | 8. configure `nzbget` with your newsgroup provider 87 | 9. add libraries to `plex` 88 | 89 | Once these steps have been completed, it is possible to add a TV Show or Movie to `sonarr` / `radarr`, have it automatically download them when available, and then it will be automatically copied into your `plex` libraries. Post-installation, this should be a fully-automated media server. The `transmission` container will automatically clean any files older than 30 days (configurable). 90 | 91 | 📓 This has only been tested on Ubuntu 18.04 LTS but it should work just fine on other linux distros. MacOS and Windows are unsupported. If you test it on MacOS or Windows and it works, let me know! 92 | 93 | ## ⚠️ A Note About Torrent Clients 94 | 95 | I've removed the cofiguration for `qbittorrent`. If you want to keep using it, feel free to search through git history to recover the configuration, but it's no longer supported and has not been updated to use the new `filebot` container. 96 | 97 | ## Network 98 | 99 | Each service is available on its own ports: 100 | 101 | | Service | Port | 102 | | ------------ | ----- | 103 | | transmission | 5656 | 104 | | nzbget | 6789 | 105 | | filebot | 7676 | 106 | | sonarr | 8989 | 107 | | radarr | 7878 | 108 | | bazarr | 6767 | 109 | | jackett | 9117 | 110 | | plex | 32400 | 111 | | portainer | 9000 | 112 | | heimdall | 8888 | 113 | | netdata | 19999 | 114 | 115 | 📓To reach `plex`, append `/web` to the address e.g. `192.168.1.11:32400/web` 116 | 117 | All of the services are running in the default docker-compose network. From within services, they can access each other via their `:` as defined in `docker-compose.yml`. These are _NOT_ the ports you've configured in your `.env` file. Those ports are mapped to the host device's network, but the services are operating within the network that docker-compose sets up, so they will not respect the rules forwarding ports to the host network. 118 | 119 | | Service | Port | 120 | | ------------ | ----- | 121 | | transmission | 5656 | 122 | | nzbget | 6789 | 123 | | filebot | 7676 | 124 | | sonarr | 8989 | 125 | | radarr | 7878 | 126 | | bazarr | 6767 | 127 | | jackett | 9117 | 128 | | plex | 32400 | 129 | | tautulli | 8181 | 130 | | heimdall | 80 | 131 | | netdata | 19999 | 132 | 133 | ## Installation 134 | 135 | ### Install Docker 136 | 137 | - 138 | 139 | ### Install Docker Compose 140 | 141 | - 142 | 143 | ### Clone this repo 144 | 145 | ```sh 146 | git clone https://github.com/ghostserverd/mediaserver-docker.git 147 | cd mediaserver-docker 148 | ``` 149 | 150 | ### Build your `.env` file 151 | 152 | ```sh 153 | cp .env_sample .env 154 | id $USER # save the result of this for building your .env file below 155 | ``` 156 | 157 | Modify the `.env` file to specify the directory configurations. Note that these directories are for the host machine. They are mapped to various locations inside of their container by the `docker-compose` file. 158 | 159 | The `.env_sample` file has some notes about the various configuration options. There are additional descriptions of each service's configuration below. 160 | 161 | #### Directories 162 | 163 | A good directory setup looks something like this 164 | 165 | ```sh 166 | CONFIG_DIR=/some/directory/media_server/config 167 | DOWNLOAD_DIR=/some/directory/media_server/downloads 168 | MEDIA_DIR=/some/directory/media_server/media 169 | TV_DIR=/some/directory/media_server/media/TV Shows 170 | MOVIES_DIR=/some/directory/media_server/media/Movies 171 | BASE_DIR=/some/directory/media_server 172 | ``` 173 | 174 | Note that there is a base volume mount that holds both `media` and `downloads` 175 | 176 | ```sh 177 | /some/directory/media_server 178 | ``` 179 | 180 | Configuring a single mount that contains both `downloads` and `media` allows `filebot` to take advantage of `hardlinks` when renaming and moving files. Hardlinks are much quicker than actually copying the file, but they require that the source and destination be on the same volume in order to work. 181 | 182 | | variable | description | 183 | | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 184 | | CONFIG_DIR | where configuration for each of the services will live. You'll end up with multiple directories in here, one for each service. If you move this directory to a different volume with a different instance of the whole media server, it should retain your various configurations. | 185 | | DOWNLOAD_DIR | where various services will download files to. ⚠️ This should not be on a small partition as it will contain media files. | 186 | | MEDIA_DIR | where your media will be copied to. ⚠️ This should not be on a small partition as it will contain media files. | 187 | | TV_DIR | where your TV shows will be placed by `filebot` on download completion. It should be a subdirectory of `MEDIA_DIR` | 188 | | MOVIES_DIR | where your TV shows will be placed by `filebot` on download completion. It should be a subdirectory of `MEDIA_DIR` | 189 | | BASE_DIR | a shared directory that houses `media` and `downloads` directories to be used for hardlinks | 190 | 191 | #### PUID and PGID 192 | 193 | | variable | description | 194 | | -------- | ------------------------------------------------------------------------------------------------------------------------------ | 195 | | PUID | the unix `UID` that will be passed to the various services. It can be discovered by running `id $USER` on the host machine. | 196 | | PGID | is the unix `GID` that will be passed to the various services. It can be discovered by running `id $USER` on the host machine. | 197 | 198 | ### Deploy the mediaserver 199 | 200 | Fill out the rest of the configuration options before deploying. See each individual service's section for configuration details. 201 | 202 | ```sh 203 | docker-compose up 204 | ``` 205 | 206 | Append `-d` to run in detached mode. The first time you run a service, it is probably a good idea to not run in dettached mode (i.e. DON'T append `-d`) so you can watch all of the logs for issues. 207 | 208 | ## Configuration 209 | 210 | ### Configure Jackett 211 | 212 | | variable | description | 213 | | ------------ | ----------------------------------- | 214 | | JACKETT_PORT | the port that jacket will listen on | 215 | 216 | `:9117` 217 | 218 | `jackett` should be configurable the same as any other installation of it. Feel free to skip these steps if you know how to configure `jackett` already. 219 | 220 | - Add an Indexer 221 | - Click `+ Add Indexer` 222 | - Search for your desired tracker 223 | - Click on the 🔧icon next to your desired tracker 224 | - Sign in with your account information 225 | - Click `Okay` 226 | - You should see `Successfully configured ` and a new entry for your tracker 227 | - Copy the `API Key` from the top right corner and save it somewhere 228 | - Click the `Copy Torznab Feed` on the tracker you just added and paste it somewhere to save it 229 | 230 | ### Configure Sonarr 231 | 232 | | variable | description | 233 | | ----------- | ----------------------------------- | 234 | | SONARR_PORT | the port that sonarr will listen on | 235 | 236 | `:8989` 237 | 238 | `sonarr` should be configurable the same as any other installation of it. Feel free to skip these steps if you know how to configure `sonarr` already. 239 | 240 | ⚠️ It is critical that you use `transmission` instead of the IP address when configuring the download client, as well as `jackett` instead of the IP when setting up your indexer. This is because this uses docker-compose networking which means each service is accessible at the name of the service, rather than the host or even local IP address. 241 | 242 | Step-by-step for those who need it 243 | 244 | - Add an Indexer 245 | 246 | - Click on the `Settings` button at the top 247 | - Click on the `Indexers` tab 248 | - Click the big `+` symbol 249 | - Click the `Custom` button in the `Torznab` section 250 | - Configure your `Torznab` feed 251 | - `Name` : the name of this indexer (doesn't matter, just name it the name of your tracker) 252 | - `URL` : the `Copy Torznab Feed` url from `jackett` that you saved earlier 253 | - ⚠️ It is necessary to replace the IP with `jackett` 254 | - `http://jackett:9117/api/v2.0/indexers//results/torznab/` instead of 255 | - `http://192.168.1.11:9117/api/v2.0/indexers//results/torznab/` 256 | - `API Key` : the `API Key` from `jackett` that you saved earlier 257 | - Click `Test` to verify that it is configured properly 258 | - Click `Save` 259 | 260 | - Add a Download Client 261 | 262 | - Click on the `Settings` button at the top 263 | - Click on the `Download Client` tab 264 | - Under `Completed Download Handling` toggle `Enable` from Yes to No 265 | - We'll be using `filebot` to handle our completed downloads 266 | - Click the `Save` button at the top right 267 | - Click the large `+` button 268 | - Click on `transmission` 269 | - Configure your Download Client 270 | - `Name` : whatever you want; probably `transmission` 271 | - `Host` : `transmission` 272 | - `Port` : `5656` or whatever you have set for `TRANS_WEBUI_PORT` in your `.env` file 273 | - `Username` : `admin` or whatever you have set for `TRANS_WEBUI_USER` in your `.env` file 274 | - `Password` : `adminadmin` or whatever you have set for `TRANS_WEBUI_PASS` in your `.env` file 275 | - `Category`: `sonarr` - this allows transmission GC to properly remove torrents after seed limits exceeds 276 | - Click `Test` to verify that it is configured properly 277 | - Click `Save` 278 | 279 | - Add Some TV Shows 280 | - Click on the `Series` button at the top 281 | - Click `+ Add Series` 282 | - Start typing in the search bar. It will search automatically when you stop typing 283 | - Configure the download path (you should only have to do this on the first show you add) 284 | - Click the dropdown that says `Select Path` 285 | - Click `Add a different path` 286 | - Click the 📁button on the right of the modal 287 | - Click `tv` # final path should be `/tv/` 288 | - Click `Ok` 289 | - Click the green ✔️that is now visible 290 | - Click the `+` sign 291 | - There are many other configuration options for `sonarr` that are not covered here. `sonarr`'s webpage is [here](https://sonarr.tv/) 292 | 293 | ### Configure Radarr 294 | 295 | | variable | description | 296 | | ----------- | ----------------------------------- | 297 | | RADARR_PORT | the port that radarr will listen on | 298 | 299 | `:7878` 300 | 301 | `radarr` should be configurable the same as any other installation of it. Feel free to skip these steps if you know how to configure `radarr` already. 302 | 303 | ⚠️ It is critical that you use `transmission` instead of the IP address when configuring the download client, as well as `jackett` instead of the IP when setting up your indexer. This is because this uses docker-compose networking which means each service is accessible at the name of the service, rather than the host or even local IP address. 304 | 305 | Step-by-step for those who need it 306 | 307 | - Add an Indexer 308 | 309 | - Click on the `Settings` button at the top 310 | - Click on the `Indexers` tab 311 | - Click the big `+` symbol 312 | - Click the `Custom` button in the `Torznab` section 313 | - Configure your `Torznab` feed 314 | - `Name` : the name of this indexer (doesn't matter, just name it the name of your tracker) 315 | - `URL` : the `Copy Torznab Feed` url from `jackett` that you saved earlier 316 | - ⚠️ It is necessary to replace the IP with `jackett` 317 | - `http://jackett:9117/api/v2.0/indexers//results/torznab/` instead of 318 | - `http://192.168.1.11:9117/api/v2.0/indexers//results/torznab/` 319 | - `API Key` : the `API Key` from `Jackett` that you saved earlier 320 | - Click `Test` to verify that it is configured properly 321 | - Click `Save` 322 | 323 | - Add a Download Client 324 | 325 | - Click on the `Settings` button at the top 326 | - Click on the `Download Client` tab 327 | - Under `Completed Download Handling` toggle `Enable` from Yes to No 328 | - We'll be using `filebot` to handle our completed downloads 329 | - Click the `Save` button at the top right 330 | - Click the large `+` button 331 | - Click on `transmission` 332 | - Configure your Download Client 333 | - `Name` : whatever you want; probably `transmission` 334 | - `Host` : `transmission` 335 | - `Port` : `5656` or whatever you have set for `TRANS_WEBUI_PORT` in your `.env` file 336 | - `Username` : `admin` or whatever you have set for `TRANS_WEBUI_USER` in your `.env` file 337 | - `Password` : `adminadmin` or whatever you have set for `TRANS_WEBUI_PASS` in your `.env` file 338 | - `Category`: `radarr` - this allows transmission GC to properly remove torrents after seed limits exceeds 339 | - Click `Test` to verify that it is configured properly 340 | - Click `Save` 341 | 342 | - Add Some Movies 343 | - Click on the `Add Movies` button at the top 344 | - Start typing in the search bar. It will search automatically when you stop typing 345 | - Configure the download path (you should only have to do this on the first movie you add) 346 | - Click the dropdown that says `Select Path` 347 | - Click `Add a different path` 348 | - Click the 📁button on the right of the modal 349 | - Click `movies` # final path should be `/movies/` 350 | - Click `Ok` 351 | - Click the green ✔️that is now visible 352 | - Click the `+` sign 353 | - There are many other configuration options for `radarr` that are not covered here. `radarr`'s webpage is [here](https://radarr.video/) 354 | 355 | ### Configure Bazarr 356 | 357 | | variable | description | 358 | | ----------- | ---------------------------------- | 359 | | BAZARR_PORT | the port that bazar will listen on | 360 | 361 | `:6767` 362 | 363 | `bazarr` should be configurable the same as any other installation of it. Feel free to skip these steps if you know how to configure `bazarr` already. 364 | 365 | Step-by-step for those who need it 366 | 367 | - Configure connection settings for Sonarr: 368 | 369 | - `Hostname or IP Address`: `sonarr` 370 | - `Listening Port`: `8989` or whatever you have set for `SONARR_PORT` in your `.env` file 371 | - `API Key`: the `API Key` from `Sonarr` 372 | 373 | - Configure connection settings for Radarr: 374 | - `Hostname or IP Address`: `radarr` 375 | - `Listening Port`: `7878` or whatever you have set for `RADARR_PORT` in your `.env` file 376 | - `API Key`: the `API Key` from `Radarr` 377 | 378 | ### Configure filebot 379 | 380 | `:7676` 381 | 382 | | variable | description | 383 | | ----------------- | --------------------------------------------------------------------------------------------------------- | 384 | | FILEBOT_PORT | the web interface port for the filebot container | 385 | | FILEBOT_FORMAT | the filebot [format expression](https://www.filebot.net/naming.html) to use | 386 | | FILEBOT_ACTION | the [action](https://www.filebot.net/forums/viewtopic.php?t=4915) for filebot to take when renaming files | 387 | | FILEBOT_CONFLICT | what filebot does when it sees a conflicting filename | 388 | | FILEBOT_SERIES_DB | the database to use for TV metadata lookup | 389 | | FILEBOT_ANIME_DB | the database to use for anime metadata lookup | 390 | | FILEBOT_MOVIE_DB | the database to use for movie metadata lookup | 391 | | FILEBOT_MUSIC_DB | the database to use for music metadata lookup | 392 | | OPEN_SUB_USER | the opensubtitles username for filebot to use when downloading subtitles [NOT FUNCTIONAL] | 393 | | OPEN_SUB_PASS | the opensubtitles password for filebot to use when downloading subtitles [NOT FUNCTIONAL] | 394 | 395 | The opensubtitles configuration is called by the container startup script, but opensubtitles still fails when filebot is actually run. Until I figure out how to make this work, stick to `bazarr`. 396 | 397 | You can navigate to `:7676` to see the filebot command that will be run when a download is completed. Do NOT expose this port to the internet as it is not password protected. 398 | 399 | These are the `filebot` CLI options: . If there are additional options you want to be able to configure, open an issue. 400 | 401 | ⚠️ This has been updated to use the `4.9.x` version of `filebot` by default. In order to properly register after you have purchased a license, copy your `license.psm` file to the filebot config directory on your host machine. The container will automatically register `filebot` with that license. 402 | 403 | ### Configure transmission 404 | 405 | | variable | description | 406 | | --------------------- | ------------------------------------------------------------- | 407 | | TRANS_WEBUI_USER | the username with which to log into transmission | 408 | | TRANS_WEBUI_PASS | the password with which to log into transmission | 409 | | TRANS_WEBUI_PORT | the port for transmission's web interface | 410 | | TRANS_CONNECTION_PORT | the connection port for tranmission to use | 411 | | TRANS_MAX_RETENTION | the time in seconds before a torrent is automatically removed | 412 | | TRANS_MAX_RATIO | the ratio at which a torrent is automatically removed | 413 | 414 | `:5656` 415 | 416 | It should not be necessary to configure transmission beyond the default configuration. The container writes a config with reasonable defaults. If you need access to additional transmission settings, feel free to open an issue. 417 | 418 | The container is already automatically configured to call `filebot` to post-process a download. 419 | 420 | ### Configure nzbget 421 | 422 | ` -L 32400:localhost:32400 448 | ``` 449 | 450 | Once you do this, you can now log into plex via `localhost:32400/web` or `127.0.0.1:32400/web` and claim the server. Once the server has been claimed, you can log into it directly via the server's IP address. 451 | 452 | | variable | description | 453 | | ------------- | ------------------------------------------------------------------------------------------------------------ | 454 | | PLUGIN_LIST | a list of plugins to install. supported plugins are `trakt` and `subzero`. leave empty to install no plugins | 455 | | PLEX_WEB_PORT | the port for the plex web interface | 456 | 457 | `:32400/web` 458 | 459 | - Add some libraries 460 | - TV Shows will be at `/data/TV Shows` assuming you followed the `/media/TV Shows` convention for `TV_DIR` 461 | - Movies will be at `/data/Movies` assuming you followed the `/media/Movies` convention for `MOVIES_DIR` 462 | - ⚠️ If you don't use `Bazarr` set up your media agents to not use local files (hopefully this will be fixed in the future) 463 | - There is a problem that I have not been able to fix yet where local TV Series art is not available. It appears the artwork downloaded by `filebot` is not readable by `plex` for an unkown reason (I don't believe it's permissions related, but if you have ideas, please open an issue). 464 | - To get around this, uncheck `Local Media Assets` for all Agents under `Settings` > `Server` > `Agents`. Artwork will be downloaded by plex and accessible. 465 | - Kill and restart the containers after logging in to Plex if you have Plexpass 466 | 467 | ```sh 468 | docker stop plex 469 | docker-compose up -d plex 470 | ``` 471 | 472 | ### Reverse proxy / letsencrypt 473 | 474 | The compose file includes a letsencrypt container which you can use to set up a reverse proxy to various services which will automatically provision an SSL certificate for you to use. If you do not want to use a reverse proxy, simply delete that entry from the compose file. 475 | 476 | I recommend that you launch the full mediaserver once without the reverse proxy enabled so you can set up authentication for `sonarr`, `radarr`, `bazarr`, `nzbget`, `tautulli`, `netdata`, and `heimdall` 477 | 478 | The reverse proxy is configured to use subdomain routing by default. It copies in appropriate configurations for each service with these names 479 | 480 | | service | config name | 481 | | ------------ | ---------------- | 482 | | sonarr | s.subdomain.conf | 483 | | radarr | r.subdomain.conf | 484 | | transmission | t.subdomain.conf | 485 | | nzbget | n.subdomain.conf | 486 | | plex | p.subdomain.conf | 487 | | tautulli | u.subdomain.conf | 488 | | netdata | m.subdomain.conf | 489 | | heimdall | h.subdomain.conf | 490 | | bazarr | b.subdomain.conf | 491 | 492 | Config files for each subdomain will be present in the `config` directory on your host machine if you wish to change the configurations. The directory is `config/letsencrypt/nginx/proxy-confs`. If you wish to use different subdomains (e.g. `plex.domain.tld` instead of `p.domain.tld`) you need to change the configuration for the subdomain in that directory, and update the `LE_SUBDOMAINS` to include the new subdomain. 493 | 494 | Note that the first time you run the letsencrypt container, it can take some time for it to register an SSL cert. 495 | 496 | | variable | description | 497 | | ------------- | ---------------------------------------------------------------- | 498 | | LE_HOSTNAME | the hostname you are using to host the reverse proxy | 499 | | LE_EMAIL | the email for which your letsencrypt SSL cert will be registered | 500 | | LE_SUBDOMAINS | the subdomains for which to register the SSL cert | 501 | 502 | ### VPN networks for transmission, nzbget, and others 503 | 504 | I have built a wireguard container following the principles described [here](https://nbsoftsolutions.com/blog/routing-select-docker-containers-through-wireguard-vpn) and have successfully tested using docker-compose to force all traffic for `nzbget` through the wireguard VPN using a config from . 505 | 506 | Download or build a wireguard config file from your VPN provider. For example, mullvad has a wireguard config generator at . Once you have the config file (e.g. mine is called `wgnet0.conf`, copy that file into your config/wireguard directory. The container will automatically find the config file and build the VPN network for you. 507 | 508 | ⚠️ Do NOT use your VPN's killswitch in the `wireguard` config file. This will disallow traffic from the docker network which will make it inaccessible from the reverse proxy container. There is a rudimentary killswitch implemented in the `wireguard` container already. I may improve this over time. 509 | 510 | `docker-compose.yml` has been updated with a commented out wireguard service. There is also a commented out `nzbget` service configured to use the wireguard container's network as an example. This will force `nzbget` to proxy all traffic through the `wireguard` container, and thus through the VPN. You can follow the same pattern with the `transmission` container, or even `sonarr` and `radarr` if you want all queries to torrent trackers to go through the VPN. 511 | 512 | To proxy an additional container through the `wireguard` container's network, add the service name (e.g. `transmission`) to the list of network aliases defined in the `wireguard` service. 513 | 514 | ```yaml 515 | networks: 516 | default: 517 | aliases: 518 | - nzbget 519 | - transmission 520 | ``` 521 | 522 | Then update the new service's definition (e.g. `transmission`) to remove the port mapping list, and add 523 | 524 | ```yaml 525 | network_mode: "service:wireguard" 526 | depends_on: 527 | - wireguard 528 | ``` 529 | 530 | Because the `wireguard` has an alias to `transmission`, it is now accessible on `transmission:5656` just like it was before. You will also want to add the port mapping that were originally in the `transmission` service definition to the `wireguard` service definition. 531 | 532 | The `wireguard` container now has a proper route back to the local network over `eth0` so services that are using the `wireguard` network should now be accessible via your local subnet. You need to specify this subnet in the `LOCAL_NETWORK` environment variable. Thanks to [htilly](https://github.com/htilly/wireguard-docker) and [cmulk](https://github.com/cmulk/wireguard-docker) who's containers I shamelessly copied and modified. Once you have set up the route back to the local subnet, you can properly port foward through the VPN. See for details on port forwarding with `mullvad`. 533 | 534 | #### Why do you need to mount `docker.sock` for the wireguard container 535 | 536 | Mounting `docker.sock` is normally an anti-pattern for containers. However, when the `wireguard` container is started, `wg-quick` rewrites `/etc/resolv.conf` with the DNS address specified in the interface's `.conf` file. This breaks DNS resolution for docker services from within any container that is using the `wireguard` container as its network. In practice, this means that from within e.g. the `transmission` or `nzbget` containers, `curl filebot:7676` will fail DNS resolution. This breaks the auto-config between downlaoders and `filebot`. 537 | 538 | To work around this issue, the `wireguard` container now inspects the network (`docker network inspect mediaserver-docker_default`) and writes `/etc/hosts` entries for each service it finds in the network. This means that if one of your service IPs changes for any reason, you'll need to restart the `wireguard` container in order to be able to properly resolve DNS for docker services again. 539 | 540 | I believe it is possible to fix this issue using `dnsmasq` instead of writing `/etc/hosts` which would remove the requirement to read from `docker.sock`, but I have not been able to get it to work, so I'm leaving this hack in place for now. 541 | 542 | If you do not mount `docker.sock`, the `wireguard` container will still run, but any containers in the `wireguard` network will be unable to resolve DNS for other docker services. If that's fine with you, you don't need to mount `docker.sock`. 543 | 544 | ##### Update: mounting `docker.sock` is no longer necessary 545 | 546 | The `wireguard` container has been updated to use `dnsmasq` to conditionally route DNS requests. 547 | 548 | The container also now scrapes the wireguard interface file for its DNS server and write /etc/dnsmasq.conf with that as the final fallback DNS address. 549 | 550 | There are now three options for enabling docker DNS resolution from within the wireguard container: 551 | 552 | 1. If `docker.sock` is mounted, write `/etc/hosts` with any service in the network (this is really just for backwards comptability and is the same behavior as described above.) 553 | 554 | 2. If `LOCAL_TLD` is set (e.g. to local) write `/etc/dnsmasq.conf` to use `127.0.0.11` for that TLD. Also, write `/etc/resolv.conf` to search `LOCAL_TLD` so that containers can access the addresses of the services without having to know to append `.local` to match the rule in `/etc/dnsmasq.conf`. This will require aliases with the TLD in each of the containers that need to be accessible from within the wireguard network. An alias should look something like this (e.g. for `LOCAL_TLD=ghost`). 555 | 556 | ```yaml 557 | filebot: 558 | image: ghostserverd/filebot:4.9.x 559 | container_name: filebot 560 | restart: always 561 | networks: 562 | default: 563 | aliases: 564 | - filebot.ghost 565 | ``` 566 | 567 | which will result in `filebot` being accessible from containers within the `wireguard` network. 568 | 569 | 3. If `SERVICE_NAMES` is set (a list of services to make available from within the wireguard network), write each service name individually to `/etc/dnsmasq.conf` to force `127.0.0.11` as the DNS server for each service address. This is nice because you don't have to write an alias for each service to make available, but you do need to list out all of the services. A sample `SERVICE_NAMES` variable is set in the `docker-compose.yml` file. It shouldn't need to be modified, but if there is a reason to, open an issue and I can make it pull from the `.env` file. 570 | 571 | The last three settings are mutually exclusive. Only one of the mechanisms should be used. Of the last two, I'm not really sure which one I prefer, but they're both better than mounting docker.sock in my opinion. 572 | 573 | ## Thank You 574 | 575 | ### Linuxserver 576 | 577 | [linuxserverurl]: https://linuxserver.io 578 | [linuxserverforumurl]: https://forum.linuxserver.io 579 | [ircurl]: https://www.linuxserver.io/irc/ 580 | [podcasturl]: https://www.linuxserver.io/podcast/ 581 | [linuxserverdonate]: https://www.linuxserver.io/donate/ 582 | 583 | Most of these containers are config wrappers around [LinuxServer.io][linuxserverurl] containers. Without their amazing linuxserver containers, none of this would have been possible. If you find this automated media server useful, go donate to them! They probably deserve it more than I do. 584 | 585 | - [forum.linuxserver.io][linuxserverforumurl] 586 | - [IRC][ircurl] on freenode at `#linuxserver.io` 587 | - [Podcast][podcasturl] covers everything to do with getting the most from your Linux Server plus a focus on all things Docker and containerisation! 588 | - [Donate][linuxserverdonate] 589 | 590 | ### Filebot 591 | 592 | [fileboturl]: https://www.filebot.net/ 593 | [filebotforumurl]: https://www.filebot.net/forums/ 594 | [filebotpurchaseurl]: https://www.filebot.net/purchase.html 595 | 596 | This would also not be possible without filebot. This has been updated to use the latest `4.9.x` version of filebot. It supports automatic registration as long as you provide a license file. 597 | 598 | - [Filebot][fileboturl] 599 | - [Forum][filebotforumurl] 600 | - [Purchase][filebotpurchaseurl] 601 | 602 | ### ASCII word generation 603 | 604 | Thanks to patorjk for his [ascii text generator](http://patorjk.com/software/taag/#p=display&f=Ogre&t=ghost) 605 | 606 | [combustionurl]: https://github.com/Secretmapper/combustion 607 | 608 | ### combustion UI for transmission 609 | 610 | Thanks to `secretmapper` for the `combustion` UI for `transmission` 611 | 612 | - [Combustion][combustionurl] 613 | 614 | ### Donate 615 | 616 | If you really want to donate to me, you can do that here 617 | 618 | [![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=Y8B6ES2LDJ2N8¤cy_code=USD&source=url) 619 | 620 | ## Future Plans 621 | 622 | - Consider switching from `nginx` to `traefik` 623 | - Auto-configuration for linking `radarr` and `sonarr` to `transmission` 624 | - Auto-configuration for linking `radarr` and `sonarr` to `nzbget` 625 | - Auto-configuration for `plex` libraries 626 | - Improve documentation (maybe blog post with pictures) 627 | - ~~Better configuration options for `nzbget`~~ 628 | - ~~Wireguard as a network container for downloaders~~ 629 | - ~~Additional containers (`tautulli`, `muximux`, `portainer`)~~ 630 | - ~~Add reverse proxy support (`traefik`?)~~ 631 | - ~~Upgrade `filebot` to `4.8.2` and make it easy to license~~ 632 | --------------------------------------------------------------------------------