Build a Media Server with FreeNAS Plex: Free Nightly DVR Recordings of TV/Movies

Build a Media Server with FreeNAS Plex: Free Nightly DVR Recordings of TV/Movies

FreeNAS Plex UI for browsing movies and tvs downloaded at night

There are many ways to build a media server, but the FreeNAS Plex approach is cheap, easy, and great for viewing different forms of movies, TV, audio, and pictures. However, you can also replace the FreeNAS bits with a DIY NAS.

What We’ll Build

This multimedia server will do a few things:

  • Record new TV shows and movies automatically and legally every night (with PlayOn).
  • Store those files so anyone can access them (on the NAS drive).
  • Catalog the media for viewing on any TV, computer or device in the house (with Plex).

The DVR recording part is not necessary. You could just put an existing media collection on the NAS and catalog it with Plex.

For Network Attached Storage basics, see the DIY NAS.

FreeNAS vs. Synology

If you need a lot of storage space or redundancy, a more sophisticated NAS may be in order.

While FreeNAS and Synology have both been major players in the space for years, FreeNAS has emerged as a popular DIY choice. It benefits from open-source and has a free option which works well enough for most home use-cases. If you have a big hard-drive or two lying around, it’s the easy choice.

If you’re ready to buy new hardware to build your NAS, then Synology may be the better option. Their all-in-one NAS solutions are much more plug-n-play. This may make the higher-end options the best NAS for Plex 4k and HDMI transcoding, as they are optimized for this use (the lower-end NASs will not be able to transcode files at these high resolutions).

Best NAS Server Hardware

With a Plex media server build, a lot still depends on how/what you want to watch.

You can go totally overboard with something like this, for the best 4k/HDMI streaming support:

… but for a single-family household like ours, we’re not watching on multiple TVs at once. The DVR/recording software (described below) captures mp4 files at 720p, so there’s really not much processing power needed by Plex (unlike when transcoding videos at 1080p). In fact, we have no trouble running FreeNAS hardware or even the DIY NAS:

If you’re going the FreeNAS server route, you might as well do a FreeNAS Plex setup. This is made quite easy by the fact that FreeNAS already has a plugin for Plex. You can just follow the official instructions, and you’ll get Plex and FreeNAS together. If you prefer the DIY NAS, just install the official Plex software on your server.

Either way, you should now have access to the Plex UI.

Running FreeNAS Docker

In the beginning, I had hoped to run FreeNAS Plex as a Docker container.

In retrospect, this would not work well. A NAS depends on efficient access to the filesystem. Running FreeNAS inside Docker would slow down this access.

However, there is a FreeNAS Docker integration. That is: FreeNAS itself can run Docker containers. So the server can be more than just a NAS. This can be done from the VMs tab.

Connecting to a FreeNAS server from a Docker container is similar to any NAS. There are two ways to go about it. The first is to mount the NAS on the machine running Docker (sudo mount). The second is to use the volume drivers to create a NFS drive for Docker:

docker volume create --driver local \
    --opt type=nfs \
    --opt o=addr=,rw \
    --opt device=:/nas \

In either case, the volume may now be mounted in the Docker container. The volume flag specifies the mapping: docker run -v nas:/nas. For Kubernetes, I use NFS Client Provisioner to create persistent volumes.

FreeNAS Plex Media Server Build

Now that FreeNAS Plex is running, it needs content.

I use PlayOn to automatically & legally record content. Although Plex does have its own DVR feature, it requires a subscription-based access (Plex Pass). PlayOn is a one-time purchase (I got it for $19.99).

It has its problems (such as only working on Windows and unfriendly UI), but the Windows desktop application is able to record from a variety of different streaming services. It also has a record during off-peak hours option, so I have it configured to run between 10pm and 5am. Finally, you can subscribe to a show within the app, causing it to be record the show automatically.

Once the show is recorded, it needs to be catalogued by Plex, which has strong opinions about where movies and TV should be located. Since this organization differs from PlayOn (not to mention, my Plex server is on a different computer), I wrote a quick script to automatically copy new downloads to the correct location on the Plex NAS:

#!/usr/bin/env python3
import subprocess, re, os, sys, yaml, shutil, time

if __name__ == "__main__":
    with open('plex.yaml', 'r') as stream:
        cfg = yaml.safe_load(stream)

    source = cfg['source']
    if not os.path.isdir(source):
        print(f'Invalid "source" directory: {source}')

    dest = cfg['destination']
    if not os.path.isdir(dest):
        print(f'Invalid "destination" directory: {dest}')

    exts = cfg['extensions']
    if not type(exts) is list or len(exts) < 1:
        print(f'No "extensions" provided.')

    default = cfg['default']
    if not default or len(default) < 1:
        print(f'No "default" sub-directory provided')

    m = cfg['map'] if type(cfg['map']) is dict else {}

    dest_dirs = {}
    for root, dirs, files in os.walk(source):
        for fn in files:
            fp = os.path.join(root, fn)
            mt = (time.time() - os.path.getmtime(fp)) / 60
            if mt < 1: continue # Skip files recently edited
            ext = fn.split('.')[-1]
            if not ext in exts: continue # Skip files not of the right type
            folders = 
            if len(folders) < 1: continue
            ff = folders[0]
            if ff in m:
                folders[0] = m[ff]
                folders = [default] + folders
            dd = os.path.join(dest, '/'.join(folders))
            dp = os.path.join(dd, fn)
            if os.path.isfile(dp):
                if os.stat(dp).st_size == os.stat(fp).st_size: # file likely unchanged

            print('/'.join(folders + [fn]))
            if not dd in dest_dirs: dest_dirs[dd] = {}
            dest_dirs[dd][fn] = fp

    for dest_dir in dest_dirs:
        if not os.path.exists(dest_dir): os.makedirs(dest_dir)
        sources = dest_dirs[dest_dir]
        for fn in sources:
            dp = os.path.join(dest_dir, fn)
            print(f'    {fn}')
            shutil.copyfile(sources[fn], dp)
extensions: ['mp4'] # Scan for files with one of these extensions
source: '/mnt/playon' # Scan (move from) this folder
destination: '/mnt/nas/plex/media' # Move to this folder
default: tv # Default sub-folder (in the destination) when no "map" is matched -- see below
map: # If the top-level folder within the source is one of these, change the folder to...
  Netflix: movies # e.g., /mnt/playon/Netflix -> /mnt/nas/plex/media/movies/
  Amazon Prime Video: movies
  Disney Plus: movies
  HBO NOW: movies
  Hulu: movies

To use this script, place both files in the same directory. Look at the plex.yaml file and read the comments to understand the configuration. The script will only copy matching files if they have not been recently modified (still being recorded) and the source file appears different than the destination (it does not exist at the destination, or the filesize has changed).

The result is that the completely downloaded movies appear in /mnt/nas/plex/media. They will be in the tv or movies subdirectory. In the FreeNAS Plex settings, enabling the auto-update features for the library cause them to then be catalogued:

freenas plex library auto-scan config
Automatically scanning the Plex library for updates.

Watching Plex with Kodi

Kodi is a media player that can run on just about any device.

See the following to set up Kodi to watch the Plex catalog:

Home Automation Ideas

Thanks for reading this post. You might be interested in this list of 100+ home automation ideas.

Or, drop your email in the form below and you'll receive links to the individual build-guides and projects on this site, as well as updates with the newest projects.

... but this site has no paywalls. If you do choose to sign up for this mailing list I promise I'll keep the content worth your time.

Written by
(zane) / Technically Wizardry
Join the discussion