A CentOS 7 BTRFS NAS device that Rocks!

By John Belthoff / In Blog / Posted Jan 28, 2016

I recently had the oppurtunity to build a NAS, (Network Attached Storage), device for a client. For years I have used NAS devices and have never quite been happy with the offerings from the several manufacturers. Some of the reasons for this was the hardware choices in the pre-build NAS devices, especially in a SOHO users price range, were always skimp a little. So I was happy to get the green light to build one for my client to get a little more power and some extra data protection.

Keep in mind I chose to max out this hardware because my client required that but you could certainly can get excellent performance from lower priced hardware so don't think the following is the only way to go. My main concern was to use a quality XEON processor and use ECC Ram. As it turns out, the folowing build maxes out a Gb network for file transfers with plenty headroom to spare. Let's get started...

Hardware Choices

  1. Intel® Xeon® Processor E3-1246 v3 
  2. CORSAIR RM550 PSU
  3. LIAN LI PC-Q26A Case
  4. ASRock E3C224D4I-14S Server Motherboard
  5. 16 GB ECC RAM
  6. 2 x Seagate 4TB NAS HDD - Regular Storage
  7. 2 x HGST 4TB Deskstar NAS HDD - Media Storage
  8. Samsung 850 PRO 128GB SSD - OS Drive

I chose to use 2 different set of mirrored disks. The Seagate, an excellent NAS drive, has an RPM of 5400 which is fine for standard long term storage of regular files. However for the Media Shares I chose the HGST 4TB Deskstar which have an RPM of 7200 with better seek time because this client has an extensive media collection which is streamed via a Plex Media Server which gives that service a little extra performance.

I chose BTRFS over ZFS because some of the limitations of the ZFS file system. I also chose to build the entire server directly from a Minimal CentOS 7 server install from the terminal. I don't need fancy Web GUI's so it's fine for me and seeing as this server sits in a closed room, there is not much need for a desktop or fancy interface.

What follows is the main build terminal commands I used to make the system work. This unit is part of a WInows Active Directory so it is joined to a domain using SAMBA (Version 4.2.3). It uses the latest Linux Kernel, 4.3.3-1.el7.elrepo.x86_64, at least at the time of this writing, and an upgraded BTRFS built from source - (btrfs-progs v4.3.1). 

So far, file transfers over the network share are running at 113 Mb/s which is as good as it gets. Also, we are able to stream 5 Full HD Transcoded Plex streams and only use about 75% of the CPU.

I hope this helps you if you decide to build your own NAS. If you have any problems with this please contact me and I will try to help you out.

The CentOS 7 BTRFS NAS Build Code

First, let's install some needed dependencies and update the minimal server.

## Centos 7 Minimal Server
yum install -y git libuuid-devel libattr-devel zlib-devel libacl-devel e2fsprogs-devel libblkid-devel lzo-devel asciidoc xmlto autoconf autoheader automake gcc

yum -y update

shutdown -r now

Build and install BTRFS

## Install New BTRFS Tools
git clone git://git.kernel.org/pub/scm/linux/kernel/git/kdave/btrfs-progs.git

cd btrfs-progs

./autogen.sh
./configure bindir=/usr/sbin
make
yum -y remove btrfs-progs
make install
make clean

cd ../
rm -rf btrfs-progs

## Btrfs Version
btrfs version

## before btrfs-progs v3.19.1
## after btrfs-progs v4.3.1

Install ELRepo RPM - Update Kernel and Set boot order.

## Install ELRepo RPM
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm

## Install Lates Kernel
yum -y --enablerepo=elrepo-kernel install kernel-ml

## Update Boot Order - May need to alter for UEFI boot
egrep ^menuentry /etc/grub2.cfg | cut -f 2 -d \'

## CentOS Linux (4.3.3-1.el7.elrepo.x86_64) 7 (Core)
## CentOS Linux (3.10.0-327.3.1.el7.x86_64) 7 (Core)
## CentOS Linux (3.10.0-327.el7.x86_64) 7 (Core)
## CentOS Linux (0-rescue-3321f82521434996c6d08be35c18345a) 7 (Core)

grub2-set-default 0

## Update again!
yum -y --enablerepo=elrepo-kernel update
shutdown -r now

Seeing as we are joining an existing domain, lets set some some params and install SAMBA. Out domain is "cooldomain.net" with an IP Address of "10.108.149.87". We will give this computer a name of "nas".

## Add following Hostname
vi /etc/hosts
10.108.149.87 nas.cooldomain.net centos

## Install Samba 4
yum -y --enablerepo=elrepo-kernel install samba* ntpdate ntp bind-utils
 
## Check Version
smbd -V
-- Version 4.2.3
 
 
## NTP Server Stuff - Set the time to the domain controller's time
systemctl enable ntpd.service
ntpdate dc-main.cooldomain.net
 
