How to create your own Netflix

This is post is only for educational purposes. I am not condoning media piracy in any way

I was asking myself, how can I build my own Netflix. That questions derived in more specific questions like “how can I…”:

  • easily stream content from my storage device to my TV?
  • automate the gathering of content to put onto my storage device?
  • securely control the resulting system?

In this post, we will see how I managed to answer such questions, while at the same time, it was an excellent exercise to learn about Docker, combining several open sources or free programs.

To carry out this project, you will need:

  • A Linux OS and Docker
  • A PC or Laptop turned on 24 hours.

In my case, I used:

  • Ubuntu 16.04 LTS (LTS stands for Long Term Support)
  • Gigabyte Barebone

I choose an Ubuntu with long term support, as once the system is set-up, it will be connected to the Internet 24 hours. With that in mind, I want a stable operating system. You are free to choose other Linux distributions, such as Debian or CentOS, only make sure that the distribution is stable and maintained for the following years, as you do not wish to update the OS too frequently.

I also bought a Mini-Barebone and RAM on Amazon:

I recycled one 512 GB internal hard disk for my project, two USB hard disks of 1 TB, and one USB hard disk of 2 TB.

After assembling the barebone, I download an ISO image of Ubuntu, and follow the instructions to copy the installation image in one of the USB hard drives, following the instructions at the Ubuntu webpage: Create a USB Stick on Windows. Similar instructions are available is your main computer runs on Linux or macOS.

Installing Ubuntu is out of this post’s scope, but it is a relatively straightforward process of answering some questions and click Next several times.

Installing Docker

Docker offers us the possibility of installing a small operating system with some libraries and a program and everything encapsulated in a container. This encapsulation allows us to deploy programs consistently.

The official definition of Docker, according to Wikipedia:

Docker is a platform as a service (PaaS) products that use OS-level virtualization to deliver software packages called containers. Containers are isolated from one another and bundle their software, libraries, and configuration files to communicate through well-defined channels. Because all of the containers share a single operating system kernel’s services, they use fewer resources than virtual machines.

The instructions to install Docker in our Ubuntu server are explained step by step in the official documentation

Installing Docker Compose

Docker allows us to create containers, but in our case, we want to make several containers (each with one program). For that, we have docker-compose.

The instructions to install Docker Compose are well explained in the official documentation

Description of the programs to use

Plex

From their website:

Plex is like mission control for your media collections. With our easy-to-install Plex Media Server software and your Plex apps, available on all your favourite phones, tablets, streaming devices, gaming consoles, and smart TVs, you can stream your video, music, and photo collections anytime anywhere, to any device.

What this means is that you can install Plex Media Server on your main content storage device (most likely a server or PC of some kind running on your network) and can stream it to any Plex viewer app available (on iOS, Android, Raspberry, Chromecast, etc.)

This program is the answer to the question:

  • How can I easily stream content from my storage device to my TV?

Sonarr

From their GitHub page:

Sonarr is a PVR for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new episodes of your favourite shows and grab, sort and rename them. It can also be configured to automatically upgrade the quality of files already downloaded when a better quality format becomes available.

This program is a partial answer to the question:

  • How can I automate the gathering of content to put onto my storage device?

I have an answer to how to download TV Shows, but not Movies, and it open a new question:

  • How can I scan several torrents sites for the media content?
  • How can I download a torrent?

Radarr

From their GitHub page:

Radarr is an independent fork of Sonarr reworked for automatically downloading movies via Usenet and BitTorrent. The project was inspired by other Usenet/BitTorrent movie downloaders such as CouchPotato.

This program closes the automated gathering of content, as it will handle Movies, but with the same limitations of scanning torrent sites and download the torrent.

Jackett

From their GitHub page:

Jackett works as a proxy server: it translates queries from apps (Sonarr, Radarr, SickRage, CouchPotato, Mylar, etc) into tracker-site-specific HTTP queries, parses the HTML response, then sends results back to the requesting software. This allows for getting recent uploads (like RSS) and performing searches. Jackett is a single repository of maintained indexer scraping & translation logic - removing the burden from other apps.

This program allows us to scan several torrent sites, proving a standard API that Radarr and Sonarr can understand.

Deluge

From Wikipedia:

Deluge is a free and open-source, cross-platform BitTorrent client written in Python. Deluge uses a front and back end architecture where libtorrent, a software library written in C++ which provides the application’s networking logic, is connected to one of various front ends, including a text console, the web interface and a graphical desktop interface using GTK+ through the project’s Python bindings.

This program closes the loop, answering the question of how I download a torrent?

jwilder/nginx-proxy

From Docker Hub:

nginx-proxy sets up a container running nginx and docker-gen. Docker-gen generates reverse proxy configs for nginx and reloads nginx when containers are started and stopped.

Only a question has remained: How can I securely control the system?

With this docker image, I partially solve the question, as it allows to expose the programs presented above via the web.

jrcs/letsencrypt-nginx-proxy-companion

From Docker Hub:

