NFS Storage Configuration: Complete Server and Client Setup Guide

Network File System (NFS) is one of the most widely used protocols for sharing files across Linux and Unix systems in networked environments. Whether you're building a centralized storage solution, sharing application data across multiple servers, or creating a home lab environment, understanding NFS configuration is essential for modern infrastructure management.

This comprehensive guide covers complete NFS setup—from basic server configuration to advanced security hardening—enabling you to implement robust, performant network storage solutions.

Introduction to NFS

NFS (Network File System) allows remote systems to mount filesystems over a network as if they were local disks. Developed by Sun Microsystems in 1984, NFS has evolved through multiple versions, with NFSv4 being the current standard offering improved performance, security, and features.

Why Use NFS?

NFS provides several advantages for networked storage:

  • Centralized storage: Single source of truth for shared data
  • Transparent access: Mounted filesystems appear local to applications
  • Cross-platform support: Works across Linux, Unix, and other systems
  • Cost-effective: No specialized hardware required
  • Scalable: Supports multiple concurrent clients
  • Simple management: Centralized backup and maintenance

Common NFS Use Cases

  • Home directories: Centralized user home directories across multiple systems
  • Application data sharing: Shared configuration and data files
  • Web content: Shared web root across multiple web servers
  • Media streaming: Centralized media library for streaming services
  • Development environments: Shared code repositories and build artifacts
  • Container storage: Persistent volumes for Kubernetes and Docker
  • Backup storage: Centralized backup destination

NFS Versions Overview

  • NFSv3: Widely supported, stateless protocol, no built-in security
  • NFSv4: Modern standard, stateful, improved security, better performance
  • NFSv4.1: Adds parallel NFS (pNFS) for better scalability
  • NFSv4.2: Latest version with server-side copy and sparse file support

This guide focuses on NFSv4 as the recommended version for new deployments.

Prerequisites

Before configuring NFS, ensure you have:

  • Root or sudo access on both server and client systems
  • Network connectivity between server and clients
  • Firewall rules configured to allow NFS traffic
  • Basic understanding of Linux filesystem concepts
  • Synchronized time across server and clients (critical for NFSv4)
  • Understanding of your network security requirements

System Requirements

NFS Server:

  • Linux distribution with NFS server packages
  • Sufficient storage space for shared directories
  • Static IP address or reliable DNS name
  • Adequate network bandwidth

NFS Client:

  • Linux distribution with NFS client packages
  • Mount point directories
  • Network access to NFS server

Critical Security Warning

WARNING: Improper NFS configuration can expose sensitive data to unauthorized access. Always:

  1. Implement firewall rules to restrict NFS access
  2. Use NFSv4 with Kerberos authentication when possible
  3. Export only necessary directories
  4. Apply appropriate read/write restrictions
  5. Monitor NFS access logs
  6. Keep NFS software updated
  7. Never expose NFS directly to the internet without VPN

Part 1: NFS Server Configuration

Step 1: Install NFS Server Packages

On Debian/Ubuntu

sudo apt update
sudo apt install nfs-kernel-server

On CentOS/RHEL/Rocky Linux

sudo yum install nfs-utils
# or
sudo dnf install nfs-utils

Step 2: Verify NFS Installation

# Check NFS version
sudo nfsstat -v

# Verify NFS service
sudo systemctl status nfs-server

Step 3: Create Shared Directories

Create directories to be shared via NFS:

# Create main shared directory
sudo mkdir -p /srv/nfs/shared

# Create specific purpose directories
sudo mkdir -p /srv/nfs/homes
sudo mkdir -p /srv/nfs/data
sudo mkdir -p /srv/nfs/backups

Step 4: Set Directory Permissions

Configure appropriate permissions:

# Full access for shared directory
sudo chown -R nobody:nogroup /srv/nfs/shared
sudo chmod 777 /srv/nfs/shared

# Or more restrictive
sudo chown -R root:root /srv/nfs/data
sudo chmod 755 /srv/nfs/data

Note: nobody:nogroup (Debian/Ubuntu) or nfsnobody:nfsnobody (RHEL/CentOS) represents unprivileged users.

Step 5: Configure NFS Exports

The /etc/exports file defines which directories are shared and with what permissions.

Basic Export Configuration

Edit exports file:

sudo nano /etc/exports

Add export entries:

# Basic syntax: directory client(options)

