Building a FreeBSD NAS, part III: ZFS

Tags: howtos, freebsd

Published on
« Previous post: A better SSL configuration for Apache 2 — Next post: Making Qt and OpenSceneGraph play nice »

This is part III of my NAS project. Check out part II for some information about the base system setup and part I for the hardware setup.

Why ZFS?

Data security is paramount when setting up a NAS. You do not want to store valuable data on your NAS just to find out later on that it has been corrupted. Likewise, you might want your NAS to be able to survive one dead hard drive. This is where ZFS comes in handy. ZFS is a filesystem designed with server users in mind. Among other features, it offers:

  • Automated compression
  • Data integrity checks
  • Volume mirroring (“software RAID”)
  • Snapshots
  • Deduplication

The best thing, though: It is available out-of-the-box in FreeBSD.

The setup

I am only covering some very basic usage scenarios here. In the following, I am assuming that you have two disks on /dev/ada1 and /dev/ada2 respectively. We will put the home directories and a mount point for media files on those disks and finish with a simple mirroring setup. At the risk of sounding like a broken record here, I am repeating the sage advice of the ages: RAID does not replace backups. RAID is not a backup solution.

In other words: This setup protects you against one hard drive failing, but not against people deleting their data deliberately. It always pays to keep an external hard drive around that can store backups in a secure location. I am using secure in the sense of being secure against damages in your apartment, not against international espionage, by the way.

Preparing the disks

We first need need to create a GPT on the disk:

$ gpart create -s gpt ada1
$ gpart show ada1
=>        34  3907029101  ada1  GPT  (1.8T)
          34  3907029101        - free -  (1.8T)

Further partitions are not required. ZFS will do the rest for us.

Creating storage for the home directories

The basic entity of ZFS is a pool. A ZFS pool can consists of multiple disks. Each pool can contain numerous filesystems. Let’s start by creating a pool on the disk.

$ zpool create storage /dev/ada1

Pools can have any name. I do not want to get creative here and call mine simply storage.

Now let’s create a filesystem that uses the pool.

$ zfs create storage/home 

Moving the home directories

This step is not really related to ZFS, but I am including it for the sake of completeness. Basically, I am copying all home directories to the pool, then fixing the permissions (for each user individually) and deleting the old home directories:

$ cp -rp /home/* /storage/home
$ chown -R user1:group1 /home/user1
$ chown -R user2:group2 /home/user2
...
$ rm -rf /home/*

Setting a new mount point

Having moved the directories to the pool, we nonetheless want the filesystem to appear as /home. Setting a new mount point is easy:

$ zfs set mountpoint=/home storage/home

Enabling compression

If you want to enable compression for the new filesystem (which I would recommend; see this article about the benefits, for example), we again use the zfs command:

$ zfs set compression=gzip storage/home
$ zfs get compressratio storage/home
NAME          PROPERTY       VALUE  SOURCE
storage/home  compressratio  1.11x  -

Note that the compression ratio is likely to improve over time, depending on what sort of you data you store.

Creating storage for the media files

We need another filesystem for storing media files.

$ zfs create storage/media
$ zfs set atime=off storage/media
$ zfs set quota=800GB storage/media

Note that I disabled access time updates which improves read performance. For my media files, I do not care about access times because they will only be read by server applications.

I also set a quota for the media files to force me to throw away old stuff. Of course, the quota can be reset any time using the zfs command.

Attaching the second hard drive

Again, the zfs command is our friend here:

$ zpool attach storage /dev/ada1 /dev/ada2

This command is so simple and easy, it made me immediately fall in love with ZFS. Setting up a mirror could not be easier…

Making the changes persistent and enabling monitoring

ZFS should be loaded automatically whenever the NAS boots up, so rc.conf needs to be modified accordingly:

$ echo 'zfs_enable="YES"' >> /etc/rc.conf

If you have configured your NAS to send you e-mails (which I explained in part II), you can instruct FreeBSD to include information about all ZFS pools in the daily status reports:

$ echo 'daily_status_zfs_enable="YES"' >> /etc/periodic.conf

This will result in status information about the pools:

Checking status of zfs pools:
NAME      SIZE  ALLOC   FREE    CAP  DEDUP  HEALTH  ALTROOT
storage  1.81T   980G   876G    52%  1.00x  ONLINE  -

all pools are healthy

Conclusion & some resources

I have but scratched the surface of ZFS features. Data deduplication, for example, is one of the great things about ZFS. It means that ZFS will not store identical blocks multiple times on a pool but just once. Unfortunately, my NAS has not enough RAM for this to work reliably. I will maybe cover this in another article.

In the meantime, here are some other great resources about using ZFS:

May your drives never fail and your data prosper.