27th June, 2019
At present I've got an old Dell PC acting as my NAS box. I have two 6T HDD drives set up as a ZFS mirror pool. This is running Ubuntu server fine.
I know that the system is chewing a not insignificant amount of power running 24/7. It also has a two drive limit, but I want to be able to have up to four drives attached. This will allow me to:
The Raspberry Pi 4 with 4G of RAM has just been announced. It has a proper 1G Ethernet port and doesn't use much power. It also has a USB 3 port. So I've decided to buy a RPi4 and one of these Orico 6648US3-C 4-bay SATA to USB 3 docking stations. This will connect to one of the RPi4's USB 3 ports and make a NAS box. I can install my existing two HDDs and have two bays spare.
While I wait for the RPi4 and the Orico 6648US3-C to arrive, I've dug out my RPi3 so that I can get ZFS up and running on it.
To cut a long story short, I tried Raspian and couldn't get the ZFS modules to compile and load. Then I tried Ubuntu for the RPi3 and got the same result. Then I remembered that FreeBSD runs on the Raspberry Pi. This has native support for ZFS and I used to use FreeBSD a lot.
So, let's give FreeBSD a whirl and see if it will meet my needs. Here's how it has gone so far. I'll keep updating the blog entry as I get things working.
I went to the Download FreeBSD page and got the FreeBSD 12.0 SD card image for the RPI3.
Back on my desktop box, I did these commands to decompress the file and burn it to my SD card:
unxz FreeBSD-12.0-RELEASE-arm64-aarch64-RPI3.img.xz sudo ddrescue -D --force FreeBSD-12.0-RELEASE-arm64-aarch64-RPI3.img /dev/sdc
I put the SD card into my RPi3 and booted it up. There's no GUI, just a console screen. I logged in as root and password root.
adduser to create a user called wkt. I used
passwd to set
root's password. I edited
/etc/group and put wkt into the wheel
group; this allows wkt to run the
su command and become root:
I set a static IP address for the Pi by adding these lines to
ifconfig_ue0="inet 10.10.1.90 netmask 255.255.255.0" defaultrouter="10.10.1.1"
With this done, I can set up the ue0 interface:
/etc/rc.d/netif restart ue0
To set up the DNS server, I created the
/etc/resolv.conf file with the
details of the servers and the domain to use for names with no dots:
search local.net nameserver 10.10.1.1 nameserver 126.96.36.199
At this point I can remove the USB keyboard and HDMI monitor, remotely
login with ssh as user wkt and use the
su command to get to a root shell.
I'm going to run several services on this device, so I installed these packages by running these commands as root:
pkg install apache24 bash minidlna proftpd rsnapshot rsync samba48 sudo vtun
At this point I haven't done any configuration for these packages.
I'm used to running
sudo on Linux, so I've installed the sudo package.
In the file
/usr/local/etc/sudoers, I removed the comment at the beginning
of this line so that wheel group members can sudo:
## Uncomment to allow members of group wheel to execute any command %wheel ALL=(ALL) ALL
The Pi doesn't have a battery-backed clock, so I added these lines to
/etc/rc.conf to start the NTP daemon and to set the system clock at boot:
ntpd_enable="YES" ntpdate_enable="YES" # Run ntpdate to sync time on boot ntpdate_hosts="pool.ntp.org" # List of ntpdate(8) servers.
To set the system's timezone, I linked the relevant zone file thus:
ln -s /usr/share/zoneinfo/Australia/Brisbane /etc/localtime
I can't connect my existing ZFS mirror pool to the RPi3 as they are SATA drives; I wouldn't want to anyway, not until I know that things work.
Luckily, I have an external USB hard drive which is configured as a ZFS pool with the name TAFE2T. The nice thing about FreeBSD is that ZFS is already set up and ready to go. All I had to do was plug the USB drive into my existing RPi3 and do (as root):
zfs import TAFE2T
and this is what I see:
[root@naspi /etc]# df -h Filesystem Size Used Avail Capacity Mounted on /dev/ufs/rootfs 14G 3.0G 10G 23% / devfs 1.0K 1.0K 0B 100% /dev /dev/msdosfs/MSDOSBOOT 50M 13M 37M 26% /boot/msdos tmpfs 50M 4.0K 50M 0% /tmp TAFE2T 1.7T 171G 1.6T 10% /TAFE2T TAFE2T/Henry 1.6T 20G 1.6T 1% /TAFE2T/Henry
Now, how do I ensure that this gets auto-mounted at boot time?
This article says to do the
zfs import so that the system knows the pool names,
and add this line to
OK, so let's reboot the system and see what happens:
[root@naspi /etc]# reboot Connection to naspi closed by remote host.
After waiting about a minute for the RPi3 to reboot, I log back in with ssh
and I see ... no ZFS pools. Hmm, I can do
zfs mount -a and the pools
get mounted. So there is something going on that I haven't figured out yet.
It looks like ZFS starts before the USB drives are attached. So my solution
is to add this Bourne shell script to
#!/bin/sh # Try to mount the ZFS USB filesystems at boot time done="no" for i in 1 2 3 4 5 6 7 8 9 10 do if [ -c "/dev/da0" -a $done = "no" ] then logger "Mounting the ZFS stuff" zfs mount -a done="yes"; break else logger "Waiting for /dev/da0"; sleep 30 fi done
I probably don't need the done variable and can rely on the break to leave the loop.
When I read the output of
dmesg. I see these ZFS warnings:
ZFS NOTICE: Prefetch is disabled by default if less than 4GB of RAM is present; to enable, add "vfs.zfs.prefetch_disable=0" to /boot/loader.conf. ZFS WARNING: Recommended minimum kmem_size is 512MB; expect unstable behavior. Consider tuning vm.kmem_size and vm.kmem_size_max in /boot/loader.conf.
So I looked these up. The consensus is to leave prefetch disabled when
there is less than 4G of RAM. Hopefully when the RPi4 arrives (with 4G)
this will not be a problem. I've also tuned the kmem_size by adding these
# Tune the VMS settings for ZFS vm.kmem_size="512M" vm.kmem_size_max="512M"
I have a security camera which stores videos and images to a server using
the FTP protocol, so I've installed proftpd on the RPi3. In
/usr/local/etc/proftpd.conf I turned UseIPv6 off as I don't use it.
/etc/rc.conf I added:
to enable the service at boot time. I started it manually by doing:
service proftpd start
ftp in as a user and see my home directory. Now I'll set up a
second user (with
adduser) who has
/usr/sbin/nologin as their shell
(so they can't ssh in) and with a home directory where the videos and
images will be stored.
Ah, I can't
ftp in as the second user as proftpd doesn't know that
their shell is valid. So I edited
/etc/shells and added
as a valid shell.
Once I installed the apache24 package, there is a vanilla Apache 2.4
web service ready to go. The ServerRoot is
and there is a user www and group www to own the files. To start it,
add the line
/etc/rc.conf and then run the command
service apache24 start
The NAS box is going to be used by myself and my wife, so I'll need to set
up SMB file sharing with Samba. To do this, I'm copying the existing
Samba config file from the existing Dell server. On FreeBSD, this is
/usr/local/etc/smb4.conf. Here is most of my file:
[global] wins support = yes workgroup = WKTHOME server string = %h server (Samba, FreeBSD) log file = /var/log/samba4/log.%m log level = 3 max log size = 1000 hosts allow = 10.10.1., 10.10.2., 192.168.2., 127.0.0.1 security = user ; Allow HP printer to login with XP-style authentication ntlm auth = yes [Music] comment = Music path = /usr/500/Music public = yes writable = no [Scan] comment = Public Stuff path = /usr/Winshare/Scan public = yes writeable = yes printable = no write list = @staff
Samba keeps its own username/password database, so now I need to set up a Samba user:
]# smbpasswd -a -U wkt New SMB password: Retype new SMB password: Forcing Primary Group to 'Domain Users' for wkt Forcing Primary Group to 'Domain Users' for wkt Added user wkt.
As usual, we enable the service by adding a line to
and run a command to start the service:
service samba_server start
I keep a store of music and videos on my existing NAS box and serve these out to my Smart TV with minidlna. On the RPi3, I had to create the directories for my files:
mkdir -p /usr/Winshare/Photos /usr/500/Photos /usr/500/Video /usr/500/Music chmod 755 /usr/Winshare/Photos /usr/500/Photos /usr/500/Video /usr/500/Music
Then I edited
/usr/local/etc/minidlna.conf, removed the existing media_dir
line and added my own lines:
< media_dir=/opt --- > media_dir=P,/usr/Winshare/Photos > media_dir=P,/usr/500/Photos > media_dir=V,/usr/500/Video > media_dir=A,/usr/500/Music
As always, edit
/etc/rc.conf to enable the service at boot:
and start the service:
service minidlna start
I use a Linux desktop, so I want to mount directories from the NAS box using
the NFS protocol. I had troubles with connecting the Linux client to the
FreeBSD server using NFSv4. So here is my current FreeBSD configuration.
mountd_enable="YES" mountd_flags="-r -n" nfs_server_enable="YES" nfsuserd_enable="YES" nfsuserd_flags="-verbose" nfsv4_server_enable="YES" rpcbind_enable="YES"
/etc/exports file looks like this:
/usr/Winshare /usr/500 -maproot=root 10.10.1.2 10.10.1.14
so I export two mount points to two clients and allow the root uid on the client to map to the root uid on the server.
On the Linux client (as root), I can manually mount the exported directories:
mount.nfs -v -o nfsvers=3 naspi:/usr/500 /usr/500 mount.nfs -v -o nfsvers=3 naspi:/usr/Winshare /usr/Winshare
Note that I'm forcing the client to use NFSv3. Once the Dell server goes
away, on my Linux box I'll change my
/etc/fstab to have this:
naspi:/usr/Winshare /usr/Winshare nfs soft,noauto,nfsvers=3 0 0 naspi:/usr/500 /usr/500 nfs soft,noauto,nfsvers=3 0 0
OK, so apparently there is a separate exports file for ZFS filesystems.
And as both my
/usr/500 are ZFS filesystems, here is
what I had to do.
First, empty the existing
echo -n > /etc/exports
Now, create this file
/usr/Winshare -maproot=root 10.10.1.2 10.10.1.14 /usr/500 -maproot=root 10.10.1.2 10.10.1.14