# Share to specific IP
/srv/nfs/shared 192.168.1.100(rw,sync,no_subtree_check)

# Share to entire subnet
/srv/nfs/data 192.168.1.0/24(rw,sync,no_subtree_check)

# Share to multiple clients
/srv/nfs/backups 192.168.1.10(rw,sync) 192.168.1.11(rw,sync)

# Read-only share
/srv/nfs/readonly 192.168.1.0/24(ro,sync,no_subtree_check)

# Multiple exports
/srv/nfs/homes 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)

Understanding Export Options

Access Options:

  • rw: Read-write access
  • ro: Read-only access

Synchronization Options:

  • sync: Write operations complete before responding (safer, slower)
  • async: Respond before writes complete (faster, less safe)

ID Mapping Options:

  • root_squash: Map root user to anonymous user (default, secure)
  • no_root_squash: Allow root on client to have root access on server (dangerous)
  • all_squash: Map all users to anonymous user
  • anonuid=X, anongid=Y: Specify UID/GID for anonymous user

Other Important Options:

  • no_subtree_check: Disable subtree checking (improves reliability)
  • fsid=0: Mark as root filesystem for NFSv4
  • crossmnt: Allow crossing mount points
  • secure: Require connections from ports < 1024 (default)
  • insecure: Allow connections from any port

Advanced Export Examples

sudo nano /etc/exports
# NFSv4 root export
/srv/nfs 192.168.1.0/24(rw,sync,fsid=0,crossmnt,no_subtree_check)

# User home directories
/srv/nfs/homes 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)

# Application data
/srv/nfs/app_data 192.168.1.50(rw,sync,no_subtree_check) 192.168.1.51(rw,sync,no_subtree_check)

# Web content (read-only for most, read-write for specific server)
/srv/nfs/www 192.168.1.0/24(ro,sync,no_subtree_check) 192.168.1.20(rw,sync,no_subtree_check)

# Backup storage (read-write for backup server only)
/srv/nfs/backups 192.168.1.30(rw,sync,no_subtree_check,no_root_squash)

# Media library (read-only for media servers)
/srv/nfs/media 192.168.1.0/24(ro,sync,no_subtree_check,all_squash,anonuid=1000,anongid=1000)

Step 6: Apply Export Configuration

After editing /etc/exports, apply the configuration:

sudo exportfs -a

Verify exports:

sudo exportfs -v

Output:

/srv/nfs/shared 192.168.1.0/24(rw,sync,wdelay,hide,no_subtree_check,sec=sys,...)
/srv/nfs/data   192.168.1.0/24(rw,sync,wdelay,hide,no_subtree_check,sec=sys,...)

Step 7: Start and Enable NFS Service

On Debian/Ubuntu

sudo systemctl enable nfs-kernel-server
sudo systemctl start nfs-kernel-server
sudo systemctl status nfs-kernel-server

On CentOS/RHEL/Rocky Linux

sudo systemctl enable nfs-server
sudo systemctl start nfs-server
sudo systemctl status nfs-server

Step 8: Configure Firewall

Allow NFS traffic through the firewall.

Using UFW (Debian/Ubuntu)

# Allow NFS from specific subnet
sudo ufw allow from 192.168.1.0/24 to any port nfs

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

# Reload firewall
sudo ufw reload

Using firewalld (CentOS/RHEL)

# Add NFS service
sudo firewall-cmd --permanent --add-service=nfs
sudo firewall-cmd --permanent --add-service=rpc-bind
sudo firewall-cmd --permanent --add-service=mountd

# Reload firewall
sudo firewall-cmd --reload

# Verify
sudo firewall-cmd --list-all

Using iptables

# Allow NFS
sudo iptables -A INPUT -p tcp --dport 2049 -s 192.168.1.0/24 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 111 -s 192.168.1.0/24 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 111 -s 192.168.1.0/24 -j ACCEPT

# Save rules
sudo iptables-save | sudo tee /etc/iptables/rules.v4

Step 9: Verify NFS Server Configuration

Check NFS server status:

# Show exports
showmount -e localhost

# Check RPC services
rpcinfo -p localhost

# View NFS statistics
nfsstat -s

Expected output for showmount:

Export list for localhost:
/srv/nfs/shared 192.168.1.0/24
/srv/nfs/data   192.168.1.0/24

Part 2: NFS Client Configuration

Step 1: Install NFS Client Packages

On Debian/Ubuntu

sudo apt update
sudo apt install nfs-common

