- Title:
- NFS on NetBSD: server and client side.
- Authors:
- Paolo Vincenzo Olivo
- Date:
- Topics:
- NetBSD, Self-hosting
- Id:
- n0bqc3
■ Premises
As pretty much any other UNIX system, NetBSD provides solid in-kernel NFS support.
Since I only run Windows occasionally (mainly for MS-Office or MATLAB) and all of my machines either run NetBSD, Slackware or Tribblix, it makes sense for me to opt for NFS as a distributed file system protocol to share files from server over the local network.
■ Server setup
1. Preliminary tasks
First of all, if you run a custom kernel, make sure to have support built-in, by inspecting your config:
$ config -x /netbsd | grep NFS
Which should at least return: #> file-system NFS # Network File System client ###> options NFSSERVER # Network File System server
In /etc/sysctl.conf, set the number of kernel threads created to serve asynchronous NFS I/O requests: # Number of kernel threads to use for NFS client vfs.nfs.iothreads=6
2. Configure a NFS server
I want make the following ZFS datasets available on the local network:
NAME USED AVAIL REFER MOUNTPOINT zfs/data 6.96G 493G 6.96G /zfs/data # pdfs, misc zfs/music 22.9G 77.1G 22.9G /zfs/music # music zfs/p2p 108G 1.61T 108G /zfs/p2p # torrent destdir zfs/pkg 3.95G 96.0G 3.95G /zfs/pkg # binary packages
First, create a /etc/exports file with the following content:
/zfs/data -alldirs -maproot=vms -network 192.168.1.0 -mask 255.255.255.0 /zfs/music -alldirs -maproot=vms -network 192.168.1.0 -mask 255.255.255.0 /zfs/p2p -alldirs -maproot=vms -network 192.168.1.0 -mask 255.255.255.0 /zfs/pkg -alldirs -maproot=vms -network 192.168.1.0 -mask 255.255.255.0
This tells mountd(8) to serve the datasets (and all subdirectories) for NFS mount requests coming from local client machines. The client's root user shall acces the shared directories as if it was user 'vms' on the server. See exports(5).
Now, let's look at relevant rc.d services.
Within /etc/rc.conf:
rpcbind=YES # required for Sun RPC services like lockd and statd mountd=YES # handle file-system mount requests nfs_server=YES # rcvar for nfsd nfsd_flags='-n6' # NFS I/O threads to create lockd=YES # handle record-locking operations on NFS file statd=YES # crash and recovery functions for the lock manager
Note: the lockd and statd services are handled by the /etc/rc.d/nfslocking rc script.
Enable the services:
$ for var in rpcbind mountd nfsd nfslocking > do service $var start > done
The mount output confirms that the dataset are now NFS-exported:
$ mount | grep NFS zfs/data on /zfs/data type zfs (NFS exported, local) zfs/music on /zfs/music type zfs (NFS exported, local) zfs/p2p on /zfs/p2p type zfs (NFS exported, local) zfs/pkg on /zfs/pkg type zfs (NFS exported, local
3. Firewall settings
We need to tell NPF to allow inbound traffic on NFS/RCP services coming from the local network. First let's check which ports where assigned to RPC services:
$ rpcinfo -p
program vers proto port service 100024 1 udp 1014 status 100024 1 tcp 1017 status 100021 0 udp 1013 nlockmgr 100021 1 udp 1013 nlockmgr 100021 3 udp 1013 nlockmgr 100021 4 udp 1013 nlockmgr 100021 0 tcp 1016 nlockmgr 100021 1 tcp 1016 nlockmgr 100021 3 tcp 1016 nlockmgr 100021 4 tcp 1016 nlockmgr 100005 1 udp 1012 mountd 100005 3 udp 1012 mountd 100005 1 tcp 1015 mountd 100005 3 tcp 1015 mountd 100003 2 udp 2049 nfs 100003 3 udp 2049 nfs 100003 2 tcp 2049 nfs 100003 3 tcp 2049 nfs
Then, by editing /etc/npf.conf, make sure these ports are opened to local clients:
$LAN = { 192.168.1.0/24 } $services_nfs = { rpcbind, nfsd, 1012-1017 } pass stateful in final from $LAN to $int_if port $services_nfs apply "log"
Atomically update the NPF ruleset:
$ npfctl reload
Now if everything went well, you should see the datasets available as NFS shares by running the showmount(8) command from a client machine:
$ showmount -e homelab Export list for homelab: /zfs/data 192.168.1.0 /zfs/music 192.168.1.0 /zfs/p2p 192.168.1.0 /zfs/pkg 192.168.1.0
Note: the server's internal address is assigned the name 'homelab' on the client's /etc/hosts file.
■ Client setup
1. Make sure to have:
rpcbind=yes nfs_client=yes lockd=yes statd=yes
inside /etc/rc.conf.
2. Start the services:
$ service rpcbind start $ service nfslocking start
■ Automounting NFS shares on NetBSD
A NetBSD NFS client is probably less common than a NFS server. But what if we run NetBSD on the desktop? Let's see the available options to automatize mounting NFS shares.
1. fstab
We can use /etc/fstab to define mount points and mount options on the client machine:
homelab:/zfs/data /net/data nfs rw,noauto,intr,timeo=14 0 0 homelab:/zfs/music /net/music nfs rw,noauto,intr,timeo=14 0 0 homelab:/zfs/p2g /net/p2p nfs rw,noauto,intr,timeo=14 0 0 homelab:/zfs/pkg /net/pkg nfs rw,noauto,intr,timeo=14 0 0
Notes:
- The `intr' mount option allows NFS requests to be interrupted if the server goes down or cannot be reached. Will avoid hanging.
- `timeo=n' defines the time (in tenths of a second) the NFS client waits for a response before it retries an NFS request. Default is 30.
- It is highly advisable to use `noauto' in order to avoid boot failures while mounting filesystems if the server is unreacheable (e.g. outside of the local netwotk)
- You may want to also play with `rsize=num' and `wsize=num', which define the maximum number of bytes in each READ/WRITE request that the NFS client can receive/send when communicating with a NFS server. On NetBSD this is set by default to 32K on amd64 and aarch64, to 8192 on other platforms. With such entries on fstab, mounting any shared dataset is as easy as:
$ mount <mountpoint>
For example, to mount homelab:/zfs/music, I'd use:
$ mount /net/music
2. amd(8)
We can use amd(8) on NetBSD to automount NFS shares. From ther man page:
> Amd is a daemon that automatically mounts filesystems whenever a file > or directory within that filesystem is accessed. Filesystems are auto- > matically unmounted when they appear to have become quiescent.
First, a map file is needed to tell amd how to resolve the lookup on the target filesystem to mount.
In this case I'll add a second [ /map ] section to my /etc/amd.conf, telling amd to use the mapfile named 'net' to mount the NFS-shared dataset under /net:
[ global ] karch = amd64 auto_dir = /amd unmount_on_exit = no restart_mounts = yes browsable_dirs = yes print_pid = no print_version = no dismount_interval = 5 cache_duration = 5 localhost_address = 127.0.0.1 log_file = /var/log/amd.log log_options = all search_path = /etc/amd map_type = file map_options = cache:=all
[ /media ] map_name = media
[ /net ] map_name = net
Make sure that the required directories are in place. Amd scans the $search_path for map files, uses $auto_dir to mount filesystems, and the directory specified by the [ /map ] section to make them available as NFS shares.
for dir in /amd /etc/amd /net > do [ -d "$dir" ] || mkdir $dir > done
A sample /etc/amd/net mapfile for NFS shares is provided below:
/defaults type:=host;rhost:=${key};fs:=${autodir}/${rhost}/root
pub type:=host;rhost:=homelab;fs:=${autodir}/${rhost}/root
Such map will mount any filesystems shared via NFS by the host homelab inside /amd/homelab/root, whenever a user tries to access /net, and symlink /amd/homelab/root to /net/pub. The shared datasets will be available inside /net/pub.
Now, let's (re)start amd:
$ service amd restart
$ amq / root "root" /media toplvl /etc/amd/media /media /net toplvl /etc/amd/net /net
Trying to access /net makes amd mount the shared filesystems:
$ file /net/pub pub: symbolic link to /amd/homelab/root $ cd /net/pub/zfs && ls data/ music/ p2p/ pkg/ $ amq -m | grep homelab homelab:/net/pub /amd/homelab/root host 0 homelab.retrobsd.ddns.net is up
3. autofs
TODO: likely covered in a separated post about autofs/automountd.