Automount Synology NFS shares from OpenBSD

       643 words, 4 minutes

A nice thing I like about macOS is that it automatically mounts CIFS shares from my Synology NAS. OpenBSD doesn’t seem to have any mounting utilities for SAMBA shares any more. But it can mount NFS shares. And those can be automatically mounted and unmounted using the amd(8) stock tool. So let’s configure the OpenBSD instances for automounting NFS shares.

The Synology NFS shares

Enabling NFS on Synology is quite simple. Read the Help Articles for more infos. I won’t cover it here but note that the followings will work with any kind of NFS shares. If you’re using FreeNAS, follow their directions.

Once configured on the NAS, OpenBSD should be able to see the NFS shares:

# showmount -e syno
Exports list on syno:
/volume1/docker                    192.168.0.0/24
/volume2/Downloads                 192.168.0.0/24
/volume2/homes                     192.168.0.0/24
/volume2/photo                     192.168.0.0/24
/volume2/TimeMachine               192.168.0.0/24

Those information are useful to get the shares paths that will be configured in amd(8).

Simple amd(8) configuration

The amd(8) configuration is quite straight forward. As soon as you understand how the map syntax works. One has to read the info(1) file to get more information: # info amd.

Enable NFS related daemons:

# rcctl enable portmap
# rcctl start portmap
portmap(ok)

# rcctl enable lockd
# rcctl start lockd
lockd(ok)

Enable the automounter daemon:

# rcctl enable amd
# rcctl set amd flags -l syslog -x error
# mkdir -p /mnt/syno
# echo "/mnt/syno amd.syno" >> /etc/amd/master

Describe the NFS shares in the map:

# vi /etc/amd/amd.syno
/defaults  rhost:=192.168.0.2;type:=nfs
docker     rfs:=/volume1/docker
Downloads  rfs:=/volume2/Downloads
homes      rfs:=/volume2/homes
photo      rfs:=/volume2/photo

Start amd(8):

# rcctl start amd

Accessing the shares is as simple as browsing the mount points:

# cd /mnt/syno/Downloads/
# ls -1
./
../
.apdisk\*
DevNeedHeroes.jpg\*
DevNeedHeroes.pptx\*
Fonts/
Freebox/
MacOS Desktop/
OpenBSD XFT/
OpenBSD-Keydisk.img
TEST.img
ThinkBSD/
ThinkPad-X260/
Ubuntu Live/
Wallpapers/
ubuntu-etc-fonts.tar.gz\*
unbound.conf
unbound.xml
# ls -alh /mnt/syno/Downloads lrwxrwxrwx 1 root wheel 39B May 19 17:04 /mnt/syno/Downloads@ -> /tmp_mnt/192.168.0.2/volume2/Downloads

After a certain amount of time (the default is 5 minutes), when amd(8) sees no more access to the share, it is automatically unmounted.

That would be nearly perfect if …

# mount
(...)
amd:90547 on /mnt/syno type nfs (v2, udp, intr, timeo=100, retrans=101)
192.168.0.2:/volume2/Downloads on /tmp_mnt/192.168.0.2/volume2/Downloads type nfs (v2, udp, soft, intr, timeo=100)

… amd(8) wasn’t stuck using NFS v2. AFAIK, NFS v3 would add support for files larger that 2GB and for asynchronous writes (hear increased performance). But there don’t seem to be an option to switch to NFS v3 in amd(8) ; as far as I understood the source code.

But… Where there is a shell, there’s a way!

Using NFSv3 with amd(8)

amd(8) comes with a mount type called “program”. It provides a way to do the mount / umount operations using any program. To enable NFSv3, let’s replace the previous type:=nfs with type:=program using a home-made script.

amd(8) will process every mount requests and pass the shares information to the script. The script will parse those args and mount / umount. Mine looks like this:

#!/bin/ksh
#
# Mount a NFSv3 share using amd(8)
#

# Expected args from amd(8)
_action=$1
_rhost=$2
_rfs=$3
_autodir=$4

if [ "$_action" == "mount" ]; then
  _lpath="${_autodir}/${_rhost}${_rfs}"
  [[ ! -d $_lpath ]] && mkdir -p $_lpath
  exec /sbin/mount_nfs -3is ${_rhost}:${_rfs} $_lpath
elif [ "$1" == "unmount" ]; then
  exec /sbin/umount ${_rhost}:${_rfs}
fi

exit 1
#EOF

The map file has to be modified to use this script for mount/umount operations:

# cat /etc/amd/amd.syno
/defaults  rhost:=192.168.0.2;type:=program;\
  mount:="/home/scripts/amd_nfsv3.sh amd_nfsv3.sh \
    mount ${rhost} ${rfs} ${autodir}";\
  unmount:="/home/scripts/amd_nfsv3.sh amd_nfsv3.sh \
    unmount ${rhost} ${rfs} ${autodir}"

Downloads  rfs:=/volume2/Downloads
docker     rfs:=/volume1/docker
homes      rfs:=/volume2/homes
photo      rfs:=/volume2/photo

Restart amd(8). From there, the NFS shares will be mounted using NFS v3

# mount | grep nfs
amd:54275 on /mnt/syno type nfs (v2, udp, intr, timeo=100, retrans=101)
192.168.0.2:/volume2/homes on /tmp_mnt/192.168.0.52/volume2/homes type nfs (v3, udp, soft, intr, timeo=100)

Now it’s time to modify all the backup scripts by removing the “mount / umount” bits :D