(Note: this article is written as a companion article to our YouTube video on this topic. Please watch the video if you want the full setup walkthrough.)
We field many inquiries for custom builds to serve particular needs. We were recently asked for assistance to build a home media storage server to store family photos, video, DVD backup archive, and other media items and to use Plex to organize it. It needed to have a lot of space, be resilient, relatively power efficient, and fairly easy to maintain without cracking open the case. The system, as built, will deliver roughly 64TB of usable storage capacity.
System Build List
Part | Price |
AMD Ryzen 5 3400G | $149.00 (price varies currently) |
ASRock B550 Pro4 | $134.99 |
G-Skill Ripjaws V DDR4-3600 C18 (2x8GB) | $85.99 |
WD Black SN750 NVMe 500GB | $64.99 |
EVGA Super Nova 650 G5 PSU | $111.47 |
3-Pk SATA Male to Molex LP4 Female Power Adapter | $8.99 |
LSI 9211-8i | $59.99 |
2-Pk Mini SAS (SFF-8087) to 4 SATA | $14.99 |
Western Digital Ultrastar DC HC320 8TB SATA HDD | $169.36 |
Rosewill 4U Server Chassis w/ 12 Hot Swap Bays | $269.99 |
There’s a lot of debate on what a good set of Plex server components would be. If you’re wanting cheap, used Dell Optiplex systems with low-power Intel CPUs sporting QuickSync are a great option. With Plex recently supporting QuickSync for on-the-fly transcoding, it becomes almost a de facto option, as it can handle plenty of simultaneous transcodes at very low power usage. However a used computer with vendor-specific components does raise questions on longevity and build flexibility. Since we’re using twelve hard drives, we need at least 4 SATA from the motherboard and another 8 from a PCIe RAID/JBOD card, and then one additional port for the OS. This requirement would certainly shrink our potential used OEM systems, but for smaller deployments, may fit just fine.
While we’re not looking to host more than just a small household of users, the system is intended to be utilized for Virtual Machines and other uses as well in the future, so we need something bit a bit more power, but without bumping up out of our desired power range like a 95W CPU+dGPU would do. AMD’s 65W TDP APU idles at very lower power and under light load, runs more efficient than something like the i5 9600K.
We select the ASRock B550 Pro4 for its price, NVMe M.2 socket, and 6 SATA ports. The G.Skill Ripjaws V RAM was a cheap option for 16GB, which gives us enough headroom for a VM or two, on top of the Plex and filesystem requirements. The 500GB of NVMe might prove too small for all of Plex’s features to be enabled for a large library, so one might consider more space if you intend on using preview thumbnails.
We picked the EVGA Super Nova 650 G5 due to the chain of four Molex connectors and it’s outstanding 10 year warranty. The Gold rating ensures we’ll have a certain level of efficiency as well. We did have to spring for a 3-pack of SATA to Molex adapters to finish powering our backplane and chassis fans though. With the current component glut, PSUs are still fairly high-priced, so the $111 was fairly affordable compared to some of our other options.
We picked a Rosewill 4U server chassis due to being the least expensive 12+ 3.5″ hot swap bay chassis we could find. It’s a steal of a deal and can host the same components that we’d cram into a standard ATX case. An LSI 9211-8i compliments our SATA connectivity, giving us eight additional SATA connections with the two Mini SAS to SATA breakout cables. Our choice of Western Digital Ultrastar drives gives us Enterprise-class warranty and performance, designed to be ran 24/7 in a RAID. ZFS is a little more forgiving than a traditional hardware RAID however, so if you’re looking to skimp on the storage, lower-end models would work, but the extra cash for the longer warranty and for the piece of mind, it is strongly recommended you flex up just a bit. If you plan on shucking external USB drives though, keep in mind they’re not designed to run 24/7 under a workload, and you may notice more failures over time. It would be worth considering using a raidz3 instead of our intended raidz2, just to give you an extra bit of security when you’re faced with swapping out a failed drive.
You can watch us build the system in our video, starting at the 5:14 mark.
The Operating System
For storage servers, there’s a plethora of options to choose from. FreeNAS and Unraid are among the most popular DIY options, due to their appliance-like design and ease-of-use. FreeNAS has a web-based GUI and is built on top of ZFS, and uses a container-type system of “jails” to isolate hosted applications such as Plex. This adds to the complexity of the setup if you want to share the underlying storage pool and may pose challenges to users not used to using jails.
Unraid provides more flexibility than ZFS, allowing one to add extra hard drives and expand the volume as needed, so you don’t need to invest in your total quantity of disks up-front. ZFS is limited in that it doesn’t allow you to add more disks to a “vdev” on the fly, but instead you’d have to add a whole new raid set and expand onto it. If you’re looking to start small and add drives over time due to limited up-front funds, it might be worth looking at buying an Unraid license for $59 (6 drives) or $89 (12 drives). Unraid does support Docker and Virtual Machines, so can be made to do most things you’d be tempted to do with a native OS, so it’s worth considering if you wanted to spring the relatively low extra cost.
For the ultimate in flexibility and control however, we’re simply going to install a standard Fedora Server Linux distro. This gives us a fully-configurable Linux base to build from and can be adjusted to suit future use-cases easily. It also allows us to start with the minimum basics that we need right now, allowing us to add more on later as needed, and requires no extra licensing costs.
The Filesystem: ZFS
With a full Linux distribution, we have a wide variety of filesystem options. BtrFS and ZFS are top contenders. BtrFS (short for B-Tree Filesystem) has strong value in a NAS storage filesystem. It’s a Copy-on-Write filesystem that supports native RAID 0, 1, and 10, with experimental support for RAID 5 and 6. It supports snapshots, checksums for blocks, and inline compression and out-of-band deduplication. These are all key features we’re looking for. However, the experimental nature of RAID 5 and 6 in BtrFS, pushes ZFS more to the forefront.
OpenZFS is an open-source derivative of Oracle’s ZFS project. It supports all the features mentioned above, plus an extra parity disk beyond RAID 6 called “raidz3.” It also supports inline deduplication in addition to compression and allows for additional speed-up options of using flash storage for read/write-caching and filesystem journaling. We won’t be implementing these more advanced features, but it does provide us the option if we choose to implement them later.
Watch our installation of Linux and setup of ZFS in our video, starting at the 13:23 mark.
Resources and Links
Rufus bootable USB creation tool: https://rufus.ie/
Fedora 33 Server: https://getfedora.org/en/server/download/
OpenZFS Setup on Fedora: Fedora — OpenZFS documentation
Download Plex Media Server: https://www.plex.tv/media-server-downloads/#plex-media-server
Quick Reference for Fedora Setup:
sudo dnf install https://zfsonlinux.org/fedora/zfs-release$(rpm -E %dist).noarch.rpm
sudo gpg --import --import-options show-only /etc/pki/rpm-gpg/RPM-GPG-KEY-zfsonlinux
sudo dnf install zfs
sudo /sbin/modprobe zfs
sudo sh -c "echo zfs >/etc/modules-load.d/zfs.conf"
listserials.sh:
List the serials of attached storage drives.
#!/bin/bash
for i in /dev/sd?; do
echo "$i";
smartctl -i $i | grep "Serial Number";
done
smartchk.php:
This file just checks a few key values in SMART to give a quick-glance health check for your storage drives. This was designed to be quick and dirty, so if can’t vouch for its robustness, but it’s not meant to be a textbook example either.
#!/usr/bin/php
<?php
// @copyright Kirk Johnson - 2018
// Used to do a quick health check based on SMART data for storage drives
$line = exec("ls /dev/sd?",$results,$retval);
if ( $retval != 0 )
die( "$line\n\r" );
foreach($results as $value)
{
if ( !file_exists($value) )
continue;
$smartresults = array();
exec( "smartctl -iA '$value'",$smartresults,$smartval );
if ( $smartval == 0 )
{
$section = 0;
$printedFirstLine = false;
foreach($smartresults as $smartline)
{
if ( !strncmp($smartline,"=== START OF INFORMATION SECTION ===",36) ) {
$section = 1; continue;
}
else if ( !strncmp($smartline,"=== START OF READ SMART DATA SECTION ===",40) ) {
$section = 2; continue;
}
switch( $section )
{
case 1:
if ( stripos($smartline,"Serial Number:") === 0 ) {
$firstline = "\n\r$value\n\r$smartline\n\r";
$printedFirstLine = false;
}
break;
case 2:
//ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
// 1 Raw_Read_Error_Rate 0x000b 100 100 050 Pre-fail Always - 0
$parts = preg_split('/\s\s+/',ltrim($smartline));
if ( sizeof($parts) >= 9
&& (stripos($parts[0],"Reallocated_Sector_Ct") > 1
|| stripos($parts[0],"Current_Pending_Sector") > 1
|| stripos($parts[0],"Offline_Uncorrectable") > 1
|| stripos($parts[0],"UDMA_CRC_Error_Count") > 1) )
{
if ( $parts[8] > 0 )
{
if ( !$printedFirstLine ) {
print( $firstline );
$printedFirstLine = true;
}
print( "$smartline\n\r" );
}
}
break;
} // switch( $section )
} // foreach()
} // if ()
} // foreach()
?>