On CentOS/RHEL/Rocky Linux

sudo yum install nfs-utils
# or
sudo dnf install nfs-utils

Step 2: Create Mount Points

# Create mount point directories
sudo mkdir -p /mnt/nfs/shared
sudo mkdir -p /mnt/nfs/data
sudo mkdir -p /mnt/nfs/backups

Step 3: Test NFS Server Accessibility

Verify the NFS server is reachable:

# Check available exports (replace with your NFS server IP)
showmount -e 192.168.1.10

Output:

Export list for 192.168.1.10:
/srv/nfs/shared 192.168.1.0/24
/srv/nfs/data   192.168.1.0/24

Step 4: Mount NFS Share Temporarily

Test mounting before making it permanent:

# Mount NFS share
sudo mount -t nfs 192.168.1.10:/srv/nfs/shared /mnt/nfs/shared

# Verify mount
df -h /mnt/nfs/shared
mount | grep nfs

Output:

192.168.1.10:/srv/nfs/shared on /mnt/nfs/shared type nfs4 (rw,relatime,vers=4.2,...)

Step 5: Test NFS Share

# Create test file
echo "NFS test successful" | sudo tee /mnt/nfs/shared/test.txt

# Read test file
cat /mnt/nfs/shared/test.txt

# Verify from server
# (On NFS server)
cat /srv/nfs/shared/test.txt

Step 6: Unmount NFS Share (if testing)

sudo umount /mnt/nfs/shared

Step 7: Configure Automatic Mounting

Make NFS mounts permanent by adding to /etc/fstab.

Backup fstab

sudo cp /etc/fstab /etc/fstab.backup.$(date +%Y%m%d)

Add NFS Mounts to fstab

sudo nano /etc/fstab

Add entries:

# Basic NFSv4 mount
192.168.1.10:/srv/nfs/shared  /mnt/nfs/shared  nfs4  defaults  0  0

# With specific options
192.168.1.10:/srv/nfs/data  /mnt/nfs/data  nfs4  rw,hard,intr,rsize=8192,wsize=8192,timeo=14  0  0

# With nofail (continues boot if NFS unavailable)
192.168.1.10:/srv/nfs/backups  /mnt/nfs/backups  nfs4  defaults,nofail  0  0

# Read-only mount
192.168.1.10:/srv/nfs/readonly  /mnt/nfs/readonly  nfs4  ro,defaults  0  0

Understanding NFS Mount Options

Common Options:

  • defaults: Use default options
  • rw/ro: Read-write or read-only
  • hard: Keep trying if server unavailable (recommended)
  • soft: Return error after timeout (can cause data corruption)
  • intr: Allow interruption of NFS operations
  • nofail: Continue boot if mount fails
  • _netdev: Wait for network before mounting

Performance Options:

  • rsize=8192: Read buffer size in bytes
  • wsize=8192: Write buffer size in bytes
  • timeo=14: Timeout in tenths of seconds
  • retrans=2: Number of retransmission attempts
  • actimeo=3: Attribute cache timeout

Version Options:

  • nfsvers=4: Force NFSv4 (or nfsvers=3 for NFSv3)
  • vers=4.2: Specify exact NFSv4.2

Step 8: Test fstab Configuration

CRITICAL: Test before rebooting:

# Unmount if currently mounted
sudo umount /mnt/nfs/shared

# Mount all from fstab
sudo mount -a

# Verify
df -h | grep nfs

Step 9: Verify After Reboot

# Reboot to test automatic mounting
sudo reboot

# After reboot, verify mounts
df -h | grep nfs
mount | grep nfs

Performance Optimization

Optimizing NFS Performance

Server-Side Optimization

Edit /etc/default/nfs-kernel-server (Debian/Ubuntu) or /etc/nfs.conf (RHEL/CentOS):

# Increase number of NFS server threads
RPCNFSDCOUNT=16

# Or in /etc/nfs.conf
[nfsd]
threads=16

Restart NFS:

sudo systemctl restart nfs-kernel-server

Client-Side Optimization

Optimal mount options in /etc/fstab:

192.168.1.10:/srv/nfs/data  /mnt/nfs/data  nfs4  rw,hard,intr,rsize=131072,wsize=131072,timeo=600,retrans=2,_netdev  0  0

Options explained:

  • rsize=131072: 128KB read size (adjust based on network)
  • wsize=131072: 128KB write size
  • timeo=600: 60-second timeout
  • retrans=2: Two retransmission attempts

