Giving /home a new home on ZFS
Currently on my main desktop machine my /home
directory resides on it's own 256gb SSD with an ext4 filesystem. I want to move this to a ZFS file system to take advantage of snapshots and compression.
I have a TrueNAS VM running in proxmox (more on this in future posts) that /home
then gets backed up to using an rsync
cronjob. However as I mentioned previously I would like to be able to take advantage of ZFS snapshots when doing backups so I have decided to move /home
to ZFS.
I run ubuntu 20.10 on my desktop PC so this is fairly straight forward. ZFS is supported out of the box in the kernel on ubuntu.
The only aspect that makes this a little bit messy is that I want to use ZFS on the existing SSD that currently has /home
on it. I'll need to do quite a bit of juggling files!
I am going to performing these steps on the live filesystem. I would recommend using a LiveCD for performing these tasks where possible, it'll make it a bit easier.
Install ZFS tools
First of all, let's install the tools required for managing zfs using apt.
sudo apt install zfsutils-linux
Copy /home to a temporary location
The next thing to do is copy the entire contents of the /home
directory that currently resides on the SSD to a temporary location. I have plenty of space on my main drive so I'm just going to create a folder there and copy everything to it but if you don't then feel free to use an external drive.
sudo mkdir /temp-hone
sudo cp -av /home/* /temp-home/
Using the -a
flag with cp
preserves all file attributes and copies recursively so there shouldn't be any strange file permission issues.
Edit fstab and un-mount the drive
Now that the /home
directory has been safely copied to another location fstab
can be edited to stop the partition being mounted at boot. For now we can simply comment out the relevant line incase something goes wrong and we need to revert this step.
sudo vim /etc/fstab
# /home was on /dev/sda1 during installation
# UUID=myuuid /home ext4 defaults
Next we can un-mount the drive. We use the -lf
flags for force and lazy un-mounting. Without this it won't work as there are programs running that are actively trying to access this file system. As I mentioned in the introduction, doing this in a live filesystem is less than ideal, which is why we had to take this step.
sudo umount -lf /dev/sda1
Copy /temp-home back to /home
Due to doing this live and having plenty of drive space we are going to copy the /temp-home/
to /home
so that when we reboot everything is where ubuntu suspects it to be, this now resides on the main OS drive.
A reboot is required because the home
drive was unmounted lazily and we need to be able to delete the partition(s) so that ZFS can do it's thing!
sudo cp -a /temp-home/* /home/
reboot
The system should come back up as if nothing has changed.
Use fdisk to delete partition
Before we can create the ZFS pool we need to delete all partitions from the second SSD, which is /dev/sda
. For this we can use fdisk
.
$ sudo fdisk /dev/sda
Welcome to fdisk (util-linux 2.36).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): d
Selected partition 1
Partition 1 has been deleted.
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Synching disks.
Using d
to delete the partition as there was only one and then w
to write the changes to the partition table.
Create a ZFS pool
The preparation is done so now we can finally create the ZFS pool. I'm going with mypool
for lack of a better name but feel free to choose whatever you like. I also only have the one drive so don't need to worry about any sort of RAIDZ or mirroring. If you have multiple drives you'd like in your pool you'll want to check out the manpages for zpool create
.
sudo zpool create mypool /dev/sda
Then just a quick zpool status
to check it was created.
$ sudo zpool status
pool: mypool
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
mypool ONLINE 0 0 0
sda ONLINE 0 0 0
errors: No known data errors
Create the ZFS filesystem
Next create the home
filesystem in the pool.
sudo zfs create mypool/home
And check it was created.
sudo zfs list
NAME USED AVAIL REFER MOUNTPOINT
mypool 984K 225G 192K /mypool
mypool/home 192K 225G 192K /mypool/home
Enable Compression
Another benefit of ZFS is being able to use compression, there is a slight performance hit for doing this but since it's just my home directory I don't see this causing me any issues. So let's enable that now.
sudo zfs set compression=lz4 mypool
I'm going to go with lz4 since this gives a great compression ratio for minimal performance impact. ServeTheHome have a great article about it.
Copy /temp-home to it's new home
Great! Now that we have the filesystem and it is mounted at /mypool/home
we can copy all the contents of the /temp-home/
directory to it once again using the cp -a
command.
sudo cp -av /temp-home/* /mypool/home
Then check the pool usage and compression ratio.
$ sudo zfs list -o name,used,avail,refer,mountpoint,compressratio
NAME USED AVAIL REFER MOUNTPOINT RATIO
mypool 54.9G 170G 192K /mypool 1.22x
mypool/home 54.9G 170G 54.9G /mypool/home 1.22x
And yep, we can now see that 54.9G is used up and the compression ratio is 1.22x. Compression has definitely paid off!
Delete everything in /home and mount the ZFS filesystem
Now to clean up and get the ZFS filesystem mounted at /home
.
Delete the /home
directory.
sudo rm -rf /home
Then change the mountpoint of mypool/home
to /home
. And while we are it we can stop mypool
from mounting by setting it's mountpoint to none
sudo zfs set mountpoint=/home mypool/home
sudo zfs set mountpoint=none mypool
Check that the files are there in /home
.
$ ll /home
total 22
drwxr-xr-x 4 root root 4 Apr 6 12:40 ./
drwxr-xr-x 24 root root 4096 Apr 6 12:46 ../
drwx------ 2 root root 2 Mar 4 17:42 lost+found/
drwxr-xr-x 46 ross ross 72 Apr 6 13:57 ross/
Awesome! Everything is there and now on a ZFS filesystem.
Reboot
Finally a quick reboot to make sure it mounts correctly on boot, there's no reason it shouldn't but better to be safe than sorry.
sudo reboot
And everything is there as expected. Success!
$ ll /home
total 22
drwxr-xr-x 4 root root 4 Apr 6 12:40 ./
drwxr-xr-x 24 root root 4096 Apr 6 12:46 ../
drwx------ 2 root root 2 Mar 4 17:42 lost+found/
drwxr-xr-x 46 ross ross 72 Apr 6 13:57 ross/
Summary
This process would have been a bit less painful if I'd use a LiveCD environment as I wouldn't have to have copies of copies of my home directory but overall it seems to have gone well.
I'm going to keep /temp-home
around for a week or so just incase something goes wrong but once I'm happy everything is okay that will be deleted.
The next steps are to learn more about ZFS snapshots and replication so that I can start using these for my backups. I'm pretty new to ZFS and this is the first time I've created pools and file systems in this manor, my only previous experience was in TrueNAS which gives a nice web UI interface for performing all these tasks.
I've heard great things about sanoid so I'm probably going to go with that for my snapshot and backup solution. I'll of course write a blog post about it but for now I'm just going to keep my rsync
cronjob around for backups.
If you have any questions or suggestions for using ZFS please get in touch. Contact details be found here.