zx23 blog

Using Zfs for Easy Offsite Backups

Continuing our series of short posts and cool tips, here’s another one for your arsenal.

You’re probably familiar with zfs and its ability to send and receive dataset snapshots. Did you also know that it can send incremental snapshots, so you can keep your remote backup up to date with minimum transfer? Or how about an easy way to sync data from an old and about-to-be-retired server to a new 128 core one?

What you will need:

  • source server running zfs
  • destination server running zfs
  • root access on both of these servers
  • a network between the two servers, preferably a high-bandwidth one (add more links for redundancy or aggregation)

Start by making a snapshot of the source dataset.

# zfs snapshot tank/srv@`date +%s`

Prepare zfs receive process on the remote server. Note that we’re using nc(1) here to send and receive the stream accross an encrypted VPN tunnel. If your servers are connected by the public Internet, you should use ssh here instead. -I option to netcat specifies the size of the TCP receive buffer.

# nc -l -I 65536 128core.server.zx23.net 1337 | zfs receive tank/srv

Back on the source server, start the transfer and pipe it into nc(1). Remember to specify a matching TCP send buffer size and also add an IPv4 TOS value to maximise throughput.

# zfs send -v tank/srv@1440759638 | nc -O 65536 -T throughput 128core.server.zx23.net 1337
send from @ to tank/srv@1440759683 estimated size is 228.00G
total estimated size is 228.00G
12:05:13   10.5M   tank/srv@1440759638
12:05:14   25.5M   tank/srv@1440759638
12:05:15   39.3M   tank/srv@1440759638

So that took care of the initial backup. From now on, you can send incremental snapshots only. You first take a new shapshot of your dataset and then pass a -i option to zfs send to indicate what the previous snapshot was for this dataset.

# zfs snapshot tank/srv@`date +%s`
# zfs send -v -i tank/srv@1440759638 tank/srv@1440795521 | nc -O 65536 -T throughput 128core.server.zx23.net 1337

zfs receive command on the remote server needs no modification. zfs will realise its receiving an incremental backup and, provided the destination file system exists, will do the right thing.

Note that if the destination filesystem was modified (which can happen if you have atimes enabled on the filesystem), you will get the following error: cannot receive new filesystem stream: destination 'tank/srv' exists. must specify -F to overwrite it. Do as it suggests, and don’t worry, it won’t cause the entire filesystem to be transferred from scratch.