| name | nfs-storage |
| description | Configure NFS servers and clients. Implement network file sharing for Linux systems. Use when setting up shared storage. |
| license | MIT |
| metadata | {"author":"devops-skills","version":"1.0"} |
NFS Storage
Configure NFS servers and clients for network file sharing across Linux systems. Covers NFSv4 server setup, export options, client mounting, autofs for on-demand mounts, Kerberos security, performance tuning, and Kubernetes integration.
When to Use
- Sharing directories between multiple Linux servers (web farms, build clusters)
- Providing shared storage for containerized workloads (Kubernetes ReadWriteMany)
- Centralizing home directories or application data across a fleet
- Setting up a development environment with shared project files
- Migrating from local storage to network-attached storage
Prerequisites
- NFS server:
nfs-kernel-server (Debian/Ubuntu) or nfs-utils (RHEL/CentOS)
- NFS client:
nfs-common (Debian/Ubuntu) or nfs-utils (RHEL/CentOS)
- Network connectivity between server and clients (TCP/UDP 2049 for NFSv4)
- Firewall rules allowing NFS traffic
- For NFSv4 Kerberos:
krb5-user and a functioning KDC
NFS Server Setup
Installation
apt update && apt install -y nfs-kernel-server
dnf install -y nfs-utils
systemctl enable --now nfs-server
systemctl status nfs-server
rpcinfo -p | grep nfs
Export Configuration (/etc/exports)
/data 10.0.0.0/24(rw,sync,no_subtree_check,no_root_squash)
/shared *(ro,sync,no_subtree_check)
/home server01.example.com(rw,sync,no_subtree_check)
/home server02.example.com(rw,sync,no_subtree_check)
/var/nfs/projects 10.0.0.0/24(rw,sync,no_subtree_check,root_squash)
/srv/nfs 10.0.0.0/24(rw,sync,fsid=0,crossmnt,no_subtree_check)
/srv/nfs/data 10.0.0.0/24(rw,sync,no_subtree_check,no_root_squash)
/srv/nfs/shared 10.0.0.0/24(ro,sync,no_subtree_check)
Export Options Explained
| Option | Description |
|---|
rw | Read-write access |
ro | Read-only access |
sync | Write data to disk before replying (safe, slower) |
async | Reply before data is written to disk (fast, risk of corruption) |
no_subtree_check | Disable subtree checking (improves reliability) |
root_squash | Map remote root (UID 0) to nobody (default, more secure) |
no_root_squash | Allow remote root to act as root on the server (use cautiously) |
all_squash | Map all remote UIDs/GIDs to nobody |
anonuid=1000 | Map anonymous users to a specific UID |
anongid=1000 | Map anonymous groups to a specific GID |
crossmnt | Allow clients to traverse into sub-mounts |
fsid=0 | Mark as the NFSv4 pseudo-root |
Applying Export Changes
exportfs -ra
exportfs -v
exportfs -o rw,sync,no_subtree_check 10.0.0.0/24:/tmp/share
exportfs -u 10.0.0.0/24:/tmp/share
Server Firewall Configuration
ufw allow from 10.0.0.0/24 to any port nfs
ufw allow from 10.0.0.0/24 to any port 111
firewall-cmd --permanent --add-service=nfs
firewall-cmd --permanent --add-service=rpc-bind
firewall-cmd --permanent --add-service=mountd
firewall-cmd --reload
firewall-cmd --permanent --add-port=2049/tcp
firewall-cmd --reload
NFS Client Configuration
Manual Mounting
apt install -y nfs-common
dnf install -y nfs-utils
showmount -e nfs-server.example.com
mkdir -p /mnt/data
mount -t nfs nfs-server.example.com:/data /mnt/data
mount -t nfs -o vers=4.2,tcp,hard,intr nfs-server.example.com:/data /mnt/data
mount | grep nfs
df -hT /mnt/data
umount /mnt/data
Persistent Mounts via /etc/fstab
nfs-server.example.com:/data /mnt/data nfs4 defaults,_netdev 0 0
nfs-server.example.com:/data /mnt/data nfs4 hard,intr,rsize=1048576,wsize=1048576,timeo=600,retrans=3,_netdev 0 0
nfs-server.example.com:/shared /mnt/shared nfs4 ro,_netdev 0 0
nfs-server.example.com:/data /mnt/data nfs4 defaults,_netdev,uid=1000,gid=1000 0 0
mount -a
mount --fake -a -v
Mount Options Explained
| Option | Description |
|---|
hard | Retry NFS requests indefinitely (recommended for data integrity) |
soft | Return error after retrans retries (risk of data corruption) |
intr | Allow interruption of hard-mounted NFS requests |
rsize=1048576 | Read buffer size in bytes (1 MB, max for NFSv4) |
wsize=1048576 | Write buffer size in bytes (1 MB) |
timeo=600 | Timeout in tenths of a second (60 seconds) |
retrans=3 | Number of retries before error (soft) or message (hard) |
_netdev | Wait for network before mounting (critical for boot) |
noatime | Do not update access time (improves performance) |
nconnect=8 | Use multiple TCP connections (kernel 5.3+, improves throughput) |
Autofs (On-Demand Mounting)
apt install -y autofs
dnf install -y autofs
/mnt/nfs /etc/auto.nfs --timeout=300
/etc/auto.nfs
# Format: mount-point options location
# Mounts will appear under /mnt/nfs/<mount-point>
data -rw,hard,intr,rsize=1048576,wsize=1048576 nfs-server.example.com:/data
shared -ro,hard,intr nfs-server.example.com:/shared
home -rw,hard,intr nfs-server.example.com:/home/&
# Wildcard: mount any subdirectory from the server automatically
# /etc/auto.master entry: /mnt/nfs /etc/auto.nfs
* -rw,hard,intr nfs-server.example.com:/srv/nfs/&
systemctl enable --now autofs
ls /mnt/nfs/data
systemctl status autofs
automount -v
Performance Tuning
Server-Side Tuning
RPCNFSDCOUNT=32
echo 32 > /proc/fs/nfsd/threads
systemctl restart nfs-server
echo 1048576 > /proc/fs/nfsd/max_block_size
sysctl -w net.core.rmem_max=134217728
sysctl -w net.core.wmem_max=134217728
Client-Side Tuning
mount -t nfs4 -o rsize=1048576,wsize=1048576,noatime nfs-server:/data /mnt/data
mount -t nfs4 -o nconnect=8 nfs-server:/data /mnt/data
nfsstat -c
nfsstat -s
mountstats /mnt/data
dd if=/dev/zero of=/mnt/data/testfile bs=1M count=1024 oflag=direct
dd if=/mnt/data/testfile of=/dev/null bs=1M iflag=direct
rm /mnt/data/testfile
fio --name=nfs-test --directory=/mnt/data --ioengine=libaio --direct=1 \
--rw=randrw --bs=4k --numjobs=4 --size=1G --runtime=60 --group_reporting
Kubernetes NFS Integration
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs
nfs:
server: nfs-server.example.com
path: /data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs
resources:
requests:
storage: 100Gi
helm repo add csi-driver-nfs https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/charts
helm install csi-driver-nfs csi-driver-nfs/csi-driver-nfs --namespace kube-system
Troubleshooting
| Symptom | Diagnostic Command | Common Fix |
|---|
| mount: access denied | showmount -e server, exportfs -v | Check /etc/exports, run exportfs -ra, verify subnet |
| mount hangs | mount -v, check network | Verify firewall allows TCP 2049; use bg mount option |
| Stale file handle | ls /mnt/data returns stale error | Unmount and remount: umount -f /mnt/data && mount -a |
| Permission denied on files | ls -la, check UID mapping | Match UIDs or use all_squash,anonuid=1000,anongid=1000 |
| Slow NFS performance | nfsstat -c, mountstats /mnt/data | Increase rsize/wsize, add nconnect=8, tune NFS threads |
| Autofs not mounting | systemctl status autofs, automount -v | Check /etc/auto.master syntax, verify server is reachable |
| NFSv4 ID mapping wrong | id username on both sides | Ensure matching domain in /etc/idmapd.conf |
| Boot hangs waiting for NFS | Check fstab options | Add _netdev and bg options to fstab entry |
| Docker volume mount fails | docker volume inspect, dmesg | Verify NFS client packages installed on Docker host |
Related Skills
linux-administration -- Server setup and network configuration
block-storage -- Underlying storage for NFS server data directories
performance-tuning -- Kernel and network tuning for NFS throughput
backup-recovery -- Backing up NFS-hosted data
object-storage -- Alternative storage model for cloud-native workloads