Environment
This guide configures an NFSv4.1 and NFSv4.2 server on Ubuntu 24.04 LTS. The example uses:
- NFS server:
nfs-server.example.com - Trusted client network:
192.168.2.0/24 - Server directory:
/srv/nfs/share - NFSv4 client path:
/share - Client mount point:
/mnt/nfs-share - Shared group:
nfsshare, numeric GID2000
Replace the hostnames, subnet, paths, and GID with values appropriate for your network. Reserve the selected GID in your identity-management system so it is not assigned to another group.
NFS with the default sec=sys mode trusts numeric user and group IDs supplied by the client. It does not encrypt file traffic and is suitable only for trusted clients on a private network or VPN. Use NFS with Kerberos and sec=krb5p when clients require strong authentication and encrypted traffic.
Install the NFS Server
Update the package index and install the server package:
sudo apt update
sudo apt install -y nfs-kernel-server
Enable and start the service:
sudo systemctl enable --now nfs-kernel-server.service
sudo systemctl status nfs-kernel-server.service --no-pager
Enable NFSv4.1 and NFSv4.2 Only
Ubuntu 22.04 and later use /etc/nfs.conf and optional snippets under /etc/nfs.conf.d. Create a local override:
sudo install -d -m 0755 /etc/nfs.conf.d
sudoedit /etc/nfs.conf.d/local.conf
Add:
[nfsd]
vers3=n
vers4=y
vers4.0=n
vers4.1=y
vers4.2=y
This configuration removes the NFSv3 dependency on the externally reachable rpcbind and mountd protocols. NFSv4 uses TCP port 2049 for normal client access.
Restart the server and check the enabled protocol versions:
sudo systemctl restart nfs-kernel-server.service
sudo cat /proc/fs/nfsd/versions
The output should show NFSv3 and NFSv4.0 disabled and NFSv4.1 and NFSv4.2 enabled, similar to -3 +4 -4.0 +4.1 +4.2.
Display the effective non-default NFS configuration when troubleshooting:
sudo nfsconf --dump
Create the Shared Directory
Create a group with a fixed GID. The same numeric GID will be configured on every Linux client:
sudo groupadd --gid 2000 nfsshare
If the group already exists, verify its GID instead of creating it again:
getent group nfsshare
Create the NFSv4 pseudo-root and the writable share:
sudo install -d -o root -g root -m 0755 /srv/nfs
sudo install -d -o root -g nfsshare -m 2770 /srv/nfs/share
The set-group-ID bit in mode 2770 makes new files and directories inherit the nfsshare group. Local server accounts that need write access can also be added to this group.
Configure the Exports
Open the export table:
sudoedit /etc/exports
Add these two lines:
/srv/nfs 192.168.2.0/24(ro,fsid=0,sync,no_subtree_check,root_squash)
/srv/nfs/share 192.168.2.0/24(rw,sync,no_subtree_check,root_squash)
The first line defines the NFSv4 root. The second exports the writable directory as /share to clients.
rwpermits writes to the shared directory.synccommits changes to stable storage before the server replies.no_subtree_checkavoids subtree verification problems when files are renamed.root_squashmaps client root requests to the anonymous identity and is enabled by default; specifying it documents the intended security behavior.fsid=0marks the distinguished NFSv4 root.
Do not add no_root_squash for a general file share. It lets a client administrator act as server root on the exported filesystem and can permit modification of root-owned files.
Check the syntax, apply the configuration, and display the active exports:
sudo exportfs -rav
sudo exportfs -v
showmount -e queries the older mount protocol and is not a reliable way to inspect an NFSv4-only server. Use exportfs -v on the server and perform a real NFSv4 mount from a client.
Restrict the Firewall
If UFW is active, allow TCP 2049 only from the trusted client network:
sudo ufw allow from 192.168.2.0/24 to any port 2049 proto tcp comment 'NFSv4 trusted clients'
sudo ufw status verbose
Do not expose NFS directly to the public internet. Apply an equivalent source-restricted rule on upstream routers, cloud security groups, and other host firewalls.
Configure an Ubuntu Client
Install the client utilities:
sudo apt update
sudo apt install -y nfs-common
Create the same group with the same numeric GID, then add the current user:
sudo groupadd --gid 2000 nfsshare
sudo usermod --append --groups nfsshare "$USER"
If the group already exists, verify that it uses GID 2000. Sign out and back in after changing group membership, then confirm it with:
id
Create an empty mount point:
sudo install -d -o root -g root -m 0755 /mnt/nfs-share
Test an NFSv4.2 mount:
sudo mount -t nfs4 -o vers=4.2,proto=tcp nfs-server.example.com:/share /mnt/nfs-share
Verify the source, protocol version, and negotiated options:
findmnt --target /mnt/nfs-share
nfsstat -m
Test access as a user who belongs to nfsshare:
touch /mnt/nfs-share/client-write-test
ls -ln /mnt/nfs-share/client-write-test
rm /mnt/nfs-share/client-write-test
If the client kernel cannot negotiate NFSv4.2, investigate and update the client rather than silently downgrading an environment intended to require NFSv4.1 or later.
Configure a Persistent Mount
Back up the mount table before editing it:
sudo cp --preserve=all /etc/fstab /etc/fstab.before-nfs
sudoedit /etc/fstab
Add one line:
nfs-server.example.com:/share /mnt/nfs-share nfs4 rw,hard,_netdev,nofail,x-systemd.automount,vers=4.2,proto=tcp 0 0
hard keeps retrying an interrupted NFS request so applications do not silently receive partial I/O failures. _netdev identifies a network filesystem, nofail permits boot to continue when the server is unavailable, and x-systemd.automount connects when the path is first accessed.
Reload the generated systemd units, validate the file, and trigger the automount:
sudo systemctl daemon-reload
sudo mount -a
ls /mnt/nfs-share
findmnt --target /mnt/nfs-share
Do not copy old examples that use nolock, intr, or a large actimeo value without a specific requirement. nolock is associated with older NFS behavior, intr is ignored by modern Linux kernels, and long attribute-cache periods can make file changes appear stale.
Windows Clients
The built-in Client for NFS in current Windows desktop releases supports NFSv2 and NFSv3, not NFSv4.1 or NFSv4.2. It therefore cannot mount the NFSv4-only export configured in this guide. Microsoft documents the version limits in its NFS overview.
Use SMB for a share that must support normal Windows clients, or deploy a separately evaluated NFSv4-capable Windows client. Do not weaken this server to NFSv3 only to accommodate one desktop without also assessing the extra RPC services, firewall ports, identity mapping, and security implications.
Troubleshooting
The Export Configuration Is Rejected
Reapply the table in verbose mode and inspect the server journal:
sudo exportfs -rav
sudo journalctl -u nfs-kernel-server.service -b --no-pager
In /etc/exports, there must be no space between a client specification and its option list. For example, 192.168.2.0/24(rw) is valid, while 192.168.2.0/24 (rw) changes the meaning and can expose the directory with unintended defaults.
The Client Cannot Reach the Server
Confirm name resolution and test TCP 2049:
getent hosts nfs-server.example.com
nc -vz nfs-server.example.com 2049
Install netcat-openbsd if nc is unavailable. Check UFW, upstream firewalls, routing, and whether the client address is inside the subnet allowed by /etc/exports.
The Client Receives Permission Denied
Compare the group IDs and inspect every component of the server path:
getent group nfsshare
id
namei -l /srv/nfs/share
The nfsshare group must use the same numeric GID on the server and client. After adding a user to a supplementary group, start a new login session before testing.
A Mount Is Busy
Identify processes using the mount before unmounting it:
sudo fuser -vm /mnt/nfs-share
sudo umount /mnt/nfs-share
Stop or move the listed processes instead of using a forced unmount during active writes.
Remove the Export
Unmount the share on each client and remove its /etc/fstab entry. On the server, remove the corresponding lines from /etc/exports, then reload the export table:
sudo exportfs -rav
To stop providing NFS entirely:
sudo systemctl disable --now nfs-kernel-server.service