Hosting Plex Media Server on My Home Lab Using Docker and Acorn

Apr 11, 2023 by Sameer Kulkarni
Hosting Plex Media Server on My Home Lab Using Docker and Acorn

Overview

This is the fourth part of the series on building my own Kubernetes home lab. If you have followed the series, you already know that so far we have explored home labs, its use cases and the compute options available to set it up. We’ve also done hardware and networking setup to get them up and running while securing other devices on the home network. We then installed OS and hosted a Kubernetes cluster on it to make it ready to run containerized applications. In this post we’re going to make use of our home lab setup that we’ve built so far and run a utility application on it.

Do you have your own personal media collection, such as music, movies, TV shows and are looking for a way to make it available for viewing whenever necessary on multiple devices? Or are you looking for a way to securely back up your media files such as photos, videos, without having to pay a hefty subscription fee to cloud backup services? If you answered yes to any of the above questions, then you could make use of a home lab to do the same. The application that I’m going to host in this post will help me with just that.

The application we’re going to host is called Plex. Plex is a media server and a streaming service used to host and stream various digital media such as Movies, TV Shows, Music and Photos. You can watch free movies and live TV, as well as host any of your personal digital media collection. Be it anything that you own or have shot using your phone and other devices. You can add them to Plex, organize it and play it back on multiple devices of your choice such as Android TVs and Phones, Roku, Amazon Fire TV, Chromecast and more. Hence it can also double as your own media backup and playback solution.

Hosting Plex On My Home Lab

Plex can be hosted by downloading the Plex Media Server from their site. Plex also has a container image which can be used to run it on container runtimes such as docker or container orchestrators such as Kubernetes. Since I want to host my applications on Kubernetes, I would be using the container image instead of the installables available to download.

First and foremost thing you need to host the Plex Media Server is a place to store the media files. Since I had attached a 2TB internal SSD to one of my four home lab servers, that machine was the obvious choice for it. Although this machine doesn’t have this disk mounted or even partitioned. Hence we first need to create and mount a disk partition at an appropriate location.

We’d also need to create an NFS share out of this mounted partition, so that we can mount it on the Plex application pods. Otherwise, the Plex pods won’t be able to read/write data on this disk.

Preparation

As I mentioned in the second post, I have left my 2TB SSD disk untouched so far. Hence I

  • First need to create a partition on it and mount it on the machine and
  • Also need to create an NFS share on the same, so that I can mount the network shares on the Plex server pods running on any node in my Kubernetes cluster.

Creating and Mounting Disk Partition

I used the CLI utility called parted to partition my disk. Before I can create any partitions on it, I first need to create a partition table. My 2TB hardisk was named /dev/sda. You can find out your disk name by running the following command.

$ sudo parted -l

Find out disk name using parted CLI tool Host01.png

I created a partition table of type GPT. You may choose any other type of partition table according to your setup and requirements. Although, GPT is a newer type which works with larger disks and is also compatible with the newer UEFI based machines.

$ sudo parted /dev/sda # Open the disk you want to partition using parted $ mklabel gpt # Create a gpt partition table

Next let’s create a 1 TB partition. I suppose 1 TB should be enough space to host any current and future media I own. Use below command to create a 1000GB partition with a disk-start at 1 MB and an ext4 file system.

$ mkpart primary ext4 1MB 1000GB # Create a 1000GB partition $ print # Review partition information$ quit $ quit # Quit the parted utility

Partition your disk with parted CLI tool Host02.png

The last step before we mounting the partition, is to format it.

$ sudo mkfs -t ext4 /dev/sda1 # Format the partition before using

The partition is now ready to be mounted and used. Let’s create a directory to mount the partition at and then mount it.

$ sudo mkdir -p /mnt/sda1 # Create a mount point $ sudo mount -t auto /dev/sda1 /mnt/sda1 # Mount the disk partition

Our disk is now ready to be used as storage for our application.

Creating NFS shares

Plex app needs to mount two directories viz. config and data. Both of these would be mounted as nfs volume mounts. Hence let’s first create the two directories to create NFS shares.

$ sudo mkdir -p /mnt/sda1/plex/{conf,data} # Create the 2 NFS share directories