Network Optimization

Enable jumbo frames (if supported):

# On both server and clients
sudo ip link set eth0 mtu 9000

# Make permanent (edit network config)
# For netplan:
sudo nano /etc/netplan/01-netcfg.yaml

# Add under interface:
#   mtu: 9000

Performance Testing

Test NFS Write Performance

# Create 1GB test file
dd if=/dev/zero of=/mnt/nfs/shared/testfile bs=1M count=1024 oflag=direct

Test NFS Read Performance

# Read test file
dd if=/mnt/nfs/shared/testfile of=/dev/null bs=1M

Comprehensive Benchmark

# Install fio
sudo apt install fio

# Run benchmark
fio --name=nfs-test --directory=/mnt/nfs/shared --size=1G \
    --bs=4k --rw=randrw --rwmixread=70 --numjobs=4 --time_based \
    --runtime=60 --group_reporting

Security Hardening

Using NFSv4 with Kerberos

For production environments, use Kerberos authentication.

On NFS Server

# Install Kerberos packages
sudo apt install krb5-user nfs-kernel-server

# Configure Kerberos
sudo nano /etc/krb5.conf

# Add NFS service principal
# (Requires Kerberos KDC setup - beyond scope)

Restricting Access by IP

Limit NFS access to specific IPs in /etc/exports:

# Single IP
/srv/nfs/secure 192.168.1.100(rw,sync,no_subtree_check)

# IP range
/srv/nfs/secure 192.168.1.100-192.168.1.110(rw,sync,no_subtree_check)

# Multiple specific IPs
/srv/nfs/secure 192.168.1.100(rw) 192.168.1.101(rw) 192.168.1.102(rw)

Using Firewall Rules

Implement strict firewall rules:

# Allow only from specific subnet
sudo iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 2049 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 2049 -j DROP

Monitoring NFS Access

Enable logging:

# View NFS statistics
nfsstat

# Monitor NFS connections
sudo netstat -an | grep 2049

# Check NFS logs
sudo journalctl -u nfs-server -f

Troubleshooting Common Issues

Issue: Cannot Mount NFS Share

Cause: Firewall blocking, incorrect exports, or network issues.

Solution:

# Check if server is reachable
ping 192.168.1.10

# Check if NFS port is open
telnet 192.168.1.10 2049

# Check exports from client
showmount -e 192.168.1.10

# Check NFS service on server
sudo systemctl status nfs-server

# Check firewall (on server)
sudo iptables -L -n | grep 2049

Issue: "Permission Denied" Errors

Cause: User ID mismatch or incorrect permissions.

Solution:

# Check directory permissions on server
ls -la /srv/nfs/shared

# Ensure UIDs match between server and client
# On server
id username

# On client
id username

# Fix permissions on server
sudo chown -R nobody:nogroup /srv/nfs/shared
sudo chmod 777 /srv/nfs/shared

# Or use all_squash in exports
# In /etc/exports:
/srv/nfs/shared 192.168.1.0/24(rw,sync,all_squash,anonuid=1000,anongid=1000)

Issue: Stale NFS File Handles

Cause: Server restarted or export configuration changed.

Solution:

# On client, unmount
sudo umount -f /mnt/nfs/shared

# Remount
sudo mount -a

# If still stale, reboot client
sudo reboot

Issue: Slow NFS Performance

Cause: Small buffer sizes, network latency, or server load.

Solution:

# Optimize mount options in /etc/fstab
192.168.1.10:/srv/nfs/data  /mnt/nfs/data  nfs4  rw,hard,intr,rsize=131072,wsize=131072,async  0  0

# Increase server threads (on server)
# Edit /etc/default/nfs-kernel-server
RPCNFSDCOUNT=32

# Restart NFS server
sudo systemctl restart nfs-kernel-server

Issue: "Mount.nfs: access denied by server"

Cause: Client IP not in exports or incorrect export options.

Solution:

# On server, check exports
sudo exportfs -v

# Verify client IP is allowed
# Edit /etc/exports if needed
sudo nano /etc/exports

# Reload exports
sudo exportfs -ra

# Check from client
showmount -e 192.168.1.10

Issue: NFS Not Mounting at Boot

Cause: Network not ready or incorrect fstab options.

Solution:

