Linux network filesystems: NFS & SMB/CIFS
NFS and SMB are the two dominant network filesystem protocols on Linux. NFS is native to Unix and optimized for Linux-to-Linux sharing; SMB (via Samba) is the standard for interoperability with Windows and Active Directory environments.
NFS versions
| Version | State | Ports | Key features |
|---|---|---|---|
| NFSv3 | Stateless | 111 + random | Requires rpcbind, mountd, lockd, statd. Firewall-unfriendly. |
| NFSv4 | Stateful | 2049 only | Integrated locking, ACLs, RPCSEC_GSS/Kerberos mandatory-to-implement (AUTH_SYS still permitted), compound operations. |
| NFSv4.1 | Stateful + sessions | 2049 only | pNFS (parallel access), session trunking, exactly-once semantics. |
| NFSv4.2 | Stateful + sessions | 2049 only | Server-side copy, sparse files, IO advise, space reservation. |
NFS server setup
# Debian/Ubuntu
sudo apt install nfs-kernel-server
sudo systemctl enable --now nfs-kernel-server
# RHEL/Fedora
sudo dnf install nfs-utils
sudo systemctl enable --now nfs-server/etc/exports
# Read-write to a subnet, sync, no subtree check
/srv/nfs/share 192.168.1.0/24(rw,sync,no_subtree_check)
# With Kerberos privacy (encryption)
/home 10.0.0.0/16(rw,sec=krb5p)
# Multiple security flavors (preferred first)
/usr 10.0.0.0/16(rw,sec=krb5p:krb5i:krb5:sys)
# Read-only public
/srv/public *(ro,sync,no_subtree_check)
# All users squashed to anonymous
/srv/guest 192.168.1.0/24(ro,all_squash,anonuid=65534,anongid=65534)Export options
| Option | Effect |
|---|---|
rw / ro | Read-write / read-only |
sync / async | Reply after commit / reply before commit (faster, unsafe) |
no_subtree_check | Disable subtree checking (recommended for reliability) |
root_squash (default) | Map remote root (UID 0) to anonymous user |
no_root_squash | Remote root acts as root on server (security risk) |
all_squash | Map all users to anonymous |
sec=sys | AUTH_SYS, UID/GID based (insecure, default) |
sec=krb5 | Kerberos authentication only |
sec=krb5i | Kerberos + integrity (signed packets) |
sec=krb5p | Kerberos + privacy (encrypted) |
Applying exports
# Export all entries
sudo exportfs -a
# Re-export after editing /etc/exports
sudo exportfs -ra
# Display current exports
sudo exportfs -vNFS client setup
# Debian/Ubuntu
sudo apt install nfs-common
# RHEL/Fedora
sudo dnf install nfs-utils
# Manual mount (NFSv4.2)
sudo mount -t nfs -o vers=4.2,hard,rsize=1048576,wsize=1048576 \
server:/share /mnt/nfs
# /etc/fstab
server:/share /mnt/nfs nfs _netdev,vers=4.2,hard,rsize=1048576,wsize=1048576 0 0Key mount options
| Option | Effect |
|---|---|
hard (recommended) | Retry indefinitely until server responds |
soft | Return error after retrans attempts (data loss risk) |
rsize / wsize | Max read/write transfer size (NFSv4.2 default 1 MB) |
timeo=600 | Initial timeout in tenths of seconds (60s default) |
retrans=2 | Retransmissions before giving up (soft only) |
nconnect=N | Use N TCP connections (NFSv4.1+, max 16) |
_netdev | Wait for network before mounting |
autofs (on-demand mounting)
# /etc/auto.master
/mnt /etc/auto.nfs --timeout=60
# /etc/auto.nfs
share -rw,hard,rsize=1048576,wsize=1048576 server:/srv/nfs/share
sudo systemctl enable --now autofsNFS security
With sec=sys (the default), the client sends UID/GID in cleartext and the server trusts them. Any root user on any client can claim to be any user. Use Kerberos (sec=krb5p) or wrap NFS in a VPN.
NFS over WireGuard (modern alternative to Kerberos)
# Server: listen only on WireGuard interface
# /etc/nfs.conf:
[nfsd]
host = 10.0.0.1
# Export to WireGuard subnet only
/srv/data 10.0.0.0/24(rw,sync,no_subtree_check,sec=sys)
# Client: mount via WireGuard IP
sudo mount -t nfs 10.0.0.1:/srv/data /mnt/dataWireGuard provides network-layer encryption and authentication without the complexity of Kerberos. Tailscale works similarly with MagicDNS.
NFS and firewalls
NFSv4 uses a single TCP port (2049), firewall configuration is trivial:
# firewalld
sudo firewall-cmd --permanent --add-service=nfs
sudo firewall-cmd --reload
# iptables
sudo iptables -A INPUT -p tcp --dport 2049 -j ACCEPTNFSv3 requires rpcbind (port 111) plus random ports for mountd, lockd, statd. Configure static ports in /etc/nfs.conf and open them all.
NFS performance tuning
# Max transfer sizes (NFSv4.2 supports 1 MB)
rsize=1048576,wsize=1048576
# Multiple connections (NFSv4.1+)
nconnect=4
# Aggressive attribute caching (single-client workloads)
actimeo=600
# Disable close-to-open consistency (single-client)
noctoSMB protocol versions
| Version | Introduced | Key features |
|---|---|---|
| SMB1 (CIFS) | - | Deprecated. Disable it. No encryption, vulnerable to WannaCry/NotPetya. |
| SMB2 | Vista/2008 | Reduced chattiness, pipelining |
| SMB3 | Win 8/2012 | Encryption, Multichannel, Direct (RDMA), Transparent Failover |
| SMB 3.1.1 | Win 10/2016 | AES-128-GCM/CCM, pre-auth integrity, SMB over QUIC |
Samba server setup
# Debian/Ubuntu
sudo apt install samba
# RHEL/Fedora
sudo dnf install samba
sudo systemctl enable --now smb nmb/etc/samba/smb.conf
[global]
workgroup = WORKGROUP
security = user
server min protocol = SMB2_02
server max protocol = SMB3
smb encrypt = desired
server multi channel support = yes
# socket options: leave unset on modern kernels, OS self-tunes better
[homes]
browseable = no
read only = no
create mask = 0700
[data]
path = /srv/samba/data
browseable = yes
read only = no
valid users = @smbgroup
create mask = 0660
directory mask = 0770Validate and add users
# Validate configuration
sudo testparm
# Add a Samba user (must exist as system user)
sudo smbpasswd -a username
# Restart
sudo systemctl restart smbd nmbSMB client setup
# Install
sudo apt install cifs-utils # Debian/Ubuntu
sudo dnf install cifs-utils # RHEL/Fedora
# Manual mount
sudo mount -t cifs //server/share /mnt/smb \
-o credentials=/etc/smbcredentials,uid=1000,gid=1000,vers=3.0
# Credentials file (/etc/smbcredentials, chmod 600)
username=user
password=secret
domain=WORKGROUP
# /etc/fstab
//server/share /mnt/smb cifs \
credentials=/etc/smbcredentials,uid=1000,gid=1000,vers=3.0,_netdev 0 0SMB security
Encryption
# Server-side (smb.conf)
[global]
smb encrypt = desired # use if client supports
# or per-share:
smb encrypt = required # reject non-encrypting clients
# Client-side
sudo mount -t cifs //server/share /mnt/smb \
-o credentials=/etc/smbcredentials,seal,vers=3.0Active Directory integration
# Install
sudo dnf install realmd sssd adcli samba-common
# Discover and join
sudo realm discover ad.example.com
sudo realm join --user=administrator ad.example.com
# Allow domain users
sudo realm permit --all ad.example.comNFS vs SMB comparison
| Feature | NFS | SMB |
|---|---|---|
| Native Linux | Yes | Via Samba |
| Native Windows | Via Services for NFS | Yes |
| Encryption | Kerberos (krb5p) or VPN | Built-in (SMB3) |
| Authentication | UID/GID or Kerberos | User-based (AD or local) |
| Parallel access | pNFS (v4.1+) | SMB Multichannel |
| Printer sharing | No | Yes |
| Single port | Yes (v4: 2049) | No (445 + 139) |
| Best for | Linux-to-Linux | Mixed Windows/Linux, AD environments |
Debugging
# NFS statistics
nfsstat -s # server stats
nfsstat -c # client stats
nfsstat -m # mount info
# Common NFS errors:
# ESTALE (116), stale file handle: unmount and remount
# EIO (5) , I/O error: check server disk health
# EACCES (13) , permission denied: check UID/GID mapping / exports
# ETIMEDOUT , increase timeo or check network