To run an NFS server and share these, we first need to install the nfs-kernel-server package and add the below lines to /etc/exports file. Note that the process I’m explaining here is for Ubuntu, since that’s the OS I’ve installed on my home lab machines. It may vary depending on your OS. Please make sure to follow the process for your OS.

/mnt/sda1/plex/conf 192.168.31.0/24(rw,sync,no_root_squash,no_subtree_check) /mnt/sda1/plex/data 192.168.31.0/24(rw,sync,no_root_squash,no_subtree_check)

If you want to share these directories with only certain IPs by replacing the CIDR with a comma separated list. The text in the parentheses following the * are NFS configuration options. You can read more about them here. Restart the NFS server for above changes to take effect.

$ sudo systemctl restart nfs-kernel-server

With this our NFS shares are also ready and now we can move on to running the application.

Running the Plex Media Server

Now that we have everything we need to run the Plex Media Server, let’s get to it. To do this I am going to use Acorn to run my Plex server. Acorn is a simple application deployment framework for Kubernetes. With this, developers can easily start making use of the powerful capabilities of Kubernetes, without having to dive into the complexities.

Install Acorn

To start using Acorn, we first need to install Acorn CLI on your machine. We can then use the CLI to install Acorn on our Kubernetes cluster. Use Homebrew to install Acorn on your Linux / macOS machine. See this for additional Acorn CLI install options.

$ brew install acorn-io/cli/acorn

Make sure your kubectl is pointing to the right Kubernetes cluster and run below command to install Acorn on the cluster.

$ acorn install

Creating Acornfile

Next we would need to write an Acornfile describing the Plex Media Server application and its configurations. Acornfiles have a similar structure as docker-compose files, while using a syntax similar to JSON and YAML. All of this makes writing Acornfiles very simple and compact. We start by providing some arguments for the Acornfile. They’re mentioned here separately for clarity and ease of maintaining the configuration for the file. The first argument defines how many replicas of the server should be run and the second argument is the plex server claim. You’ll need to get this token, you first need to create a free account for yourself and then go to https://www.plex.tv/claim/ to get the token. This token connects your account with your server to view your local content as well as from the streaming services all in one place.

Note: Once created, this token is valid only for 4 minutes. So make sure to get this token and configure it, only when you’re ready to run the application.

args: { scale: 3 "plexserver_claim": "claim-sV78fdGrGQ_aZsaJz-wn" } ...

The next section is for containers. We only need to run one container image to host the Plex Media Server, hence this Acornfile only has one container object. In other cases, you may add additional containers, if required. In the plexserver container object, we specify the image, the container ports to publish, and some environment variables. The PUID and PGID are the user and group ids to access the nfs mounts. See the linux documentation for more details. Lastly we mention the location where to mount the config and data volumes on the container.

... containers: { plexserver: { scale: args.scale env: { "PLEX_CLAIM": args.plexserver_claim "PGID": "1000" "PUID": "1000" "VERSION": "latest" "TZ": "Asia/Kolkata" } image: "ghcr.io/linuxserver/plex" ports: { publish: [ "pms-web:32400/tcp", "dlna-tcp:32469/tcp", "plex-companion:3005/tcp", "plex-roku:8324/tcp", "dlna-udp:1900/udp", "discovery-udp:5353/udp", "gdm-32410:32410/udp", "gdm-32412:32412/udp", "gdm-32413:32413/udp", "gdm-32414:32414/udp" ] } dirs: { "/config": "volume://plexserver-pv-nfs-config" "/data": "volume://plexserver-pv-nfs-data" } } } ...

The last section defines the nfs volumes to use for storing the Plex Server configuration and to read the local media streaming purposes. Note that the two volumes have different storage classes. That is because we have two different NFS shares that we have created above and we need a separate storage class pointing to them. You can find the complete Acornfile on my GitHub repository.

... volumes: { "plexserver-pv-nfs-config": { size: 10G class: "nfs-conf" accessModes: "readWriteMany" } "plexserver-pv-nfs-data": { size: 900G class: "nfs-data" accessModes: "readWriteMany" } }

