Set Up NFS Server in 5 Minutes (Quick Start)
I run NFS on a Fedora server to share the /data directory with a dev team of about six people, who mount it from their local machines every morning. The initial setup only takes a few commands:
# Install NFS server
sudo dnf install nfs-utils -y
# Create the shared directory
sudo mkdir -p /srv/nfs/shared
sudo chmod 755 /srv/nfs/shared
# Declare exports
echo "/srv/nfs/shared 192.168.1.0/24(rw,sync,no_subtree_check)" | sudo tee -a /etc/exports
# Start and enable the service
sudo systemctl enable --now nfs-server
# Reload exports
sudo exportfs -ra
If you’re testing on a trusted local network, go ahead and try mounting from a client right away to see if the connection works. But on a default Fedora system — where SELinux is Enforcing and firewalld are both enabled out of the box — skipping the next two sections will almost certainly leave you debugging for hours with the mount still failing.
Step-by-Step Breakdown
1. How NFS Works
After installation, you have three core daemons: rpc.nfsd accepts and handles connections from clients, rpc.mountd manages mount requests, and rpcbind acts as the port mapper between them. Check the status right after starting:
sudo systemctl status nfs-server
sudo showmount -e localhost # view the current list of exports
2. /etc/exports Syntax
The /etc/exports file is where you declare which directories to share, which hosts can access them, and with what permissions. A few real-world examples:
# Share read-write with the entire subnet
/srv/nfs/shared 192.168.1.0/24(rw,sync,no_subtree_check)
# Share read-only with a specific machine
/srv/nfs/docs 192.168.1.100(ro,sync)
# Share with multiple hosts, different permissions
/srv/nfs/public 192.168.1.0/24(rw,sync) 10.0.0.5(ro,sync)
Key options worth knowing:
rw/ro: read-write or read-onlysync: write to disk before replying to the client — safer thanasyncno_subtree_check: disables subtree checking, reduces errors when files are renamed while a client has them openall_squash: maps all UID/GID tonfsnobody— useful when you don’t want client users to have real permissionsno_root_squash: root on the client equals root on the server; only use this when truly necessary and with a clear understanding of the risks
After every edit to this file, reload with:
sudo exportfs -ra
sudo exportfs -v # view exports with their active options
3. Configuring firewalld
This is the most commonly skipped step. NFS needs more services opened than you might expect — not just port 2049:
# Open the required services for NFS
sudo firewall-cmd --permanent --add-service=nfs
sudo firewall-cmd --permanent --add-service=rpc-bind
sudo firewall-cmd --permanent --add-service=mountd
sudo firewall-cmd --reload
# Confirm
sudo firewall-cmd --list-services
If you want to restrict access to just the internal subnet rather than opening everything, use the internal zone:
sudo firewall-cmd --permanent --zone=internal --add-service=nfs
sudo firewall-cmd --permanent --zone=internal --add-service=rpc-bind
sudo firewall-cmd --permanent --zone=internal --add-service=mountd
sudo firewall-cmd --permanent --zone=internal --add-source=192.168.1.0/24
sudo firewall-cmd --reload
4. SELinux — It’s Not as Hard as You Think
I used to habitually run setenforce 0 to disable SELinux and move on quickly. After reading about several production server breaches caused by disabled security defaults, I dropped that habit entirely. For NFS, you just need to enable the right booleans:
# View all NFS-related booleans
getsebool -a | grep nfs
# Allow read-write and read-only exports
sudo setsebool -P nfs_export_all_rw 1
sudo setsebool -P nfs_export_all_ro 1
# If clients mount NFS as a home directory
sudo setsebool -P use_nfs_home_dirs 1
If your shared directory is not under /srv/nfs (for example, you’re using /data/shared), you need to assign the correct SELinux context:
# Assign the NFS context to a custom directory
sudo semanage fcontext -a -t nfs_t "/data/shared(/.*)?"
sudo restorecon -Rv /data/shared
# Verify the context is correct
ls -lZ /data/shared
When you get a “Permission denied” error despite correct firewall configuration, this is the first command I run:
sudo ausearch -m avc -ts recent | tail -30
Advanced: Fixing Ports and NFS v4
Fixing Ports for Stable Firewall Rules
By default, rpc.mountd and nlockmgr use dynamic ports — they change after every restart, which breaks firewall rules after a reboot. Pin them in /etc/nfs.conf:
sudo nano /etc/nfs.conf
[mountd]
port=892
[lockd]
port=32803
udp-port=32769
[statd]
port=662
Open these ports in the firewall and restart:
sudo firewall-cmd --permanent --add-port=892/tcp
sudo firewall-cmd --permanent --add-port=892/udp
sudo firewall-cmd --permanent --add-port=32803/tcp
sudo firewall-cmd --permanent --add-port=32769/udp
sudo firewall-cmd --permanent --add-port=662/tcp
sudo firewall-cmd --permanent --add-port=662/udp
sudo firewall-cmd --reload
sudo systemctl restart nfs-server
Mounting from a Client
# Install client tools on the client machine
sudo dnf install nfs-utils -y
# Test manual mount
sudo mount -t nfs 192.168.1.10:/srv/nfs/shared /mnt/test
df -h /mnt/test
ls -la /mnt/test
# Unmount after testing
sudo umount /mnt/test
To mount automatically at boot, add an entry to /etc/fstab:
192.168.1.10:/srv/nfs/shared /mnt/shared nfs defaults,_netdev 0 0
The _netdev option matters more than you’d think — it tells systemd to wait for the network to be ready before attempting the mount. Without it, the client machine may hang at boot if the NFS server hasn’t come up yet.
Practical Tips After 6 Months in Production
Monitor connected clients:
sudo showmount -a # list currently mounted clients
sudo nfsstat -s # server statistics
sudo nfsstat -c # client statistics (run on the client machine)
Handling UID/GID mismatch — this comes up more often than you’d expect: the user on the server and client have different UIDs, so the mount succeeds but you still get permission denied with no obvious reason:
# Check the UID of the current user
id username
# Solution: map everyone to a fixed UID/GID
/srv/nfs/shared 192.168.1.0/24(rw,sync,all_squash,anonuid=1000,anongid=1000)
Use NFS v4.2 to get the latest features (sparse file support, server-side copy, improved security):
sudo mount -t nfs -o vers=4.2 192.168.1.10:/srv/nfs/shared /mnt/shared
# Confirm the version in use
cat /proc/mounts | grep nfs
Back up exports before experimenting:
sudo cp /etc/exports /etc/exports.bak.$(date +%Y%m%d)
Check which NFS versions the server supports:
cat /proc/fs/nfsd/versions
# Output: +2 +3 +4 +4.1 +4.2
# Disable NFS v2 if not needed (reduces attack surface)
echo "-2" | sudo tee /proc/fs/nfsd/versions
I’ve been using Fedora as my primary development machine for two years and I’m quite happy with its package update cadence. NFS on Fedora looks more complex than on other distros because of SELinux and firewalld. But that’s precisely why this setup is more robust — two layers of default protection that many distros simply don’t have. Spending an extra 20 minutes configuring things correctly upfront will save you many hours of debugging down the road.
