NFS HOWTO: an NFSv4 file server and clients on Linux today

Updated November 2026

NFS lets Linux and Unix machines mount a directory from a server as if it were a local disk. Use NFS version 4 (4.2 on current systems): it needs only TCP port 2049, works through firewalls, and can use Kerberos for real security. This page sets up a server, mounts it on clients, and covers the mistakes that cause most NFS trouble.

The classic Linux NFS-HOWTO (2002, NFSv2/v3 era) is kept by the Linux Documentation Project at tldp.org. The steps below are for current releases as of November 2026.

What changed since NFSv3

Set up the server

# Debian / Ubuntu
sudo apt install nfs-kernel-server
# Fedora / RHEL / Alma / Rocky
sudo dnf install nfs-utils

Create the directory to share. Here members of a projects group may write, and new files inherit the group because of the setgid bit (the leading 2):

sudo groupadd -g 2000 projects
sudo mkdir -p /srv/nfs/projects
sudo chgrp projects /srv/nfs/projects
sudo chmod 2770 /srv/nfs/projects

Add one line per share to /etc/exports. Each line is a path, then one or more clients, each with options in brackets and no space before the bracket:

/srv/nfs/projects   192.168.1.0/24(rw,sync,no_subtree_check)
/srv/nfs/iso        192.168.1.0/24(ro) backup.example.lan(rw,no_root_squash)

Load the exports and start the server (the same unit name, nfs-server, works on both families):

sudo exportfs -ra
sudo exportfs -v
sudo systemctl enable --now nfs-server

exportfs -ra re-reads /etc/exports and any *.exports files in /etc/exports.d/; run it after every change. exportfs -v lists what is actually exported, with all defaults filled in.

Export options you will use
OptionMeaningDefault
rw / roRead-write or read-onlyro
sync / asyncsync commits writes to disk before replying; async is faster but can lose data if the server crashessync
root_squashRequests from root (UID 0) on the client act as an anonymous userOn; no_root_squash turns it off
all_squashMap every user to the anonymous user (anonuid/anongid)Off
no_subtree_checkSkip the subtree check, which causes problems when files are renamedAlready the default; writing it silences a warning
sec=Allowed security flavors, for example sec=krb5psys

Watch the space. /srv/nfs/iso 192.168.1.0/24(ro) gives that network read-only access. /srv/nfs/iso 192.168.1.0/24 (ro), with a space, gives that network the defaults and gives every host in the world read-only access.

Make it NFSv4-only

If no clients need NFSv3, switch it off so that only port 2049 stays open. Red Hat documents this procedure for RHEL 10; Fedora and Debian 13 use the same unit names and the same /usr/sbin/rpc.mountd path. Edit /etc/nfs.conf (or add a file in /etc/nfs.conf.d/):

[nfsd]
vers3=n

Then stop the NFSv3 helpers and tell rpc.mountd not to listen on the network. Create /etc/systemd/system/nfs-mountd.service.d/v4only.conf:

[Service]
ExecStart=
ExecStart=/usr/sbin/rpc.mountd --no-tcp --no-udp
sudo systemctl mask --now rpc-statd.service rpcbind.service rpcbind.socket
sudo systemctl daemon-reload
sudo systemctl restart nfs-mountd nfs-server
cat /proc/fs/nfsd/versions

The last command shows which versions are on, for example -3 +4 +4.1 +4.2.

Firewall

# firewalld, NFSv4 only
sudo firewall-cmd --permanent --add-service=nfs
# firewalld, if you still serve NFSv3
sudo firewall-cmd --permanent --add-service={nfs,rpc-bind,mountd}
sudo firewall-cmd --reload
# ufw (Ubuntu), NFSv4 only
sudo ufw allow from 192.168.1.0/24 to any port 2049 proto tcp

The firewalld commands change the default zone; if that zone faces the Internet, add --zone= with the zone that holds your LAN. NFSv3 also needs the lock and status daemons on fixed ports: set port= under [lockd] and [statd] in /etc/nfs.conf and open those ports as well, as Red Hat's NFSv3 procedure shows.

Mount on a client

# Debian / Ubuntu
sudo apt install nfs-common
# Fedora / RHEL
sudo dnf install nfs-utils

sudo mkdir -p /mnt/projects
sudo mount -t nfs nfs1.example.lan:/srv/nfs/projects /mnt/projects
findmnt -t nfs4
nfsstat -m

findmnt and nfsstat -m show the version and options the client actually negotiated, such as vers=4.2,proto=tcp,hard,sec=sys. Mount by the full path the server exports, as Red Hat’s procedure does.

Mount at boot with fstab and systemd

For a share that should appear when first used, rather than holding up boot, add this line to /etc/fstab:

nfs1.example.lan:/srv/nfs/projects  /mnt/projects  nfs  rw,_netdev,nofail,x-systemd.automount,x-systemd.idle-timeout=10min  0 0
sudo systemctl daemon-reload
sudo systemctl restart remote-fs.target
ls /mnt/projects          # triggers the mount

systemd turns each fstab line into units. x-systemd.automount creates an automount point that mounts on first access; x-systemd.idle-timeout=10min unmounts it again after ten idle minutes; _netdev marks it as needing the network; nofail lets boot continue if the server is down. The autofs package is still available for large map-driven setups, but systemd automount covers most needs.

Keep the default hard mount. Without options, NFS retries forever (hard), so programs wait while a server reboots and then carry on. The nfs(5) manual warns that soft can silently corrupt data; use it only where a quick error matters more than your data.

Users, IDs and permissions

With sec=sys, the server checks permissions using the numeric UID and GID the client sends. User alice must have the same UID on every machine, or she will see other people’s files. Keep accounts in one place (LDAP, FreeIPA or Samba AD, see the LDAP HOWTO) rather than in each /etc/passwd. If files show up owned by nobody, check that the NFSv4 ID-mapping domain (Domain= in /etc/idmapd.conf) matches on server and client.

Because sec=sys trusts the client, anyone with root on an allowed client can act as any user except root. Limit exports to the hosts or subnets that need them, and never export to * with rw.

Kerberos and TLS

For untrusted networks, use Kerberos: export with sec=krb5p and mount with -o sec=krb5p. Each machine needs a host key in /etc/krb5.keytab, the server needs an nfs/ service principal, and the client runs rpc-gssd. A FreeIPA domain sets most of this up for you; RHEL’s file-services guide has a full procedure. In return, the server checks a real Kerberos ticket instead of trusting UIDs, and krb5p encrypts all traffic. Recent kernels and nfs-utils also support NFS over TLS (the tlshd service and the xprtsec=tls mount option), documented for RHEL 10.

Troubleshooting

Sources