commit 421ed4f6c1a25bf9cd5eebd938072e7ec81b315b Author: Adrien Poupa Date: Sat Feb 19 17:17:15 2022 -0500 feat: Initial commit diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..d1292bb --- /dev/null +++ b/.env.example @@ -0,0 +1,7 @@ +USER_ID=1000 +GROUP_ID=1000 +TIMEZONE="America/New_York" +PIA_LOCATION=ca +PIA_USER= +PIA_PASS= +PIA_LOCAL_NETWORK="192.168.0.0/16" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..75254f8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +.env +.idea +/heimdall +!/heimdall/.gitkeep +/sonarr +!/sonarr/.gitkeep +/radarr +!/radarr/.gitkeep +/prowlarr +!/prowlarr/.gitkeep +/qbittorrent +!/qbittorrent/.gitkeep +/pia +!/pia/.gitkeep +/pia-shared +!/pia-shared/.gitkeep diff --git a/CONFIGURATION.md b/CONFIGURATION.md new file mode 100644 index 0000000..ce6e8ca --- /dev/null +++ b/CONFIGURATION.md @@ -0,0 +1,101 @@ +# Configuration + +## Environment Variables + +`cp .env.example .env` + +then fill the `.env` file with your variables: + +- `USER_ID`: ID of the user to use in Docker containers, defaults to `1000` +- `GROUP_ID`: ID of the user group to use in Docker containers, defaults to `1000` +- `TIMEZONE`: for the containers, defaults to `America/New_York` +- `PIA_LOCATION`: servers to use for PIA, defaults to `ca`, ie Montreal, Canada with port forwarding support +- `PIA_USER`: PIA username +- `PIA_PASS`: PIA password + +## PIA Wireguard VPN + +I chose PIA since it supports Wireguard and [port forwarding](https://github.com/thrnz/docker-wireguard-pia/issues/26#issuecomment-868165281), +but you could use other providers: + +- OpenVPN: [linuxserver/openvpn-as](https://hub.docker.com/r/linuxserver/openvpn-as) +- Wireguard: [linuxserver/wireguard](https://hub.docker.com/r/linuxserver/wireguard) +- NordVPN + OpenVPN: [bubuntux/nordvpn](https://hub.docker.com/r/bubuntux/nordvpn/dockerfile) +- NordVPN + Wireguard (NordLynx): [bubuntux/nordlynx](https://hub.docker.com/r/bubuntux/nordlynx) + +For PIA + Wireguard, copy the example `.env` and fill it with your PIA credentials: + +`cp .env.example .env` + +The location of the server it will connect to is set by `LOC=ca`, defaulting to Montreal - Canada. + +## Sonarr & Radarr + +### File Structure + +Sonarr and Radarr must be configured to support hardlinks, to allow instant moves and prevent using twice the storage +(Bittorrent downloads and final file). The trick is to use a single volume shared by the Bittorrent client and the *arrs. +Subfolders are used to separate the TV shows from the movies. + +The configuration is well explained by [this guide](https://trash-guides.info/Hardlinks/How-to-setup-for/Docker/). + +In summary, the final structure of the shared volume will be as follows: + +``` +data +├── torrents = shared folder qBittorrent downloads +│ ├── movies = movies downloads tagged by Radarr +│ └── tv = movies downloads tagged by Sonarr +└── media = shared folder for Sonarr and Radarr files + ├── movies = Radarr + └── tv = Sonarr +``` + +Go to Settings > Management. +In Sonarr, set the Root folder to `/data/media/tv`. +In Radar, set the Root folder to `/data/media/movies`. + +![](https://cdn.poupa.net/uploads/2022/03/root-folder.png) + +### Download Client + +Then qBittorrent can be configured at Settings > Download Clients. Because all the networking for qBittorrent takes +place in the VPN container, the hostname for qBittorrent is the hostname of the VPN container, ie `vpn`, and the port is `8080`: + +![](https://cdn.poupa.net/uploads/2022/03/qbittorrent.png) + +## Prowlarr + +The indexers are configured through Prowlarr. They synchronize automatically to Radarr and Sonarr. + +Radarr and Sonarr may then be added via Settongs > Apps. The Prowlarr server is `http://prowlarr:9696`, the Radarr server +is `http://radarr:7878` and Sonarr `http://sonarr:8989`: + +![](https://cdn.poupa.net/uploads/2022/03/sonarr.png) + +Their API keys can be found in Settings > Security > API Key. + +## qBittorrent + +Set the default save path to `/data/torrents` in Settings: + +![](https://cdn.poupa.net/uploads/2022/03/path.png) + +Restrict the network interface to Wireguard: + +![](https://cdn.poupa.net/uploads/2022/03/wireguard.png) + +The web UI login page can be disabled on for the local network in Settings > Web UI > Bypass authentication for clients + +``` +192.168.0.0/16 +127.0.0.0/8 +172.17.0.0/16 +``` + +## Heimdall + +Applications can be added in Items > Add. The URLs should be the static IP, ie: `http://192.168.0.10:8989/` for Sonarr +for example. + +![](https://cdn.poupa.net/uploads/2022/03/homepage.png) diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..9f5d028 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,88 @@ +# Installation + +## Requirements + +Any Docker-capable recent Linux box. +I am using a fresh Ubuntu Server 20.04 on a repurposed laptop so this guide reflects it, +but it would probably work with other distributions and different versions with a few tweaks. + +## Pre-Docker Steps + +### OpenSSH + +If not done during installation, install OpenSSH server for remote connection: `sudo apt install openssh-server` + +### Static IP + +Set a static IP: + +`sudo nano /etc//netplan/00-installer-config.yaml` + +```yaml +# This is the network config written by 'subiquity' +network: + ethernets: + enp2s0: + dhcp4: no + addresses: + - 192.168.0.10/24 + gateway4: 192.168.0.1 + nameservers: + addresses: [8.8.8.8, 8.8.4.4] + version: 2 +``` + +Here, `192.168.0.10` is going to be the static IP, and we will use Google's DNS servers. Apply the plan: + +`sudo netplan apply` + +You can check the server uses the right IP with `ip a`. + +### Laptop Specific Configuration + +If the server is installed on a laptop, you may want to disable the suspension when the lid is closed: + +`sudo nano /etc/systemd/logind.conf` + +Replace: +- `#HandleLidSwitch=suspend` by `HandleLidSwitch=ignore` +- `#LidSwitchIgnoreInhibited=yes` by `LidSwitchIgnoreInhibited=no` + +Then restart: `sudo service systemd-logind restart` + +## Docker Setup + +Install Docker by following [these instructions](https://docs.docker.com/engine/install/ubuntu/). + +Then, [install Compose V2](https://docs.docker.com/compose/cli-command/#install-on-linux). + +For a global installation (both your current user and `root` when using `sudo`), +copy `/usr/libexec/docker/cli-plugins` rather than `$HOME/.docker/cli-plugins/docker-compose`. + +You may then run the applications with `sudo docker compose up -d` + +## NFS Share + +It is now time to share the folders to other local devices using NFS, as it is easy to set up and fast. +Install the NFS kernel server: + +`sudo apt-get install nfs-kernel-server` + +Then edit `/etc/exports` to configure your shares: + +`/mnt/data/media 192.168.0.0/255.255.255.0(rw,all_squash,nohide,no_subtree_check,anonuid=1000,anongid=1000)` + +This will share the `media` folder to anybody on your local network (192.168.0.x). +I purposely left out the `sync` flag that would slow down file transfer. +On [some devices](https://forum.kodi.tv/showthread.php?tid=343434) you may need to use the `insecure` option for the share to be available. + +Restart the NFS server to apply the changes: `sudo /etc/init.d/nfs-kernel-server restart` + +On other machines, you can see the shared folder by adding the following to your `/etc/fstab`: + +`192.168.0.10:/mnt/data/media /mnt/nas nfs ro,hard,intr,auto,_netdev 0 0` + +## References + +- [NFS setup](https://askubuntu.com/a/7124) +- [Hardlinks and Instant Moves (Atomic-Moves)](https://trash-guides.info/Hardlinks/Hardlinks-and-Instant-Moves/) diff --git a/README.md b/README.md new file mode 100644 index 0000000..59125ac --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +# Docker Compose NAS + +After searching for the perfect NAS solution, I realized what I wanted could be achieved +with some Docker containers on a vanilla Linux box. The result is an opinionated Docker Compose configuration capable of +browsing indexers to retrieve media resources and downloading them through a Wireguard VPN with port forwarding. + +## Applications + +The following applications are available: + +- [Sonarr](https://sonarr.tv/): PVR for newsgroup and bittorrent users +- [Radarr](https://radarr.video/): Movie collection manager for Usenet and BitTorrent users +- [Prowlarr](https://github.com/Prowlarr/Prowlarr): Indexer aggregator for Sonarr and Radarr +- [qBittorrent](https://www.qbittorrent.org/): Bittorrent client with a complete web UI +- [PIA Wireguard VPN](https://github.com/thrnz/docker-wireguard-pia): Encapsulate qBittorrent traffic in +[PIA](https://www.privateinternetaccess.com/) with [Wireguard](https://www.wireguard.com/) with port forwarding. +- [Heimdall](https://heimdall.site/): Application dashboard + +## Installation + +See [installation instructions](./INSTALL.md). + +TLDR: `cp .env.example .env`, edit to your needs then `sudo docker compose up -d` + +## Configuration + +See [configuration](./CONFIGURATION.md). + +## Containers + +| **Application** | **Image** | **Port** | **Notes** | +|-------------------|------------------------------------------------------------------------------------|----------|-------------------------------------------------------------------| +| Sonarr | [linuxserver/sonarr](https://hub.docker.com/r/linuxserver/sonarr) | 8989 | | +| Radarr | [linuxserver/radarr](https://hub.docker.com/r/linuxserver/radarr) | 7878 | | +| Prowlarr | [linuxserver/prowlarr:develop](https://hub.docker.com/r/linuxserver/prowlarr) | 9696 | `develop` tag as it is not stable yet | +| PIA Wireguard VPN | [thrnz/docker-wireguard-pia](https://hub.docker.com/r/thrnz/docker-wireguard-pia) | | | +| qBittorrent | [linuxserver/qbittorrent:14.3.9](https://hub.docker.com/r/linuxserver/qbittorrent) | 8080 | Uses VPN network
Frozen to v4.3.9 due to Libtorrent 2.x issues | +| Heimdall | [linuxserver/heimdall](https://hub.docker.com/r/linuxserver/heimdall) | 80, 443 | | + + +## Improvement + +There is always room for improvement. I did not need those containers so I did not include them, but maybe you could +benefit from: + +- [Bazarr](https://www.bazarr.media/): companion application to Sonarr and Radarr that manages and downloads subtitles +- [Lidarr](https://lidarr.audio/): music collection manager for Usenet and BitTorrent users +- [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr): Proxy server to bypass Cloudflare protection, useful +for some indexers in Prowlarr +- [Jackett](https://github.com/Jackett/Jackett): API Support for your favorite torrent trackers, as a Prowlarr replacement +- [Plex](https://www.plex.tv/): Plex Media Server +- you tell me! diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..5066c9b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,99 @@ +version: "3.9" +services: + sonarr: + image: lscr.io/linuxserver/sonarr + container_name: sonarr + environment: + - PUID=${USER_ID} + - PGID=${GROUP_ID} + - PGID=${GROUP_ID} + volumes: + - ./sonarr:/config + - /mnt/data:/data + ports: + - "8989:8989" + restart: unless-stopped + radarr: + image: lscr.io/linuxserver/radarr + container_name: radarr + environment: + - PUID=${USER_ID} + - PGID=${GROUP_ID} + - PGID=${GROUP_ID} + volumes: + - ./radarr:/config + - /mnt/data:/data + ports: + - "7878:7878" + restart: unless-stopped + prowlarr: + image: lscr.io/linuxserver/prowlarr:develop + container_name: prowlarr + environment: + - PUID=${USER_ID} + - PGID=${GROUP_ID} + - PGID=${GROUP_ID} + volumes: + - ./prowlarr:/config + ports: + - "9696:9696" + restart: unless-stopped + qbittorrent: + image: lscr.io/linuxserver/qbittorrent:14.3.9 + container_name: qbittorrent + environment: + - PUID=${USER_ID} + - PGID=${GROUP_ID} + - TZ=${TIMEZONE} + - WEBUI_PORT=8080 + volumes: + - ./qbittorrent:/config + - /mnt/data/torrents:/data/torrents + restart: unless-stopped + network_mode: "service:vpn" + depends_on: + - vpn + vpn: + image: thrnz/docker-wireguard-pia + container_name: vpn + volumes: + - ./pia:/pia + - ./pia-shared:/pia-shared + ports: + - "6881:6881" + - "6881:6881/udp" + - "8080:8080" + cap_add: + - NET_ADMIN + - SYS_MODULE + environment: + - LOC=${PIA_LOCATION} + - USER=${PIA_USER} + - PASS=${PIA_PASS} + - LOCAL_NETWORK=${PIA_LOCAL_NETWORK} + - PORT_FORWARDING=1 + - PORT_SCRIPT=/pia-shared/portupdate-qbittorrent.sh + sysctls: + - net.ipv4.conf.all.src_valid_mark=1 + - net.ipv6.conf.default.disable_ipv6=1 + - net.ipv6.conf.all.disable_ipv6=1 + - net.ipv6.conf.lo.disable_ipv6=1 + healthcheck: + test: ping -c 1 www.google.com || exit 1 + interval: 30s + timeout: 10s + retries: 3 + restart: unless-stopped + heimdall: + image: lscr.io/linuxserver/heimdall + container_name: heimdall + environment: + - PUID=${USER_ID} + - PGID=${GROUP_ID} + - PGID=${GROUP_ID} + volumes: + - ./heimdall:/config + ports: + - "80:80" + - "443:443" + restart: unless-stopped diff --git a/heimdall/.gitkeep b/heimdall/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/pia-shared/portupdate-qbittorrent.sh b/pia-shared/portupdate-qbittorrent.sh new file mode 100755 index 0000000..3a0976f --- /dev/null +++ b/pia-shared/portupdate-qbittorrent.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +port="$1" +QBT_USER=admin +QBT_PASS=adminadmin +QBT_PORT=8080 + +echo "Setting qBittorrent port settings ($port)..." +# Very basic retry logic so we don't fail if qBittorrent isn't running yet + while ! curl --silent --retry 10 --retry-delay 15 --max-time 10 \ + --data "username=${QBT_USER}&password=${QBT_PASS}" \ + --cookie-jar /tmp/qb-cookies.txt \ + http://localhost:${QBT_PORT}/api/v2/auth/login + do + sleep 10 + done + +curl --silent --retry 10 --retry-delay 15 --max-time 10 \ + --data 'json={"listen_port": "'"$port"'"}' \ + --cookie /tmp/qb-cookies.txt \ + http://localhost:${QBT_PORT}/api/v2/app/setPreferences + +echo "qBittorrent port updated successfully ($port)..." diff --git a/pia/.gitkeep b/pia/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/prowlarr/.gitkeep b/prowlarr/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/qbittorrent/.gitkeep b/qbittorrent/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/radarr/.gitkeep b/radarr/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/sonarr/.gitkeep b/sonarr/.gitkeep new file mode 100644 index 0000000..e69de29