## Update NTP Config - Set DC to first server in the list
vi /etc/ntp.conf
server dc-main.cooldomain.net iburst prefer
 
## Start NTP
systemctl start ntpd.service
 
## DNS zone resolution
vi /etc/resolv.conf
 
search cooldomain.net
nameserver 10.108.149.17
nameserver 10.108.149.19
 
## Test DNS
host -t A dc-main.cooldomain.net
## Local hostname resolution
getent hosts centos

Let's configure SAMBA

## Find the Samba Config file
smbd -b | grep CONFIGFILE
 
## Configure Samba
vi /etc/samba/smb.conf
 
[global]
 
       netbios name = NAS
       security = ADS
       workgroup = COOLDOMAIN
       realm = COOLDOMAIN.NET
 
       log file = /var/log/samba/%m.log
       log level = 1
 
       dedicated keytab file = /etc/krb5.keytab
       kerberos method = secrets and keytab
       winbind refresh tickets = yes

       # Rnas Config Values
       max protocol = SMB3
       encrypt passwords = yes
       printcap name = /dev/null
       allow trusted domains = 0
 
       winbind trusted domains only = no
       winbind use default domain = yes
       winbind enum users  = yes
       winbind enum groups = yes
       # Important: The ranges of the default (*) idmap config
       # and the domain(s) must not overlap!
 
       # Default idmap config used for BUILTIN and local accounts/groups
       idmap config *:backend = tdb
       idmap config *:range = 20000-99999
 
       # idmap config for domain COOLDOMAIN
       idmap config COOLDOMAIN:backend = rid
       idmap config COOLDOMAIN:range = 100000-999999
 
       # Use template settings for login shell and home directory
       winbind nss info = template
       template shell = /bin/bash
       template homedir = /home/%U
 

## Test it
testparm
 
## Join the domain - Follow the prompts
net ads join -U administrator
 
## libnss_winbind
vi /etc/nsswitch.conf
 
passwd:     files winbind
shadow:     files winbind
group:      files winbind
 
 
## Start the Deamons
systemctl enable nmb.service
systemctl start nmb.service
systemctl enable smb.service
systemctl start smb.service
systemctl enable winbind
systemctl start winbind 
 
 
## Testing Winbindd user/group retrieval
wbinfo -u
wbinfo -g
 
## Testing OS Commands
getent passwd
getent group
 
## Open Firewall
firewall-cmd --permanent --add-service=samba
firewall-cmd --reload
 
### DONE WITH SAMBA!!! ###

Now that we are done with SAMBA, let's setup our BTRFS file systems and mirror our disks.

## Creating BTRFS Shares - Find the disks!!!!
ls -l /dev | grep sd
brw-rw----. 1 root disk      8,   0 Dec 19 20:52 sda
brw-rw----. 1 root disk      8,   1 Dec 19 20:52 sda1
brw-rw----. 1 root disk      8,   2 Dec 19 20:52 sda2
brw-rw----. 1 root disk      8,  16 Dec 19 20:52 sdb
brw-rw----. 1 root disk      8,  32 Dec 19 20:52 sdc

## Create Mirror & Mount it
mkfs.btrfs -m raid1 -d raid1 /dev/sd[bc]
mkdir -p /data-shares
mount /dev/sdb /data-shares/

## fstab
-- Get the UUID of the mirror
btrfs device scan

## Do some preliminary steps...
btrfs fi label /data-shares/ Shares
btrfs fi show /data-shares
btrfs balance start /data-shares

## Add the New Mirror to fstab
vi /etc/fstab
UUID=d5756c6e-6297-4239-889b-623437861e33 /data-shares/ btrfs defaults,autodefrag,skip_balance 0 0

## Create a Subvolume - This is optional
btrfs subvolume create /data-shares/sharedfolder
btrfs subvolume list /data-shares

## Change Permissions - Use your values here...
chown -R jbelthoff /data-shares/sharedfolder
chgrp -R nasusers /data-shares/sharedfolder

## Add share to smb.conf
vi /etc/samba/smb.conf

[Shared Folder]
       path = /data-shares/sharedfolder
       read only = no
       comment = "Crashplan Local Backup"
       browseable = 0
       admin users = "+admin","@COOLDOMAIN\domain admins"
       write list = "COOLDOMAIN\JBelthoff","@COOLDOMAIN\nasusers","+admin","COOLDOMAIN\Administrator"
       valid users = "COOLDOMAIN\JBelthoff","@COOLDOMAIN\nasusers","+admin","COOLDOMAIN\Administrator"

## Reload Samba
smbcontrol all reload-config

## Set SELinux!!!!
chcon -t samba_share_t /data-shares/sharedfolder


#####################################################################
## ALL DONE ! #######################################################
#####################################################################

At this point you should be able to connect from your windows machine. Simply map a network drive.