Install on the server

# Debian / Ubuntu
sudo apt install nfs-kernel-server

# Fedora / RHEL
sudo dnf install nfs-utils

# Verify
sudo systemctl status nfs-server

Plan the export filesystem

NFSv4 expects a single virtual filesystem root with exported subdirectories bind-mounted under it. Common convention is to use /srv/nfs as the root:

# Create the root + per-export bind mount points
sudo mkdir -p /srv/nfs/{photos,projects,backup}

# Bind-mount real directories under the NFS root
sudo mount --bind /mnt/data/photos    /srv/nfs/photos
sudo mount --bind /mnt/data/projects  /srv/nfs/projects
sudo mount --bind /mnt/raid/backup    /srv/nfs/backup

# Make persistent in /etc/fstab
cat << 'EOF' | sudo tee -a /etc/fstab
/mnt/data/photos    /srv/nfs/photos    none    bind    0    0
/mnt/data/projects  /srv/nfs/projects  none    bind    0    0
/mnt/raid/backup    /srv/nfs/backup    none    bind    0    0
EOF

Configure exports

Edit /etc/exports:

# The pseudo-root (NFSv4 requirement)
/srv/nfs              192.168.1.0/24(rw,sync,no_subtree_check,fsid=root,crossmnt)

# Each export under the root
/srv/nfs/photos       192.168.1.0/24(rw,sync,no_subtree_check,nohide)
/srv/nfs/projects     192.168.1.0/24(rw,sync,no_subtree_check,nohide,no_root_squash)
/srv/nfs/backup       192.168.1.10(rw,sync,no_subtree_check,nohide)   # backup server only
/srv/nfs/photos       192.168.1.50(ro,sync,no_subtree_check,nohide)   # media VM read-only

Apply:

sudo exportfs -ra        # reload exports
sudo exportfs -v         # show what's currently exported

sudo systemctl restart nfs-server

The options that matter

  • rw / ro — read-write or read-only
  • sync — commit writes before replying; safer, slightly slower. async is faster but data can be lost on server crash
  • no_subtree_check — avoid spurious "stale file handle" errors after renames
  • fsid=root — required on the v4 pseudo-root export
  • crossmnt — allow clients to see subdirectories that are themselves mounted (e.g. bind mounts under the root)
  • nohide — show child exports under the parent (NFSv4 default behavior)
  • no_root_squash — allow remote root to act as root (rare; usually leave the default root_squash)
  • all_squash — map all remote UIDs to anonymous; useful for "shared dump folder" semantics
  • anonuid=1000,anongid=1000 — what UID/GID anonymous maps to

Firewall

NFSv4 only needs TCP port 2049 (no RPC dance like v3). Open it to the trusted LAN:

# nftables (see /tutorials/nftables-modern-linux-firewall.html)
ip saddr 192.168.1.0/24 tcp dport 2049 accept

# Or ufw
sudo ufw allow from 192.168.1.0/24 to any port 2049

# Or firewalld
sudo firewall-cmd --permanent --add-service=nfs
sudo firewall-cmd --reload

Mount on a client

sudo apt install nfs-common

# Manual mount
sudo mkdir -p /mnt/photos
sudo mount -t nfs4 -o noatime,vers=4.2 nas.lab:/photos /mnt/photos

# Verify
df -h /mnt/photos
ls /mnt/photos

Note: with NFSv4 the path is relative to the pseudo-root — not /srv/nfs/photos but just /photos.

Persistent mount via /etc/fstab

# /etc/fstab
nas.lab:/photos    /mnt/photos    nfs4    noauto,x-systemd.automount,noatime,vers=4.2,_netdev    0    0

noauto + x-systemd.automount = lazy mount only when accessed; less hassle if the NFS server isn't up at boot. _netdev tells systemd to wait for the network before trying.

Per-mount tuning options

# Read-ahead size + reasonable timeouts
sudo mount -t nfs4 nas.lab:/photos /mnt/photos \
    -o noatime,vers=4.2,rsize=131072,wsize=131072,timeo=600,retrans=2,hard,intr

# rsize/wsize 128KB (or larger on 10 GbE): faster bulk transfer
# timeo=600: 60 second timeout per request (in tenths of a second)
# hard: keep retrying on timeout (vs soft, which fails the I/O)
# intr: allow Ctrl-C to interrupt stuck I/O (legacy; modern kernel ignores)

UID / GID mapping

NFS by default uses numeric UIDs/GIDs. If amir is UID 1000 on the server but UID 1001 on the client, file ownership gets confused.

Three strategies:

  1. Match UIDs across hosts. Simplest for homelab; pick one UID/GID per user and use it everywhere.
  2. idmapd / NFSv4 ID mapping. Both sides agree on a domain; UIDs are mapped via user@domain. Less common in practice.
  3. all_squash with anonuid. Treat the whole export as anonymous; useful for shared / dump folders.

Kerberos auth (krb5p)

For environments needing real authentication + encryption, NFSv4 supports Kerberos:

# Export with Kerberos privacy (encrypt + auth)
/srv/nfs/sensitive  *(rw,sync,sec=krb5p,no_subtree_check)

# Client mount
sudo mount -t nfs4 -o sec=krb5p,vers=4.2 server:/sensitive /mnt/sensitive

Requires a working Kerberos KDC (FreeIPA, Active Directory, or standalone MIT/Heimdal). For most homelab use, sec=sys (default UID-based) on a trusted LAN is fine; Kerberos is for "I can't trust the LAN to be clean."

NFSv4.2 features worth knowing

  • Server-side copycp between two paths on the same NFS server doesn't round-trip data through the client.
  • Sparse files — correctly preserve holes (no longer dense-allocated on copy).
  • Application data blockfallocate works correctly over NFS.
  • POSIX ACLssetfacl / getfacl work transparently.

Always mount with vers=4.2 on modern clients + servers; gives you the full feature set.

Debugging

# Check exports on server
sudo exportfs -v
sudo cat /proc/fs/nfsd/exports

# Check who's mounted from the server
sudo showmount -a nas.lab           # may not work for v4-only; use rpcinfo

# Server-side stats
nfsstat -s

# Client-side stats
nfsstat -c

# Force unmount a stuck NFS mount (last resort)
sudo umount -l /mnt/photos          # lazy unmount
# Or
sudo umount -f /mnt/photos          # force

NFSv4 vs alternatives

  • Samba / SMB — the right pick for Windows / macOS clients. Linux can mount SMB too, but for Unix-to-Unix, NFS is faster + simpler.
  • SSHFS — FUSE over SSH; great for ad-hoc remote mounts; slower than NFS; doesn't scale to dozens of mounts.
  • iSCSI (see that tutorial) — block storage; one writer per LUN. Different shape.
  • CephFS (see that tutorial) — distributed POSIX filesystem; more redundancy, much more setup.

For "one NAS exporting directories to N Linux clients," NFSv4 is the simplest right answer in 2026.