lets-encrypt-Nginx-proxy-companion is a lightweight companion container for Nginx-proxy. It handles the automated creation, renewal and use of Let’s Encrypt certificates for proxied Docker containers.

This program closes the last question, as it will secure via HTTPS the web access of the programs presented above.

Preparing the storage

In my case, I decided to use several external USB hard-drives and concatenate the space into a single virtual drive. For that, I made use of LVM (Logical Volume Management).

The detailed instructions are outside the scope of this post, but the reader can find more information in Combine All Your Hard Drives Into One Seamless Storage Container With LVM.

After the virtual device was created, I format it with mkfs.ext4 and mounted the device in /mnt/storage/.

Creating the configuration for Docker Compose

Create a folder in your home folder, for example, media_centre and create a file with the name docker-compose.yml` inside the folder with the following code:

version: '2'

volumes:
  radarr-config:
    external: true
  sonarr-config:
    external: true
  deluge-config:
    external: true
  jackett-config:
    external: true
  nginx-vhostd:
    external: true
  nginx-confd:
    external: true
  nginx-html:
    external: true
  nginx-certs:
    external: true

services:

  plex:
    image: linuxserver/plex
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /mnt/storage/apps/plex/config:/config
      - /mnt/storage/media:/media/
      - /mnt/storage/apps/plex/transcode:/transcode
    environment:
      - VERSION=latest
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Amsterdam
    network_mode: "host"
    restart: unless-stopped
    
  radarr:
    image: linuxserver/radarr
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - radarr-config:/config
      - /mnt/storage/downloads:/downloads
      - /mnt/storage/media/Movies/:/movies
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Amsterdam
      - VIRTUAL_HOST=radarr.your.hostname.com
      - LETSENCRYPT_HOST=radarr.your.hostname.com
      - VIRTUAL_PORT=7878
      - HTTPS_METHOD=redirect
    restart: unless-stopped

  sonarr:
    image: linuxserver/sonarr
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - sonarr-config:/config
      - /mnt/storage/downloads:/downloads
      - /mnt/storage/media/TV Shows/:/tv
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Amsterdam
      - VIRTUAL_HOST=sonarr.your.hostname.com
      - LETSENCRYPT_HOST=sonarr.your.hostname.com
      - VIRTUAL_PORT=8989
      - HTTPS_METHOD=redirect
    restart: unless-stopped

  nginx-proxy:
    image: jwilder/nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - nginx-vhostd:/etc/nginx/vhost.d
      - nginx-confd:/etc/nginx/conf.d
      - nginx-html:/usr/share/nginx/html
      - nginx-certs:/etc/nginx/certs:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro
    labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy=true"
    restart: unless-stopped
      
  letsencrypt-nginx-proxy-companion:
    depends_on: 
      - nginx-proxy
    image: jrcs/letsencrypt-nginx-proxy-companion
    volumes:
      - nginx-vhostd:/etc/nginx/vhost.d
      - nginx-confd:/etc/nginx/conf.d
      - nginx-html:/usr/share/nginx/html
      - nginx-certs:/etc/nginx/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock:ro
    restart: unless-stopped

  deluge:
    image: ghcr.io/linuxserver/deluge
    environment:
      - PUID=1000 
      - PGID=1000 
      - TZ=Europe/Amsterdam 
    volumes:
      - deluge-config:/config 
      - /mnt/storage/downloads:/downloads 
    network_mode: "host" 
    restart: unless-stopped

  jackett:
    image: ghcr.io/linuxserver/jackett
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - jackett-config:/config
      - /mnt/storage/downloads:/downloads
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Amsterdam
      - VIRTUAL_HOST=jackett.your.hostname.com
      - LETSENCRYPT_HOST=jackett.your.hostname.com
      - VIRTUAL_PORT=9117
      - HTTPS_METHOD=redirect
    restart: unless-stopped

Remember to replace your.hostname.com for your user-friendly and easy to remember hostname. If you don’t have a domain, do not despair, you can find several Internet services providing DDNS. I am currently using Dynu.

Also, remember to replace 192.168.178.30 for the IP address of your server.

Starting up the system

Before starting the system, we must create the volumes specified at the beginning of the configuration. For that, we must type:

$ docker volume create --name radarr-config

And we repeat with all the external volumes defined in our docker-compose.yml file.

In the folder we created before, we start up our system by typing:

$ docker-compose up -d

It will take a while to download all images and create the HTTPS certificates with Let’s Encrypt, but do not worry. Everything is automatic, and no questions or pushing next is required. So, relax, and go to drink a coffee.

Configuring the system

After everything have been installed, our last step is to configure the system. For that, we must go to every program and follow the instructions in the welcome tutorial of each program.

We can enter into every program, pointing our web browser to:

  • 192.168.178.30:32400 or your IP address for Plex
  • 192.168.178.30:8112 or your IP address for Deluge
  • radarr.your.hostname.com for Radar
  • sonarr.your.hostname.com for Sonarr
  • jackett.your.hostname.com for Jackett

Congratulations, you just created your own Netflix.