# _ _ _____ ____
# | \ | | ___/ ___|
# | \| | |_ \___ \
# | |\ | _| ___) |
# |_| \_|_| |____/
#
NFS stands for Network File System, and it is a way to share a portion or the entire file system across multiple systems. For those interested, NFS is a product of the famed Sun Microsystems (RIP), and was developed in 1984.
In linux, NFS comes in two varieties, a kernel base variety and a user based one. As one could easily deduce, the kernel based server uses a kernel module to provide network accessiblility to the shared system. Where the user based system relies on a system service to provide the same functionality. Both have benefits and risks. While the kernel variety is faster, it also poses greater risks to security. Regardless, most of the time, the kernel variety is what is desired.
This set of instructions was intended to be a quick “how-to”, but due to recent changes in how the service is configured for debian derivative distrobutions, it turned into anything but brief.
At the time of writing, Summer 2025, nearly every article of official documentation concerning setup of the nfs-kernel-server had not been updated to reflect the new changes. This of course, complicated things exponentially.
Only included in the official Debian wiki, is the step to first ensure that your kernel supports nfs. To do so run the command below, and check to make sure at least two implementations are listed.
grep NFSD /boot/config-`uname -r`
If you see two lines uncommented, then you are good to go.
First things first, install the software.
sudo apt install nfs-kernel-server
/etc/exports
The file /etc/exports
or set of files located in /etc/exports.d/*
is used by the NFS server to acquire
which folders should be shared with the network. The syntax is very basic, and only requires three parameters;
folder location, client(s) address(or network), and mount options. This file usually comes with examples
provided as comments, but for the sake of learning an example can be found below.
/some/random/mount/point 192.168.1.1(rw)
Which tells nfsd to share the folder at /some/random/mount/point
with the client on 192.168.1.1
and allow
both reading and writing. if you wanted to share that folder with the entire network, the second parameter
would have been something like 192.168.1.0/24(rw)
. Notice the definition of the subnet.
This is what we will primarily concern ourselves with.
[!note] Support for V3 More than likely your NFS client will support V4, and V3 support will not be required.
[!warning] OpenBSD Requires V3 For those badasses out there ruling the world with OpenBSD, V4 is not supported, so you will be required to keep V3 enabled. Sorry about that, but success comes with many sacrifices.
If you are planning to run version 3 of this protocol, then you will need to install an additional package
rpcbind
. and configure it for use.
sudo apt install rpcbind
By default, rpcbind only listens for connections on 127.0.0.1
, so in order to share your NFS share with your
local network you will be required to change this. Furthermore, you will need to modify the hosts.allow
file.
There are three different ways to modify the rpcbind configuration file. Choose one.
As part of a command line perl script: perl -pi -e 's/^OPTIONS/#OPTIONS/' /etc/default/rpcbind
Using sed: sudo sed -i 's/OPTIONS/#OPTIONS/g' /etc/default/rpcbind
By hand with a text editor: Simply open the file in an editor and comment out all the lines.
Now add the following line to your hosts.allow
file and restart the service.
echo "rpcbind: 192.168.1." >> /etc/hosts.allow
systemctl restart rpcbind.service
/etc/exports
The file /etc/exports
or set of files located in /etc/exports.d/*
is used by the NFS server to acquire
which folders should be shared with the network. The syntax is very basic, and only requires three parameters;
folder location, client(s) address(or network), and mount options. This file usually comes with examples
provided as comments, but for the sake of learning an example can be found below.
/some/random/mount/point 192.168.1.1(sync,wdelay,crossmnt,no_subtree_check,sec=sys,rw,insecure,no_root_squash,no_all_squash)
/var/nfs/share 192.168.10.0/255.255.255.0(rw,sync,no_root_squash,no_subtree_check,crossmnt,fsid=0)
Which tells nfsd to share the folder at /some/random/mount/point
with the client on 192.168.1.1
. If you wanted
to share that folder with the entire network, the second parameter would have been something like
192.168.1.0/24(sync,wdelay,crossmnt,insecure,rw, etc...)
. Notice the definition of the subnet.
Below are some NFS options used for this case:
When done restart or start the rpcbind service.
Before summer of 2025, to configure the server you would have modified two files /etc/default/nfs-common
and
/etc/default/nfs-kernel-server
. Now, this is no longer the case. All configuration should take place in
either the primary server configuration file /etc/nfs.conf
or in a localized configuration file located
in the configuration file directory at /etc/nfs.conf.d
. As a matter of server administration “best practices”
the latter of these choices is preferred.
To save time, one could simply copy an example configuration file from
/usr/share/nfs-commmon/conffiles/nfs.conf
to the localized configuration directory /etc/nfs.conf.d/
, or
simply copy and paste the example provided below.
[lockd]
port=32768
udp-port=32768
[mountd]
udp=no
port=32767
[nfsd]
udp=n
tcp=y
vers2=n
vers3=y
vers4=n
vers4.0=n
vers4.1=n
vers4.2=n
[statd]
port=32765
outgoing-port=32766
You will want to disable and mask unused parts of the NFS service to prevent them from being started by other services.
Since only version three requires the use of the rpcbind.service
you will want to disable it, and it’s
socket service.
sudo systemctl mask rpcbind.service
sudo systemctl mask rpcbind.socket
If you only want to run version three (v3), then you will want to mask these services that are only used on version 4.
# nfs-idmapd
systemctl disable nfs-idmapd.service
systemctl mask nfs-idmapd.service
systemct stop nfs-idmapd.service
# nfs-blkmap
systemctl disable nfs-blkmap.service
systemct stop nfs-blkmap.service
/etc/services
The /etc/services
file primarily is used by the system to reference what services are running on what ports.
This file is then used by iptables to provide definitions for firewall rules. At the end of this file is a
location for your local additions. You will want to provide the definitions for your nfs service ports here.
# Local services
#
# RPC/NFS ports
# Listing here does not mean they will bind to these ports.
#
rpc.statd-bc 32765/tcp # RPC statd broadcast
rpc.statd-bc 32765/udp # RPC statd broadcast
rpc.statd 32766/tcp # RPC statd listen
rpc.statd 32766/udp # RPC statd listen
rpc.mountd 32767/tcp # RPC mountd
rpc.mountd 32767/udp # RPC mountd
rpc.lockd 32768/tcp # RPC lockd/nlockmgr
rpc.lockd 32768/udp # RPC lockd/nlockmgr
Now that you have defined the ports in the configuration file and in the system service file, you will need to
open those ports on the firewall. Since we manage this system’s firewall with uncomplicated firewall manager
ufw
, this is easy to do.
sudo ufw allow proto tcp from 192.168.1.0/24 to any port 32765:32768
# You should only have to configure ports for the TCP protocol, but you can open them for the UDP protocol
# just in case.
sudo ufw allow proto udp from 192.168.1.0/24 to any port 32765:32768
Nearly ever tutorial out there suggests one take the extra precautionary measure of setting up what is referred to as “shares” or as “pseudo file system mount points”, whatever they are called, they are the same thing. These mount points are used to prevent malicious users from acquiring access to parts of the system they are not supposed to have access to. Which is because NFS is run by the root user, and therefore can be exploited. (Basically not time to explain.)
In order to configure this feature, you will need to modify the configuration file created earlier, adding the
option for exports
to designate the rootdir for provisioning. You will want to place this option above the
[mountd]
section. So your configuration file should now look like so:
[lockd]
port=32768
udp-port=32768
# Place new lines for provisioning below.
[exports] # <-- Here
rootdir=/var/nfs # <-- And here.
[mountd]
udp=no
port=32767
[nfsd]
udp=n
tcp=y
vers2=n
vers3=y
vers4=n
vers4.0=n
vers4.1=n
vers4.2=n
[statd]
port=32765
outgoing-port=32766
Since this involves tinkering with drives that are already mounted AND currently busy being used by the nfs service, it is good idea to stop the rpcbind and nfs-service.
sudo systemctl stop rpcbind.socket
sudo systemctl stop rpcbind.service
sudo systemctl stop nfs-server.service
We will restart both services when we have completed configuration.
Create the needed directories, change ownership of that tree, and perform a mount.
sudo mkdir -p /var/nfs
# You can create two directories at once with brackets.
sudo mkdir -p /var/nfs/{mount1,mount2}
sudo chown -R nobody:nobody /var/nfs
sudo mount --bind /path/to/mount1 /var/nfs/mount1
sudo mount --bind /path/to/mount2 /var/nfs/mount2
Check to see that everything worked with sudo df -ah
.
Open up /etc/fstab
and add the mount points to the file. Like so:
/path/to/mount1 /var/nfs/mount1 none bind
/path/to/mount2 /var/nfs/mount2 none bind
/etc/exports
Now, you will need to modify the /etc/exports
file to reflect these new mount points. The key difference is
now that you have set rootdir=/var/nfs
, as far as rpcbind and nfs-server are concerned, /var/nfs
is now
the root of your filesystem. So, you only need to add the path after /var/nfs
.
/mount1 10.0.0.1/255.255.255.255(sync,wdelay,crossmnt,no_subtree_check,sec=sys,rw,insecure,no_root_squash,no_all_squash)
/mount2 10.0.0.1/255.255.255.255(sync,wdelay,crossmnt,no_subtree_check,sec=sys,rw,insecure,no_root_squash,no_all_squash)
Restart both rpcbind and nfs-server on the host.
sudo systemctl start rpcbind.service
sudo systemctl start nfs-server.service
Check that everything is running on your host machine with sudo showmount -e
This is where things get a little sticky, because it is time for you to test your mounts on your client system. The actual commands to do so, will vary depending on what system that is. Regardless, the key is to make sure you designate the “tcp only” option. On OpenBSD, the command will look like so:
sudo mount_nfs -T3 -o nodev,nosuid,rw,soft,intr 10.0.0.1:/mount1 /mnt/mount1
The -T3
flag instructs the system to mount using TCP and with version 3 only.
You can check to ensure you are running the desired versions of nfs like so in linux:
cat /proc/fs/nfsd/versions
Personally, I do not do this for my desktop environment. I haven’t quite invested the time into discovering
what exactly the hangup was about, but I have had the system hang while executing the sync operation on the
NFS attached drive directly before performing a reboot several times. Everytime this occurred, my drive was
marked as having been unmounted dirty, so the long thirty minute filesystem check was required once booted up
again. This occurred enough to where finally the line mounting the drive was removed from /etc/fstab
, and
a script was written to easily and manually mount the drive instead. This seems to have worked better for my
situation.
Once everything is up and running, you probably do not want to mount the nfs volume manually each time. So, you can set up fstab to mount the NFS volume automatically on boot with the rest of the filesystem.
host_ip:/var/nfs/general /nfs/general nfs auto,nofail,noatime,nolock,intr,tcp,actimeo=1800 0 0
host_ip:/home /nfs/home nfs auto,nofail,noatime,nolock,intr,tcp,actimeo=1800 0 0