# Add _netdev option in /etc/fstab
192.168.1.10:/srv/nfs/shared  /mnt/nfs/shared  nfs4  defaults,_netdev,nofail  0  0

# Ensure network is ready before mounting
sudo systemctl enable NetworkManager-wait-online.service

Best Practices

1. Use NFSv4

NFSv4 offers better security and performance:

# Force NFSv4 in /etc/fstab
192.168.1.10:/srv/nfs/shared  /mnt/nfs/shared  nfs4  defaults  0  0

2. Use Root Squashing

Prevent root on client from having root access on server:

# In /etc/exports (root_squash is default)
/srv/nfs/shared 192.168.1.0/24(rw,sync,root_squash)

3. Use Sync Instead of Async

Safer but slightly slower:

# In /etc/exports
/srv/nfs/data 192.168.1.0/24(rw,sync,no_subtree_check)

4. Implement Firewall Rules

Restrict NFS access:

# Allow only from trusted subnet
sudo ufw allow from 192.168.1.0/24 to any port nfs

5. Monitor NFS Performance

Regular monitoring:

# Create monitoring script
cat << 'EOF' | sudo tee /usr/local/bin/nfs_monitor.sh
#!/bin/bash
nfsstat -s | grep -E 'commit|write|read'
EOF

sudo chmod +x /usr/local/bin/nfs_monitor.sh

6. Regular Backups

NFS server data should be backed up:

# Backup NFS shared directories
sudo rsync -avz /srv/nfs/ /backup/nfs_$(date +%Y%m%d)/

7. Use nofail for Non-Critical Mounts

Prevent boot failures:

# In /etc/fstab
192.168.1.10:/srv/nfs/optional  /mnt/optional  nfs4  defaults,nofail  0  0

8. Document NFS Configuration

Maintain documentation:

# Save NFS configuration
sudo cp /etc/exports /root/exports_backup_$(date +%Y%m%d)
sudo exportfs -v > /root/nfs_exports_$(date +%Y%m%d).txt

9. Keep Systems Updated

Regular updates:

# Update NFS packages
sudo apt update && sudo apt upgrade nfs-kernel-server nfs-common

10. Test Disaster Recovery

Regular testing:

# Test server failure scenario
# Test client remounting
# Verify data integrity

Advanced NFS Configurations

Exporting to Multiple Subnets

# In /etc/exports
/srv/nfs/multi 192.168.1.0/24(rw,sync) 10.0.0.0/24(rw,sync)

Using NFSv4 Pseudo-Filesystem

# In /etc/exports
/srv/nfs 192.168.1.0/24(rw,sync,fsid=0,crossmnt,no_subtree_check)
/srv/nfs/dir1 192.168.1.0/24(rw,sync,no_subtree_check)
/srv/nfs/dir2 192.168.1.0/24(rw,sync,no_subtree_check)

# Mount on client (note simplified path)
sudo mount -t nfs4 192.168.1.10:/dir1 /mnt/dir1

NFS with AutoFS

Automatically mount/unmount NFS shares on access:

# Install autofs
sudo apt install autofs

# Configure
sudo nano /etc/auto.master

# Add:
/mnt/auto  /etc/auto.nfs  --timeout=60

# Create auto.nfs
sudo nano /etc/auto.nfs

# Add:
shared  -rw,hard,intr  192.168.1.10:/srv/nfs/shared

# Restart autofs
sudo systemctl restart autofs

# Test (automatically mounts on access)
ls /mnt/auto/shared

Conclusion

NFS provides powerful, flexible network storage capabilities for Linux environments. By properly configuring NFS servers and clients with appropriate security measures and performance optimizations, you can create reliable centralized storage solutions that scale with your infrastructure needs.

Key takeaways:

  1. Use NFSv4 for modern deployments
  2. Implement proper security with firewall rules and root_squash
  3. Optimize performance with appropriate buffer sizes
  4. Use _netdev and nofail in fstab for reliability
  5. Monitor NFS performance and access regularly
  6. Document configurations thoroughly
  7. Test failure scenarios before production deployment
  8. Keep systems updated for security and bug fixes
  9. Backup NFS data regularly
  10. Consider Kerberos for production security

Remember that NFS is best suited for trusted networks. For internet-facing storage or untrusted networks, consider VPN tunneling or alternative solutions like SFTP or cloud object storage.

By following the procedures and best practices in this guide, you can confidently deploy and manage NFS infrastructure that provides reliable, performant network storage for your Linux environment.