Yesterday i finally fixed my zfs/nfs setup. While doing that, i came across some problems. This article documents these problems so others don't waste hours like i did.
My setup
I have a vm host that runs zfs for a lot of harddisks. I wanted to access the zfs datasets from my virtual machines. What i didn't want is to share the nfs exports across my whole network. So for security reasons, i wanted to share them via ipv6 link-local addresses.
So i set up a bridge on the vm-host with the ipv6 link-local address 'fe80::1' and all the vms are connected to this bridge. The vms have autoconfigured ipv6 link-local adresses.
######### br0 ens0 #####
#VM-Host#----------------+------------------------------#VM1#
######### fe80::1/64 | fe80::4242:ff:fe5e:beef/64 #####
|
|
| ens0 #####
\------------------------------#VM2#
fe80::4242:ff:fe5e:cafe/64 #####
zfs-on-linux and sharenfs
Zfs has a nice feature that exports datasets via nfs if you set the sharenfs option. So i tried:
zfs set sharenfs="rw=@fe80::/64%br0" mypool/mydataset
The result can be checked if you type the following command: (the mountpoint for my example is /srv/mypool/mydataset)
exportfs -v
/srv/mypool/mydataset
<world>(rw,wdelay,root_squash,no_subtree_check,mountpoint,sec=sys,rw,secure,root_squash,no_all_squash)
If you look at it, you might see the problem: Zfs exports it as world read-write allowed. That is not the intended behavior and probably a security risk. It seems zfs or nfs can't parse the link-local address and defaults to world.
The solution
After many tries this solution worked for me:
I disabled the sharenfs option for all my datasets.
zfs set sharenfs=off mypool/mydataset
And used /etc/exports for the nfs exports:
/srv/mypool/mydataset fe80::%br0/64(rw,no_root_squash,no_subtree_check)
This allowed access from the whole fe80::/64 subnet. But only on the bridge br0.
To reload the exports, you have to run
exportfs -ar
The (now working) syntax is a bit weird: You put the ipv6-link-local address, then the device with percent-symbol, and the cidr-mask last.
In retrospect, this might have worked with the sharenfs option, too.
Mounting the share inside the vm
This is my systemd-mount service file:
[Unit]
Description=NFS from vmhost
After=network.target
[Mount]
What=[fe80::1%%ens0]:/srv/mypool/mydataset/
Where=/srv/mydataset/
Type=nfs
[Install]
WantedBy=multi-user.target
The additional percent-sign is needed for systemd! The file needs to be called "srv-mydataset.mount" to satisfy the systemd requirements for filenames. (put it in /etc/systemd/system/)
To enable it and start it run:
systemctl daemon-reload
systemctl enable srv-mydataset.mount
systemctl start srv-mydataset.mount