I recently signed up for Netflix and am retiring my headless home media pc. This blog will have to serve as its obituary. The box spent about half of its life running FreeNAS, and half running Archlinux. I’ll briefly talk about my experience with FreeNAS, the migration, and then I’ll get to the robust setup I ended up with.
The machine itself cost around $1000 in 2014. Powered by an AMD A4-7300 3.8GHz cpu with 8GB of memory. A SilverStone DS380 case is both functional, quiet and looks great. The hard drives have been updated over the last two years until it had a full compliment of 6 WD Green 4TiB drives - all spinning bits of metal though.
Initially I had the BSD based FreeNAS operating system installed. I had a single hard drive in its own ZFS pool for TV and Movies, and a second ZFS pool comprised of 5 hard drives for documents and photos.
FreeNAS is straight forward to use and setup, provided you only want to do things supported out of the box or by plugins. Each plugin is installed into its own jail giving you full control over what data is accessible to each jail. There were several things that I really liked about FreeNAS; the web administration interface worked a charm, also had no problems using ZFS. Quite mind blowing taking disks offline and increasing the size of the pool by adding in larger drives. I haven’t used any BSD systems before this so making custom jails, installing custom software, running jails
with a VPN etc were all quite frustrating tasks.
Eventually these differences got too annoying, I decided to use what I knew from working with Docker and use my normal operating system: ArchLinux. I had read a lot about btrfs when I first set up FreeNAS so I was keen to switch filesystems at the same time. The migration was an exercise in care. I had approximately ~6TB of data. The ZFS pool could operate in degraded mode without any two of its disks - so in theory I could make the migration work without using external disks. Long story short I backed everything to two disks, replaced the ZFS pool with a BTRFS volume, and migrated the data. The ability to add additional disks to the live btrfs volume was very impressive. I almost got caught out by not removing the zfs partition labels with
I had these services running on both operating systems:
They all follow the same general template:
Management is all done with the
to start at boot.
Since each service is really just running a server inside docker, these are the containers I settled on:
I setup the mount points so that each service could only access what it needs to access. For example transmission can only write files in two download directories - one for music, and one for tv/movies. (Actually that isn’t 100% accurate - in order to not lose in-progress downloads when the docker container is restarted the
You can see the service files for each container on github at https://github.com/hardbyte/home-media-setup
The machine itself cost around $1000 in 2014. Powered by an AMD A4-7300 3.8GHz cpu with 8GB of memory. A SilverStone DS380 case is both functional, quiet and looks great. The hard drives have been updated over the last two years until it had a full compliment of 6 WD Green 4TiB drives - all spinning bits of metal though.
Initially I had the BSD based FreeNAS operating system installed. I had a single hard drive in its own ZFS pool for TV and Movies, and a second ZFS pool comprised of 5 hard drives for documents and photos.
FreeNAS is straight forward to use and setup, provided you only want to do things supported out of the box or by plugins. Each plugin is installed into its own jail giving you full control over what data is accessible to each jail. There were several things that I really liked about FreeNAS; the web administration interface worked a charm, also had no problems using ZFS. Quite mind blowing taking disks offline and increasing the size of the pool by adding in larger drives. I haven’t used any BSD systems before this so making custom jails, installing custom software, running jails
with a VPN etc were all quite frustrating tasks.
Eventually these differences got too annoying, I decided to use what I knew from working with Docker and use my normal operating system: ArchLinux. I had read a lot about btrfs when I first set up FreeNAS so I was keen to switch filesystems at the same time. The migration was an exercise in care. I had approximately ~6TB of data. The ZFS pool could operate in degraded mode without any two of its disks - so in theory I could make the migration work without using external disks. Long story short I backed everything to two disks, replaced the ZFS pool with a BTRFS volume, and migrated the data. The ability to add additional disks to the live btrfs volume was very impressive. I almost got caught out by not removing the zfs partition labels with
wipefs
. I’ve been warned that raid5 and raid6 isn’t very well tested in btrfs, but I’ve gotten away with it so far.I had these services running on both operating systems:
- Emby for streaming content to chromecast and other devices
- Couchpotato for finding movie torrents
- Sickrage for finding tv show torrents
- Headphones for finding music torrents
- Transmission for downloading the torrents
- OpenVPN for basic hiding of downloading activity
- Nginx webserver & reverse proxy to help access the above services and host local content
- systemd controlled docker containers for each service
- btrfs subvolumes created for each docker data volume
- anything that even thinks about torrents accessing the internet via VPN
They all follow the same general template:
[Unit]
Description=Some Dockerized Service
After=docker.service
Requires=docker.service
[Service]
Restart=always
RestartSec=60
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill container-name
ExecStartPre=-/usr/bin/docker rm container-name
ExecStartPre=/usr/bin/docker pull user/upstream-container-name
ExecStart=/usr/bin/docker run --net=host --rm \
-e TZ="Australia/Sydney" \
-v /mnt/drive/server-configs/container-name:/config \
-v /mnt/drive/Video:/media \
-v /mnt/drive/Music:/music \
-v /mnt/drive/Downloads:/downloads \
--name=container-name \
user/upstream-container-name
ExecStop=/usr/bin/docker stop -t 2 container-name
[Install]
WantedBy=multi-user.target
- I’m directly mounting volumes from
/mnt/drive
- This setup carries out updates on restart, a more robust approach would be to pin the container version.
- Note directives with
=-
are allowed to fail without consequence. - This template doesn’t link to any other docker containers.
[Unit]
Description=Transmission Server
# https://github.com/dperson/transmission
After=vpn.service
Requires=vpn.service
...
ExecStart=/usr/bin/docker run \
--net=container:vpn \
...
Management is all done with the
systemctl
tools. I’ve enabled all the services to start at boot.
Since each service is really just running a server inside docker, these are the containers I settled on:
- Emby -
emby/embyserver
- Couchpotato -
linuxserver/couchpotato
- Sickrage -
needo/sickrage
- Headphones -
linuxserver/headphones
- Transmission -
dperson/transmission
- OpenVPN -
dperson/openvpn-client
- Nginx webserver & reverse proxy -
dperson/nginx
http://your-machine/emby
or http://your-machine/transmission
. I set up a simple home page that nginx was serving to point users at the correct services.I setup the mount points so that each service could only access what it needs to access. For example transmission can only write files in two download directories - one for music, and one for tv/movies. (Actually that isn’t 100% accurate - in order to not lose in-progress downloads when the docker container is restarted the
incomplete
downloads folder is also a mount point).You can see the service files for each container on github at https://github.com/hardbyte/home-media-setup