Creating a backup of a Virtual Machine (Virtual Box) from you FreeNAS server and storing it offline in a safe spot should be part of a disaster recovery plan. I had setup a PiHole DNS advert blocking virtual machine, (you can follow the FreeNAS: Pi-Hole Virtual Machine Install article to install your own) and while it wouldn’t be too hard to recreate, when a DNS server is down, all of your network devices are probably not able to connect to the internet. So downtime is a real pain in the ass. Ideally, there would be a way to run PiHole in a jail, but it seems that there aren’t any plans to make it run on BSD based systems. So we are stuck using a VM and before I migrated my PiHole to my FreeNAS server I wanted to make sure backups were simple and could be easily automated, like FreeNAS: Backup Jails Automatically Using IOCAGE Import and Export. While it may not be absolutely crucial to backup a PiHole install, just more convenient, there any number of other use cases for Virtual Machines on FreeNAS which could hold critical data.
I’ve also put together a quick backup script which you can use to automate the backup of your virtual machine disk snapshot. Alright so lets jump in.
This article is part of my series of FreeNas setup, configuration and install articles.
Backing Up a FreeNAS Virtual Machine
We are not going to be backing up the drive so to speak but a snapshot of the drive. So the first think we are going to do is take a snapshot of the zVol which the virtual machine is using as a drive. In the FreeNAS WebUI, click your way to
Storage -> Snapshots -> Add You will need to select the dataset and name the snapshot.
Once you’ve created the snapshot, lets head to the WebUI shell (or you can SSH into server). Lets list all of the snapshots with this command
zfs list -t snapshot and find the one you want to backup.
We will now send the snapshot to a backup file wit the following command:
zfs send [pool]/[zvol]@[snapshotname] > [file_location]
In my case, it the command looks like this:
zfs send data/PiHole-9sprl@piholesnap > /mnt/data/phbackup1
Running this will take a few minutes depending on the size of the snapshot and the speed of your machine. Once it is done, that file you have created is your backup. Keep it someplace safe and you can restore your virtual machine anytime you would like!
Restoring the FreeNAS Virtual Machine
Restoring the backup is also pretty straight forward. You can either reattach to an existing virtual machine or you can create a new virtual machine to attach the zVol.
If you need to destroy the old pools, go to:
storage -> pools -> three little dots -> delete
Let’s head to the WebUI shell (or you can SSH into server) and run the following command:
zfs receive [pool]/[zVol] < [file_location]
In my case, it the command looks like this:
zfs receive data/PiHole < /mnt/data/phbackup1
Again, this will take a few minutes depending on the size of the snapshot and the speed of your machine.
Now we need to attach the new pool to the virtual machine. Through the WebUI, go to:
Virtual Machine -> Devices on VM. Select the ‘disk’ device and click the three dots and select edit. Under zVol, select the volume you just created (in my case /data/PiHole) and click OK. Go back and start the VM up again and you should be off and running with the restored drive.
If you are creating a new virtual machine, simply select use an existing disk and point to the zVol during the WebUI creation process.
I was able to put together a quick backup script which would backup the latest automated snapshot of a zVol. The script below, as noted in the comments of the file, takes two command line variables. The first is the zvol / snapshot name and the second is the location of the backup file.
#First command line variable is snapshot name. Second command line variable is the location of the backup file.
#Example below would backup the ssd/pihole snapshot to /mnt/backup.bak:
#bash vmbackup.sh ssd/pihole /mnt/backup.bak
snapshot=$(zfs list -t snapshot -o name -s creation -r $1 | tail -1)
echo “Backing-up latest snapshot of $1”
echo “Lastest Backup is $snapshot”
echo “Backup location is $2”
zfs send $snapshot > $2
Place the script somewhere and point a cron job (task -> cron job) to it. Just make sure that you coordinate the timing between your automated snapshots and the cron job.
So that’s it. Simple post, but a powerful backup solution.