Kubernetes doesn’t provide a volume provisioner for NFS mounts, hence we either have to install an external provisioner, as mentioned in the kubernetes documentation, or create PVs manually. In this case, I’m going to create PVs myself and mention the appropriate storage class on them, so as to match them with the right PVC that Acorn will create for my application.

You can find all the files and manifests I’ve used during this post to my github repository. Let’s first clone it and update it with your NFS share values. Run the below commands by replacing the place holders with your specific NFS share values.

$ git clone https://github.com/samkulkarni20/plex-server-acorn.git #clone the repo $ cd plex-server-acorn $ sed -i 's/NFS_SERVER_IP/<YOUR_NFS_SERVER_IP>/g' {sc.yaml,pv.yaml} $ sed -i 's/PLEX_CONF_NFS_PATH/<CONF_DIR_PATH_ON_SERVER>/g' {sc.yaml,pv.yaml} $ sed -i 's/PLEX_DATA_NFS_PATH/<DATA_DIR_PATH_ON_SERVER>/g' {sc.yaml,pv.yaml}

Let’s create the storage classes and PVs on the Kubernetes cluster now.

$ kubectl create -f sc.yaml # Create storage classes $ kubectl create -f pv.yaml # Create the persistent volumes

Run the Plex Media Server

We can now run the Acorn application and let it create the required Kubernetes objects, such as deployments and services to run the plex server for us. Make sure to update the plexserver_claim with the claim id from https://www.plex.tv/claim/.

$ acorn run -n plex-server .

When you run this command, Acorn will build a container image for the given Acornfile and push it to the local container registry that it runs when you install Acorn on the Kubernetes cluster. It then creates all the necessary Kubernetes objects to run the app. In this case it creates a Kubernetes deployment and ClusterIP as well as LoadBalancer type services.

Since I’m using K3s as my Kubernetes distribution, I don’t need to run an additional load balancer provider on my cluster. K3s by default runs ServiceLB for the same. If your Kubernetes distribution doesn’t include a load balancer, you can install something like MetalLB in order to have external IPs assigned to your LoadBalancer type services.

After the above command finishes successfully, check to see if all plexserver pods are running and get the external-ip(s) for pms-web load balancer service.

Plex Server Pods Ready Host03.png

Plex Server Service Ready Host04.png

Open the link http://pms-web-service-external-ip:32400/web, by inserting your own load balancer ip. This will open the plex server setup prompts. Follow the prompts to give your server a name and to add your local media library locations. Note that these locations must be under /data directory, since that is where we’ve mounted our NFS drive for storing local media.

Configure local media libraries Host05.png

This will complete your Plex Media Server setup and now you can enjoy locally hosted media server streaming and backing up all your personal media files. Now all you need to do is keep adding the local media files to your NFS directory and you can enjoy them from any device.

Accessing Plex Media Server on a browser Host06.png

Conclusion

Using Plex mobile app to view personal photos hosted on home lab Host07.jpg

In this post we saw

  1. How you can host your own Plex Media Server on your home lab to backup and stream your local media across various devices.
  2. How you can partition and mount your disks on Ubuntu
  3. How to create an NFS share and use it with your Kubernetes cluster.

We hosted the Plex Media Server app using Acorn. You can learn more about Acorn at https://docs.acorn.io/ or by joining a hands-on training class.

Do you think that the number of ads on the internet these days is too much and are looking for a one-stop solution to block them on all your devices? If yes, do check out the next post in this series, where I go over hosting an application on your home lab to do just that. If you’d like to get more comfortable with Acorn, you can register for an upcoming training class, or visit the getting started guide.

This is the fourth part in a series of posts on my home lab. Here are the other posts in the series.

  1. Building a Kubernetes Home Lab from the Ground Up
  2. Hardware and Networking Setup for My Home Lab
  3. Software Setup for My Home Lab
  4. Hosting Plex Media Server On My Home Lab
  5. Hosting Pi-hole on My Home Lab
  6. Creating an Application Dashboard for your Home Lab
  7. DIY Cloud Storage: Running Nextcloud on a Kubernetes Home Lab

Sameer Kulkarni is a software engineer with 14+ years of experience and is working as a Principal Engineer at InfraCloud. You can chat with him on Twitter and read more of his work on Medium.

Header Photo by Farzad on Unsplash