HTPC, Docker, and Private Internet Access
Summary
This guide will walk you through the process of setting up an HTPC docker stack that routes everything through a VPN. I'm using Private Internet Access, but the VPN docker container is designed to work with a bunch of different providers. Please note the link above includes a referral code. All of the media-centric docker containers come from the outstanding work of the LinuxServer.io team. This guide does not walk through configuring the individual components.
Setup
Preface
This assumes you already have docker up and running. I'm running this on Arch Linux in a Proxmox container, but it should be the same across most distros.
Docker Containers
For reference, these are the containers that are used:
- Glueton for the VPN
- Deluge for BitTorrent
- Sonarr for TV
- Jackett for searching
- Radarr for movies
- NZBGet for newsgroups
- NZBHydra2 for generic newsgroup searching
System Settings
I've got a homebrew NAS/HTPC setup using Arch Linux and ZFS. There are a few variables you'll need to change based on your setup, but it should be fairly straight-forward. These are run under the uid:gid of 1000:1000 which is typically the first user that you've added to your system. More of that in a minute when we get to the LinuxServer.io containers and how that is leveraged. The setup looks like this:
# The directory that holds my docker-compose files
mkdir -p /opt/dockerfiles/htpc
# The directory that holds configurations
mkdir -p /opt/htpc
# The directory where all of my media is stored
mkdir -p /storage00/media/htpc
# Set the permissions on the above
sudo chown -R 1000:1000 /opt/dockerfiles/htpc
sudo chown -R 1000:1000 /opt/htpc
sudo chown -R 1000:1000 /storage00/media/htpcCreating the Docker Environment
Next we'll create a .env file that allows us to reuse values throughout the docker-compose.yml file that we'll create. Creating the file is simple enough:
# Create the file
vi /opt/dockerfiles/htpc/.envNow add the following to the file created above:
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
TZ=America/Detroit
# The UID and GID that I'd mentioned above.
PUID=1000
PGID=1000
# The directory where data and configuration will be stored.
ROOT=/opt/htpc
MEDIA=/storage00/media/htpcNext we'll create the docker-compose.yml file. You'll see where the variables above are automatically reused throughout the file. A couple of notes from the file:
- The Glueton containers acts as a VPN gateway for all the other containers, i.e. they need to route their connections through the VPN. It also acts as the front door for you to access the containers. The ports are listed in the docker-compose comments.
- The containers have dependencies so they start in the right order, e.g. Sonarr depends on Jackett which depends on Glueton.
And now for the docker-compose.yml file to bring it all together. First create the file:
# Create the file
vi /opt/dockerfiles/htpc/docker-compose.ymlCopy and paste the following into the file above. Please note that you'll need to customize the settings for the Glueton container:
version: '3'
services:
  gluetun:
    image: qmcgaw/private-internet-access
    container_name: gluetun
    cap_add:
      - NET_ADMIN
    network_mode: bridge
    ports:
      - 8888:8888/tcp # Tinyproxy
      - 8388:8388/tcp # Shadowsocks
      - 8388:8388/udp # Shadowsocks
      - 8000:8000/tcp # Built-in HTTP control server
      - 8112:8112 # deluge
      - 8989:8989 # sonarr
      - 9117:9117 # jackett
      - 7878:7878 # radarr
      - 6789:6789 # nzbget
      - 5076:5076 # hydra2
    # command:
    environment:
      - VPNSP=private internet access
      - TZ=${TZ}
      - USER=XXXXXXX # Your username
      - PASSWORD=YYYYYY # Your password
      - REGION=ZZZZZZ # Your region, e.g. US East. No quotes.
      - EXTRA_SUBNETS=10.0.0.0/8,192.168.0.0/16,172.16.0.0/12
    restart: unless-stopped
  deluge:
    container_name: deluge
    image: linuxserver/deluge
    restart: unless-stopped
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ${MEDIA}/unsorted:/downloads
      - ${ROOT}/config/deluge:/config
    network_mode: service:gluetun 
    depends_on:
      - jackett
      - gluetun
  sonarr:
    container_name: sonarr
    image: linuxserver/sonarr
    restart: unless-stopped
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ${ROOT}/config/sonarr:/config 
      - ${MEDIA}/tv:/tv 
      - ${MEDIA}/unsorted:/downloads 
    network_mode: service:gluetun
    depends_on:
      - jackett
      - gluetun
  jackett:
    container_name: jackett
    image: linuxserver/jackett
    restart: unless-stopped
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ${MEDIA}/unsorted:/downloads
      - ${ROOT}/config/jackett:/config
    network_mode: service:gluetun
    depends_on:
      - gluetun
  radarr:
    container_name: radarr
    image: linuxserver/radarr
    restart: unless-stopped
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    volumes:
      - ${ROOT}/config/radarr:/config 
      - ${MEDIA}/movies:/movies 
      - ${MEDIA}/unsorted:/downloads
    network_mode: service:gluetun
    depends_on:
      - jackett
      - gluetun
  nzbget:
    container_name: nzbget
    image: linuxserver/nzbget
    restart: unless-stopped
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ} 
    volumes:
      - ${MEDIA}/unsorted:/downloads 
      - ${ROOT}/config/nzbget:/config 
    network_mode: service:gluetun
    depends_on:
      - jackett
      - gluetun
  hydra2:
    image: linuxserver/nzbhydra2
    container_name: hydra2
    restart: unless-stopped
    environment:
      - PUID=${PUID} 
      - PGID=${PGID} 
      - TZ=${TZ} 
    network_mode: service:gluetun
    volumes:
      - ${ROOT}/config/hydra2:/config
      - ${MEDIA}/unsorted:/downloads
    depends_on:
      - gluetun
      - jackett
Assuming all goes well, you'll see a bunch of directories created based on the ENV variables that we'd set. For example:
[nlabadie@nas config]$ pwd
/opt/htpc/config
[nlabadie@nas config]$ ls
deluge  hydra2  jackett  nzbget  radarr  sonarr
[nlabadie@nas htpc]$ pwd
/storage00/media/htpc
[nlabadie@nas htpc]$ ls
movies  music  tv  unsortedConclusion
This should hopefully give you a starting point for your HTPC setup. I'm a fan of using Jellyfin as the server, and streaming the media using Infuse on Apple TV. They even make a fancy plugin for syncing the two.
You can access the individual services for setup by hitting the ports that are commented at the beginning of the docker-compose.yml file, specifically this:
- 8112:8112 # deluge
- 8989:8989 # sonarr
- 9117:9117 # jackett
- 7878:7878 # radarr
- 6789:6789 # nzbget
- 5076:5076 # hydra2For example, if your hostname is nas.domain.lan, then you'd go to the following URL to access Jackett: http://nas.domain.lan:9117. The same goes for all the other services listed above, e.g. http://nas.domain.lan:8112 for Deluge.