The NFS4 exports syntax can be particularly confusing when dealing with multiple exports on a single line. The manpage states that options specified after a dash affect "all subsequent exports on that line only." Here's what that means in practice:
# Affects only /export1 and /export2
/path1 -rw,sync 192.168.1.0/24
/path2 -ro,async 192.168.1.0/24
# Different behavior - options after dash apply to all paths on this line
/path1 /path2 -rw,sync 192.168.1.0/24
The fsid=0 parameter has caused much confusion in NFS4 implementations. While it was crucial in earlier versions, modern NFS4 servers (kernel 3.0+) often don't require it for the root export. However, it's still recommended for:
- Better backward compatibility
- Explicitly marking the root of your NFS export tree
- Preventing potential issues with some client implementations
The ability to mount non-exported directories under an exported parent is actually by design in NFS4. This behavior stems from NFS4's pseudo-filesystem approach where:
# Even though only /exp/distr is exported, clients can access:
/exp/distr/archlinux
/exp/distr/debian
# And potentially /exp/users if permissions allow
To restrict this, you need to either:
- Use the 'no_pseudo' export option
- Implement explicit export restrictions for each subdirectory
- Adjust filesystem permissions accordingly
The rmtab behavior you observed raises valid security concerns. Modern best practices recommend:
# Disable rmtab completely in /etc/nfs.conf:
[mountd]
manage-gids = false
no-nfs-owner = true
# Add this to prevent rmtab updates:
echo "NEED_RMTAB=no" >> /etc/default/nfs-common
For monitoring active mounts, consider these alternatives:
- netstat -an | grep 2049
- ss -tnp | grep nfsd
- Custom scripts parsing /proc/fs/nfsd/clients/*
Here's a recommended exports setup for your scenario:
# /etc/exports
/exp 192.168.1.0/24(fsid=0,rw,async,no_subtree_check,no_root_squash,crossmnt)
/exp/distr 192.168.1.0/24(rw,async,no_subtree_check,no_root_squash,no_pseudo)
/exp/users 192.168.1.0/24(ro,all_squash,anonuid=65534,anongid=65534)
And corresponding fstab entries:
# /etc/fstab
/dev/disk/by-label/users /mnt/users ext4 defaults,nosuid,nodev 0 0
/dev/disk/by-label/distr /mnt/distr ext4 defaults,nosuid,nodev 0 0
/mnt/users /exp/users none bind,nosuid,nodev 0 0
/mnt/distr /exp/distr none bind,nosuid,nodev 0 0
Remember to run exportfs -ra
after changes and verify with exportfs -v
.
For secure client mounting:
# Recommended client mount options:
mount -t nfs4 -o \
rw,hard,noatime,nodiratime,proto=tcp,timeo=600,retrans=2 \
server:/exp/distr /mnt/nfs/distr
Key options explained:
- hard: Critical for data integrity
- noatime/nodiratime: Reduces metadata writes
- proto=tcp: More reliable than UDP
- timeo/retrans: Adjust for your network conditions
The phrase "subsequent exports on that line only" in the exports(5)
manpage refers to how default options (prefixed with '-') apply to multiple exports declared on the same line. For example:
/shared/data -rw,sync client1(rw) client2(ro)
Here, -rw,sync
becomes the default for both client1
and client2
, with each client able to override these defaults.
While older NFS4 implementations required fsid=0
to designate the root of the pseudo-filesystem, modern Linux kernels (since ~2012) handle this automatically. However, including it explicitly doesn't hurt:
/export fsid=0,ro 192.168.1.0/24
The exception is when you need to maintain compatibility with very old clients or special configurations.
Your observation about mounting /exp/users
despite it not being exported stems from NFS4's pseudo-filesystem behavior. When you export /exp
with fsid=0
, clients can traverse to any subdirectory unless explicitly restricted. To prevent this:
/exp 192.168.1.0/24(fsid=0,ro,no_subtree_check)
/exp/distr 192.168.1.0/24(rw)
/exp/users 192.168.1.0/24(noaccess)
The noaccess
option explicitly blocks access while maintaining the directory structure.
The /var/lib/nfs/rmtab
situation presents several issues:
- Disable rmtab entirely by adding
--no-nfs-version 3
to/etc/nfs.conf
under the[nfsd]
section - Regularly clean stale entries with:
echo > /var/lib/nfs/rmtab
- For NFS4-only environments, consider:
mount -t nfs4 -o vers=4 server:/export /mnt
Here's a complete working configuration for secure NFS4 exports:
# /etc/exports
/exported fsid=0,ro,no_subtree_check 192.168.1.0/24
/exported/data rw,no_root_squash 192.168.1.10
/exported/backups ro 192.168.1.20
# /etc/nfs.conf
[nfsd]
debug=0
vers4=y
vers3=n
After modifying these files, restart services:
systemctl restart nfs-server
exportfs -arv