Red Hat Enterprise Linux and Oracle Linux NFS Server Configuration and Management

General Description of an NFS Server

Network File System (NFS) lets a Red Hat Enterprise Linux or Oracle Linux server export directory hierarchies to remote clients. Clients mount the exported path and use ordinary file operations, while the server applies host export policy, NFS credentials, root squashing, local UNIX permissions and ACLs, SELinux policy, quotas, locking, recovery, and storage semantics.

The server stack combines kernel nfsd threads with nfs-utils programs, systemd units, /etc/exports, /etc/nfs.conf, firewalld or nftables, SELinux, optional Identity Management and Kerberos components, and optional TLS support on current releases. A healthy nfs-server unit does not prove that a client is authorised or that an application identity can write.

This guide is the companion server section for the Red Hat Enterprise Linux and Oracle Linux networking guide. It focuses on RHEL 8, 9, and 10 and Oracle Linux 8, 9, and 10. The common baseline is nfs-utils, systemd, firewalld, and SELinux; advanced functions are marked where their release support differs.

Typical server tasks include:

  • Installing nfs-utils and managing nfs-server and auxiliary RPC services.
  • Preparing XFS or ext-family storage, ownership, ACLs, quotas, and stable mount points.
  • Defining exports in /etc/exports or /etc/exports.d/*.exports and applying them with exportfs.
  • Selecting NFSv4-only service or supporting NFSv3 with fixed RPC ports.
  • Opening only the required firewalld services and source networks.
  • Maintaining SELinux enforcement and resolving AVC denials without disabling policy.
  • Using consistent numeric identities or Kerberos through IdM for stronger authentication.
  • Configuring NFS over TLS where the installed RHEL or Oracle Linux release supports it.
  • Monitoring clients, RPC operations, storage latency, network health, and security logs.

Safety, Version Scope, Conventions, and Example Values

Warning: An export, SELinux, firewall, storage, or protocol-version change can interrupt applications immediately. Keep console or out-of-band access, back up configuration, preserve a rollback, and coordinate with client owners. Do not disable SELinux or firewalld merely to make a test succeed.

Command prompts:

$ command       # Run as an ordinary user
# command       # Run as root, or prefix the command with sudo

Documentation-only example values:

Purpose

Example

NFS service name and address

nfs01.example.com / 192.0.2.10

Authorised IPv4 network

192.0.2.0/24

Authorised IPv6 network

2001:db8:100::/64

Single client

client01.example.com / 192.0.2.21

NFS namespace root

/nfs

Projects export

/nfs/projects

Underlying storage mount

/data/projects

Shared group

nfswriters, GID 2000

firewalld zone

internal

Kerberos/IdM domain

example.com / EXAMPLE.COM

 

Capture state before editing:

# stamp=$(date +%F-%H%M%S)
# mkdir -p /root/nfs-backups/$stamp
# cp -a /etc/exports /etc/exports.d /etc/nfs.conf /etc/nfs.conf.d \
  /root/nfs-backups/$stamp/ 2>/dev/null || true
# exportfs -v > /root/nfs-backups/$stamp/exportfs-v.txt
# cp -a /etc/firewalld /root/nfs-backups/$stamp/firewalld 2>/dev/null || true
# firewall-cmd –list-all-zones > /root/nfs-backups/$stamp/firewalld-zones.txt 2>&1
# getsebool -a | grep -i nfs > /root/nfs-backups/$stamp/selinux-nfs-booleans.txt
# semanage fcontext -l | grep -i nfs > /root/nfs-backups/$stamp/selinux-fcontexts.txt 2>&1 || true
# systemctl status nfs-server –no-pager > /root/nfs-backups/$stamp/nfs-server.txt 2>&1 || true

For a remote change, leave the current SSH session open and test the service from a second session or client. Export and firewall changes should be source-restricted and reversible.

Contents

  1. NFS architecture, protocol versions, and server services
  2. Planning storage, identity, permissions, SELinux, security, and availability
  3. Installation and systemd service management
  4. Configuration files, Network File Services settings, and runtime state
  5. Preparing XFS/ext storage, groups, ACLs, and bind mounts
  6. /etc/exports syntax, selectors, defaults, and export options
  7. Basic NFSv4 export and NFSv4 pseudo-filesystem examples
  8. Adding, changing, deleting, and reloading exports
  9. NFSv4-only and NFSv3-compatible service configuration
  10. firewalld and nftables configuration
  11. SELinux server policy and troubleshooting
  12. UID/GID mapping, root squashing, and application identities
  13. Kerberos and IdM-secured NFS
  14. NFS with TLS, mutual TLS, quotas, and NFS over RDMA
  15. Performance tuning, monitoring, metrics, and packet capture
  16. Maintenance, high availability, backup, and disaster recovery
  17. Troubleshooting workflows, common failures, and command reference

NFS Architecture, Versions, and Server Services

The kernel NFS server processes file requests through nfsd threads. nfs-utils supplies the programs that configure those threads, authorise exports, manage NFSv3 RPC services, integrate GSS/Kerberos, preserve NFSv4 client state, and report statistics. NFSv4 consolidates more functions on TCP port 2049; NFSv3 normally needs rpcbind, mountd, statd, and lockd in addition to the NFS port.

Protocol

Characteristics

Operational guidance

NFSv4.2

Stateful, integrated locking, TCP 2049, NFSv4 namespace, modern data and layout features when supported.

Preferred for current Linux clients. Supports strong Kerberos flavours and current TLS implementations.

NFSv4.1

Sessions, improved recovery and connection handling, TCP 2049.

Keep for compatible clients unless a strict policy requires only 4.2.

NFSv4.0

Older NFSv4 state and callback model, TCP 2049.

Retain only for clients that need it; test DNS and failover carefully.

NFSv3

Core protocol plus MOUNT, rpcbind, locking and status RPC services; often more firewall ports.

Use for a defined compatibility requirement. Pin auxiliary ports and test reboot/lock recovery.

 

Service and Process Reference

Service or process

Purpose

Inspection

nfs-server.service

Meta service for the kernel NFS server and required helpers.

systemctl status nfs-server

rpc.nfsd / nfsd

Starts and serves kernel NFS threads and advertised versions.

cat /proc/fs/nfsd/versions; nfsstat -s

rpc.mountd

Authorises NFSv3 MOUNT requests and helps supply export access information.

systemctl status nfs-mountd; rpcinfo -p

rpcbind

Maps RPC program numbers to ports for NFSv3-era services.

systemctl status rpcbind; rpcinfo -p localhost

rpc-statd.service

NFSv3 reboot and lock recovery notifications.

systemctl status rpc-statd; journalctl -u rpc-statd

lockd

Kernel Network Lock Manager for NFSv3 locking.

rpcinfo -p; journalctl -k | grep lockd

gssproxy

Handles server-side GSS/Kerberos credentials on current RHEL-family systems.

systemctl status gssproxy; journalctl -u gssproxy

nfs-idmapd

NFSv4 identity mapping support where required.

systemctl status nfs-idmapd; /etc/idmapd.conf

nfsdcld / nfsdclnts

NFSv4 client recovery state and client inspection.

nfsdclnts –clientinfo; journalctl -u nfsdcld

rpc-rquotad

Remote quota reporting when quota-rpc is installed and enabled.

systemctl status rpc-rquotad; rpcinfo -p

tlshd

RPC-with-TLS handshake daemon on supported releases.

systemctl status tlshd; journalctl -u tlshd

 

Verify Enabled Protocol Versions

$ cat /proc/fs/nfsd/versions
-2 -3 +4 +4.0 +4.1 +4.2

A plus sign means enabled. Confirm the version actually used on each client with nfsstat -m or findmnt. Do not disable NFSv3 based only on an assumption that every client is current.

Plan Storage, Identity, Security, and Availability

Planning Checklist

  • Use dedicated XFS or ext-family file systems or clearly bounded subtrees. Do not export /, /etc, /var, or a broad path that can reveal future mounts.
  • Confirm local storage is mounted before nfs-server and use the mountpoint export option for critical mount-backed paths.
  • Keep numeric UID/GID values consistent through local policy, LDAP, Active Directory integration, or IdM. Names alone do not control sec=sys ownership.
  • Keep SELinux enforcing. Plan labels and booleans; troubleshoot AVC denials rather than setting permissive mode.
  • Use root_squash and source-restricted exports. Treat no_root_squash as a narrowly justified exception.
  • Use sync for normal data integrity. async is a risk decision, not a routine performance setting.
  • Prefer NFSv4. A v4-only server normally needs only the nfs firewalld service; v3 requires additional services and fixed-port planning.
  • For sensitive data, use Kerberos integrity/privacy, NFS TLS where supported, or an approved encrypted network overlay.
  • Plan quotas, capacity monitoring, snapshots, backups, and restoration before clients depend on the share.
  • For HA, use fencing, shared or replicated storage designed for the cluster, a stable service address, and preserved NFSv4 recovery state.

Access Decision Layers

Layer

What can deny access

Export policy

Client host/network, requested path, ro/rw, security flavour, and squash options.

Network policy

firewalld zone, rich rule, direct nftables rule, upstream ACL, or route.

NFS credential

Numeric UID/GID under AUTH_SYS or Kerberos principal under RPCSEC_GSS.

SELinux

Server process policy, file type, boolean, or certificate/key context.

POSIX permission

Owner/group/mode, default ACL, parent directory search permission, sticky/setgid bits.

Storage state

Read-only mount, quota, space, inode exhaustion, I/O error, snapshot state, or fencing issue.

Application behaviour

Wrong account, umask, file locking, open-file pattern, or unsupported shared-storage semantics.

 

Install NFS Server Packages and Manage Services

Install Packages

# dnf install -y nfs-utils
$ rpm -q nfs-utils
$ command -v exportfs nfsstat rpcinfo showmount
$ dnf info nfs-utils

Optional packages used later include quota-rpc, quota, acl, policycoreutils-python-utils, krb5-workstation, ipa-client, ktls-utils, tcpdump, sysstat, pcp-system-tools, and rdma-core. Package availability depends on the release and enabled repositories.

Enable and Start the NFS Server

# systemctl enable –now nfs-server.service
$ systemctl status nfs-server.service –no-pager
$ systemctl is-enabled nfs-server.service
$ systemctl is-active nfs-server.service

Reload Versus Restart

# exportfs -rav                  # Apply export-table changes
# systemctl reload nfs-server    # Reload where supported
# systemctl restart nfs-server   # Required for many daemon/listener changes

Prefer exportfs -rav for /etc/exports-only changes. Restarting nfs-server can affect active stateful clients and should be coordinated. Changes to /etc/nfs.conf protocol versions, fixed ports, thread counts, GSS/TLS helpers, or listener addresses normally need a restart.

Initial Verification

$ exportfs -v
$ cat /proc/fs/nfsd/versions
$ ss -lntup | grep -E “:2049\b|rpcbind|mountd”
$ rpcinfo -p localhost
$ nfsstat -s
$ journalctl -u nfs-server -b –no-pager

Configuration Files and Runtime State

Path

Purpose

/etc/exports

Primary persistent export table.

/etc/exports.d/*.exports

Modular export snippets. Use a .exports suffix.

/etc/nfs.conf

INI-style settings for nfsd, mountd, statd, lockd, and related components.

/etc/nfs.conf.d/*.conf

Local snippets where supported by the installed nfs-utils; verify effective behaviour on the release.

/etc/idmapd.conf

NFSv4 identity-mapping domain and settings.

/etc/gssproxy/*.conf

GSS proxy service definitions used for Kerberos-secured NFS.

/etc/krb5.conf

Kerberos realm and discovery configuration.

/etc/krb5.keytab

Host and nfs service keys; root-only secret.

/etc/firewalld

Persistent zones, services, policies, and rich rules.

/etc/selinux

SELinux mode and policy configuration; normal NFS administration should not require disabling enforcement.

/var/lib/nfs/etab

Runtime export table maintained by exportfs; do not edit.

/proc/fs/nfsd

Kernel NFS server control and state pseudo-filesystem.

/proc/net/rpc/nfsd

Raw server operation counters.

systemd journal and audit log

Service, kernel, firewalld, SELinux AVC, GSS, and storage evidence.

 

Inspect Configuration and Units

$ grep -R –line-number –exclude=”*~” . /etc/nfs.conf /etc/nfs.conf.d 2>/dev/null
$ systemctl cat nfs-server.service
$ systemctl list-dependencies nfs-server.service
$ rpm -V nfs-utils
$ man nfs.conf

RHEL and Oracle Linux releases can differ in defaults and advanced capabilities. Treat the local man pages and vendor documentation for the installed major/minor release as authoritative.

Prepare Export Storage, Groups, ACLs, and Mount Ordering

Create a Group-Writable XFS or ext Export

# groupadd –gid 2000 nfswriters
# mkdir -p /data/projects
# chown root:nfswriters /data/projects
# chmod 2770 /data/projects
$ stat -c “%A %a %U %G %n” /data/projects
$ getent group nfswriters

Apply POSIX ACLs

# dnf install -y acl
# setfacl -m g:nfswriters:rwx /data/projects
# setfacl -m d:g:nfswriters:rwx /data/projects
# setfacl -m d:o::— /data/projects
$ getfacl -p /data/projects

Keep the group GID and user memberships identical in IdM, LDAP, Active Directory integration, or local account policy across clients and server. Test with the actual application service account.

Bind Mount into a Stable NFS Namespace

# mkdir -p /nfs/projects
# mount –bind /data/projects /nfs/projects
$ findmnt /nfs/projects

Persistent /etc/fstab example:

/data/projects  /nfs/projects  none  bind,x-systemd.requires-mounts-for=/data/projects  0  0
# systemctl daemon-reload
# mount -a
$ findmnt -R /nfs

Use mountpoint in the export options for storage that must be mounted. It prevents the empty directory beneath a failed mount from being exported accidentally.

Warning: Do not use chmod 777 to make NFS work. It bypasses the intended identity model, broadens local access, and does not solve SELinux, export, quota, or read-only storage problems.

/etc/exports Syntax, Selectors, and Defaults

The format is path, whitespace, client selector, and an immediately adjacent parenthesised option list. Whitespace between a client selector and its option block changes the meaning and can expose the export more broadly than intended.

/nfs/projects  192.0.2.0/24(rw,sync,no_subtree_check,root_squash)

Critical whitespace: /nfs/projects client01.example.com(rw) restricts rw to that client. /nfs/projects client01.example.com (rw) is parsed differently and can apply rw as a default to other clients. Always run exportfs -v after editing.

Client Selector Examples

Type

Example

Guidance

FQDN

client01.example.com

Requires trustworthy, stable resolution.

IPv4 host

192.0.2.21

Specific and easy to audit.

IPv4 network

192.0.2.0/24

Normal choice for a managed client subnet.

IPv6 host

2001:db8:100::21

No square brackets in /etc/exports.

IPv6 prefix

2001:db8:100::/64

Authorises the whole prefix.

Wildcard

*.example.com

Matches dots; can be broader than expected.

Netgroup

@engineering

Uses NSS netgroup data; verify with getent netgroup.

All hosts

*

Avoid for writable production exports.

 

Default Export Behaviour

When not overridden, common defaults are ro, sync, wdelay, and root_squash. State important options explicitly so a reviewer does not need to remember defaults.

Export Option Reference

Option

Meaning and operational guidance

ro / rw

Read-only or read-write. Local mode, ACL, SELinux, quota, and storage state still apply.

sync / async

sync acknowledges stable writes and is the normal integrity choice. async can lose acknowledged data after an unclean restart.

root_squash

Maps remote UID 0 to the anonymous identity; normal safe default.

no_root_squash

Gives client root server-side root authority. Use only for a tightly restricted, documented requirement.

all_squash

Maps all remote identities to the anonymous account.

anonuid / anongid

Sets numeric anonymous identity; use a dedicated local account for controlled all_squash shares.

subtree_check / no_subtree_check

Enables or disables subtree verification. no_subtree_check is common for dedicated exports and rename-heavy workloads.

secure / insecure

Controls whether non-GSS requests must originate from a reserved client port. insecure broadens acceptance and should be exceptional.

fsid=0

NFSv4 pseudo-filesystem root. Use one stable root.

fsid=N

Stable unique file-system identifier when needed.

crossmnt

Allows traversal into mounted children and can inherit export options. Audit newly mounted children.

mountpoint / mp

Export only while the path is a mount point.

wdelay / no_wdelay

Controls batching delay for synchronous writes; no_wdelay does not matter with async.

sec=sys

Client-provided numeric UNIX credentials; no cryptographic user authentication.

sec=krb5

Kerberos authentication.

sec=krb5i

Kerberos authentication and integrity.

sec=krb5p

Kerberos authentication, integrity, and privacy encryption.

security_label

Enables labeled NFS behaviour where supported and correctly configured; requires compatible clients and SELinux policy.

xprtsec=tls / mtls

Requires RPC-with-TLS confidentiality or mutual authentication on supported releases and nfs-utils versions.

 

Basic NFSv4 Export

Prepare the Directory

# mkdir -p /nfs/projects
# chown root:nfswriters /nfs/projects
# chmod 2770 /nfs/projects
# restorecon -Rv /nfs/projects

Define and Activate the Export

Add to /etc/exports or /etc/exports.d/projects.exports:

/nfs/projects  192.0.2.0/24(rw,sync,no_subtree_check,root_squash) \
  2001:db8:100::/64(rw,sync,no_subtree_check,root_squash)
# exportfs -rav
$ exportfs -v
$ exportfs -s

Open firewalld for NFSv4

# firewall-cmd –zone=internal –permanent –add-service=nfs
# firewall-cmd –reload
$ firewall-cmd –zone=internal –list-all

Ensure the client-facing connection is actually in the internal zone:

$ firewall-cmd –get-active-zones
$ nmcli -f GENERAL.CONNECTION,GENERAL.DEVICE,GENERAL.STATE device show

Start and Test

# systemctl enable –now nfs-server
$ ss -lnt sport = :2049
$ cat /proc/fs/nfsd/versions

Client test:

# dnf install -y nfs-utils
# mkdir -p /mnt/projects
# mount -t nfs4 -o vers=4.2 nfs01.example.com:/nfs/projects /mnt/projects
$ nfsstat -m
$ sudo -u projectuser touch /mnt/projects/client-write-test
$ ls -ln /mnt/projects/client-write-test
$ rm /mnt/projects/client-write-test
# umount /mnt/projects

NFSv4 Pseudo-Filesystem Namespace

A pseudo-filesystem gives clients a stable tree independent of the server storage paths. Export /nfs as fsid=0, bind mount real storage beneath it, and export child paths with explicit options.

Prepare Mounts

# mkdir -p /nfs/projects /nfs/reference
# mount –bind /data/projects /nfs/projects
# mount –bind /data/reference /nfs/reference
$ findmnt -R /nfs

Export the Namespace

/nfs  192.0.2.0/24(ro,fsid=0,crossmnt,sync,no_subtree_check,root_squash)
/nfs/projects  192.0.2.0/24(rw,sync,no_subtree_check,root_squash,mountpoint)
/nfs/reference 192.0.2.0/24(ro,sync,no_subtree_check,root_squash,mountpoint)
# exportfs -rav
$ exportfs -v

Client Paths

# mount -t nfs4 nfs01.example.com:/projects /mnt/projects
# mount -t nfs4 nfs01.example.com:/reference /mnt/reference

Use one fsid=0 namespace root. crossmnt is convenient but can expose mounted children with inherited options; explicit child exports and a strict storage-mount inventory are easier to audit.

Add, Change, Delete, and Reload Exports

Inspect

$ exportfs
$ exportfs -v
$ exportfs -s
$ cat /var/lib/nfs/etab

Apply Persistent Changes

# vi /etc/exports.d/projects.exports
# exportfs -rav
$ exportfs -v

Temporary Command-Line Export

# exportfs -o ro,sync,root_squash client01.example.com:/nfs/reference
$ exportfs -v

Unexport One Client and Path

# exportfs -u client01.example.com:/nfs/reference
$ exportfs -v

Remove Persistently

# vi /etc/exports.d/projects.exports
# exportfs -rav
$ exportfs -v

Warning: exportfs -ua removes all active exports and effectively stops NFS access. Use it only in a planned full shutdown.

For a permission or security-flavour change, coordinate client remount behaviour. An already mounted client can retain state that makes a simple server-side test appear inconsistent until the client renews or remounts.

Configure an NFSv4-Only Server

An NFSv4-only server reduces open ports and removes NFSv3 mount, lock, and status services. RHEL documentation explicitly supports disabling vers3 in /etc/nfs.conf and masking NFSv3-related units when no other application needs them. Apply this only after a complete client and RPC dependency inventory.

Example /etc/nfs.conf:

[nfsd]
vers3=n
vers4.0=n
vers4.1=y
vers4.2=y

If the release documentation requires only one minor version, set the individual vers4.x values. Avoid ambiguous combinations of a global vers4 setting and minor-version settings.

# systemctl mask –now rpc-statd.service rpcbind.service rpcbind.socket
# mkdir -p /etc/systemd/system/nfs-mountd.service.d
# cat > /etc/systemd/system/nfs-mountd.service.d/v4only.conf <<EOF
[Service]
ExecStart=
ExecStart=/usr/sbin/rpc.mountd –no-tcp –no-udp
EOF
# systemctl daemon-reload
# systemctl restart nfs-mountd nfs-server
$ cat /proc/fs/nfsd/versions
$ ss -lntup | grep -E “:2049\b|rpcbind|mountd”

The rpc.mountd override disables its NFSv3 MOUNT listeners while retaining the internal functions required by NFSv4. Remove the override, run systemctl daemon-reload, and unmask the RPC units before restoring NFSv3 support.

Caution: Masking rpcbind or rpc-statd can break other RPC applications. Confirm rpcinfo -p, installed products, backup agents, clustering components, and vendor requirements first. Unmask promptly if the audit identifies a dependency.

# firewall-cmd –zone=internal –permanent –add-service=nfs
# firewall-cmd –reload

Configure NFSv3 with Optional NFSv4 Support

NFSv3 requires rpcbind, mountd, statd, and lockd. Pin lock and status ports to make the firewall deterministic. The following follows the current RHEL pattern; confirm values are unused and supported on the installed release.

Example /etc/nfs.conf:

[nfsd]
vers3=y
vers4=y

[lockd]
port=5555
udp-port=5555

[statd]
port=6666
# ss -lntup | grep -E “:(5555|6666)\b”
# systemctl unmask rpcbind.service rpcbind.socket rpc-statd.service
# systemctl enable –now rpcbind.socket
# systemctl enable –now rpc-statd nfs-server
$ rpcinfo -p localhost
$ cat /proc/fs/nfsd/versions

firewalld Rules for NFSv3

# firewall-cmd –zone=internal –permanent –add-service={nfs,rpc-bind,mountd}
# firewall-cmd –zone=internal –permanent \
  –add-port={5555/tcp,5555/udp,6666/tcp,6666/udp}
# firewall-cmd –reload
$ firewall-cmd –zone=internal –list-all

Test locks and reboot recovery, not only mounting. A share that mounts can still fail when an application first requests a lock. Use rpcinfo -p and packet capture to confirm the exact ports.

Restrict NFS with firewalld Sources and Rich Rules

Dedicated Zone for NFS Clients

# firewall-cmd –permanent –new-zone=nfs-clients
# firewall-cmd –permanent –zone=nfs-clients –add-source=192.0.2.0/24
# firewall-cmd –permanent –zone=nfs-clients –add-service=nfs
# firewall-cmd –reload
$ firewall-cmd –zone=nfs-clients –list-all

A source-bound zone is often clearer than opening NFS in a broad interface zone. Ensure a source is not unexpectedly assigned to a higher-precedence policy or overlapping zone.

Rich Rule Example

# firewall-cmd –zone=internal –permanent –add-rich-rule=’
  rule family=”ipv4″ source address=”192.0.2.0/24″ \
  service name=”nfs” accept’
# firewall-cmd –reload
$ firewall-cmd –zone=internal –list-rich-rules

Remove a Rule

# firewall-cmd –zone=internal –permanent –remove-rich-rule=’
  rule family=”ipv4″ source address=”192.0.2.0/24″ \
  service name=”nfs” accept’
# firewall-cmd –reload

Inspect the nftables Backend

$ firewall-cmd –get-active-zones
$ firewall-cmd –list-all-zones
# nft list ruleset
# nft monitor trace

Do not edit firewalld-managed nftables chains directly. Use firewalld for persistent policy unless the server is intentionally managed by a standalone nftables configuration.

SELinux Configuration and Troubleshooting

SELinux is an independent enforcement layer. An export can be correct in /etc/exports and still be denied by policy. Keep Enforcing mode and inspect the specific denial. The available file types and booleans can change with policy packages, so query the installed system instead of copying a generic setsebool command blindly.

Inspect Status, Labels, and NFS Booleans

$ getenforce
$ sestatus
$ ls -Zd /nfs /nfs/projects
$ getsebool -a | grep -i nfs
$ sepolicy booleans | grep -i nfs 2>/dev/null || true
$ semanage fcontext -l | grep -Ei “nfs|public_content”

Restore Expected Labels

# restorecon -Rv /nfs /data/projects
$ ls -Zd /nfs /nfs/projects /data/projects

restorecon applies the policy-defined label for the path. A bind mount shows the label of the underlying object, so label the real storage path rather than only the empty mount-point directory.

Use Persistent File-Context Rules When Required

If policy documentation calls for a specific type, define it persistently with semanage and then apply it. Do not rely on chcon because relabelling or restorecon can remove an ad hoc label.

# dnf install -y policycoreutils-python-utils
# semanage fcontext -a -t public_content_rw_t “/data/projects(/.*)?”
# restorecon -Rv /data/projects
$ ls -Zd /data/projects

The correct type depends on the policy and workload. Query man nfs_selinux and sepolicy on the installed host before choosing a type.

NFS Export Booleans

$ getsebool nfs_export_all_ro nfs_export_all_rw 2>/dev/null
$ sepolicy booleans -b nfs_export_all_rw 2>/dev/null

Some policies use nfs_export_all_ro and nfs_export_all_rw to prevent accidental exports of arbitrary labels. Enable only the minimum required boolean after reviewing its local description:

# setsebool -P nfs_export_all_rw on

Caution: A broad boolean can widen what nfsd may export. Prefer a specific supported label when practical, and still rely on /etc/exports, file permissions, and firewalld. Record and review persistent boolean changes.

Investigate AVC Denials

# ausearch -m AVC,USER_AVC -ts recent
# ausearch -m AVC -ts recent -c nfsd
# journalctl -t setroubleshoot –since “-30 minutes”
# sealert -a /var/log/audit/audit.log 2>/dev/null

Do not pipe an unreviewed denial into audit2allow and install the result. First correct labels, booleans, mount contexts, and application design. A custom policy module is the final step when the access is truly intended and no supported policy control exists.

UID/GID Mapping, Root Squashing, and Application Access

AUTH_SYS Trust Model

sec=sys carries numeric UNIX credentials supplied by an authorised client. It is appropriate only for managed clients and networks because a client administrator can normally create an account with an arbitrary UID. Central identity improves consistency but does not cryptographically prove the user to the NFS server.

$ id projectuser
$ getent passwd projectuser
$ getent group nfswriters
$ ls -ldn /nfs/projects
$ getfacl -pn /nfs/projects

Root Squashing

/nfs/projects  192.0.2.0/24(rw,sync,no_subtree_check,root_squash)

A file created by client root can appear as the anonymous account. Grant the intended group or service account permission rather than setting no_root_squash.

All-Squash Service Share

# groupadd –system –gid 2001 nfsdrop
# useradd –system –uid 2001 –gid 2001 –home-dir /nonexistent \
  –shell /sbin/nologin nfsdrop
# mkdir -p /nfs/dropbox
# chown nfsdrop:nfsdrop /nfs/dropbox
# chmod 0730 /nfs/dropbox
/nfs/dropbox  192.0.2.0/24(rw,sync,no_subtree_check,all_squash,anonuid=2001,anongid=2001)

Application Test

$ sudo -u appsvc id
$ sudo -u appsvc namei -om /nfs/projects
$ sudo -u appsvc touch /nfs/projects/server-side-test
$ ls -ln /nfs/projects/server-side-test
$ rm /nfs/projects/server-side-test

Run equivalent tests from the client using the same service account. A successful root shell test does not validate a confined systemd service, container, or application domain.

Kerberos and Identity Management Secured NFS

RPCSEC_GSS uses Kerberos principals and supports sec=krb5, krb5i, and krb5p. In an IdM environment, use IdM service principals and keytab retrieval rather than manually duplicating account data. DNS and time must be correct before NFS GSS troubleshooting begins.

Prerequisites

$ hostname –fqdn
$ getent hosts nfs01.example.com
$ dig -x 192.0.2.10 +short
$ chronyc tracking
$ ipa ping 2>/dev/null || true
$ realm list 2>/dev/null || true

Create the NFS Service in IdM

Run the service-add command with an authorised IdM administrator, then retrieve the keytab on the NFS server:

$ ipa service-add nfs/nfs01.example.com
# ipa-getkeytab -s idm01.example.com \
  -p nfs/nfs01.example.com -k /etc/krb5.keytab
# klist -k /etc/krb5.keytab
# restorecon -v /etc/krb5.keytab

Enable GSS Components

# systemctl enable –now gssproxy
# systemctl restart nfs-server
$ systemctl status gssproxy nfs-server –no-pager
# journalctl -u gssproxy -u nfs-server -b

Require Kerberos Privacy

/nfs/secure  192.0.2.0/24(rw,sync,no_subtree_check,root_squash,sec=krb5p)
# exportfs -rav
$ exportfs -v

Client Verification

$ kinit projectuser@EXAMPLE.COM
$ klist
# mount -t nfs4 -o sec=krb5p nfs01.example.com:/secure /mnt/secure
$ nfsstat -m
$ sudo -u projectuser touch /mnt/secure/kerberos-test

Troubleshoot GSS

$ kvno nfs/nfs01.example.com
# klist -k /etc/krb5.keytab
# journalctl -u gssproxy -u nfs-server –since “-30 minutes”
# ausearch -m AVC -ts recent
# tcpdump -ni any port 88 or port 2049

A sec=sys mount succeeding while sec=krb5p fails isolates the problem to the Kerberos/GSS/name/time path rather than basic NFS transport.

NFS with TLS and Mutual TLS

Current vendor releases add RPC-with-TLS support. Red Hat Enterprise Linux 10 documents NFS TLS through ktls-utils and tlshd. Oracle Linux 10 documentation states that the TLS server procedure applies to Oracle Linux 9 or later. Exact kernel, package, and minor-release prerequisites matter, so confirm the installed vendor documentation before enabling or requiring TLS.

Install and Prepare Certificates

# dnf install -y ktls-utils openssl
# openssl req -new -newkey rsa:4096 -noenc \
  -keyout /etc/pki/tls/private/nfs01.example.com.key \
  -out /etc/pki/tls/private/nfs01.example.com.csr \
  -subj “/C=AU/ST=NSW/L=Sydney/O=Example/CN=nfs01.example.com” \
  -addext “subjectAltName=DNS:nfs01.example.com,IP:192.0.2.10”

Send the CSR to the approved CA. Install the CA and server certificate, then restore labels:

# cp example-ca.crt /etc/pki/ca-trust/source/anchors/
# update-ca-trust
# mv nfs01.example.com.crt /etc/pki/tls/certs/
# chown root:root /etc/pki/tls/private/nfs01.example.com.key \
  /etc/pki/tls/certs/nfs01.example.com.crt
# chmod 0600 /etc/pki/tls/private/nfs01.example.com.key
# restorecon -Rv /etc/pki/tls/private /etc/pki/tls/certs

Configure tlshd

Example /etc/tlshd.conf server section:

[authenticate.server]
x509.certificate = /etc/pki/tls/certs/nfs01.example.com.crt
x509.private_key = /etc/pki/tls/private/nfs01.example.com.key
# systemctl enable –now tlshd.service
$ systemctl status tlshd.service –no-pager
# journalctl -u tlshd.service -b

Client Mount and Verification

# mount -t nfs4 -o xprtsec=tls nfs01.example.com:/projects /mnt/projects
# journalctl -u tlshd –since “-10 minutes”
$ nfsstat -m

Require TLS on an Export Where Supported

/nfs/private  192.0.2.0/24(rw,sync,root_squash,xprtsec=tls)

For mutual TLS, provision a client certificate and configure the [authenticate.client] section on the client, then mount with xprtsec=mtls. Enforcing xprtsec=mtls on the export prevents non-mutually authenticated transport when the installed exports(5) supports that option.

Security note: TLS provides transport confidentiality and optional host certificate authentication. It does not replace local permissions, SELinux, export allow-lists, root squashing, or user-level Kerberos where user identity is required.

Quotas on an NFS Server

Enable quotas on the underlying XFS or ext file system first. The quota-rpc package and rpc-rquotad service expose quota information to remote clients; they do not create the quota policy.

Verify Local Quota State

$ findmnt /nfs/projects
# quotaon -p /nfs/projects 2>/dev/null || true
# xfs_quota -x -c “state” /nfs/projects 2>/dev/null || true
# xfs_quota -x -c “report -h” /nfs/projects 2>/dev/null || true

Install and Enable Remote Quota Service

# dnf install -y quota-rpc
# systemctl enable –now rpc-rquotad
$ systemctl status rpc-rquotad –no-pager
$ rpcinfo -p localhost | grep -i rquota

The vendor procedure uses UDP port 875 by default. Open it only from client networks:

# firewall-cmd –zone=internal –permanent –add-port=875/udp
# firewall-cmd –reload

To use a different fixed port or permit remote quota modification, edit /etc/sysconfig/rpc-rquotad according to the installed man page. Remote quota modification broadens administrative authority and should normally remain disabled.

Optional NFS over RDMA

NFS over RDMA can reduce CPU overhead and latency on supported RDMA hardware and networks. It is not a general Ethernet performance switch. Validate adapters, drivers, lossless fabric design where required, kernel modules, client support, and storage throughput before deployment.

# dnf install -y rdma-core
# grep -Ev “^[[:space:]]*(#|$)” /etc/rdma/modules/rdma.conf
# modprobe xprtrdma
# modprobe svcrdma
$ lsmod | grep -E “xprtrdma|svcrdma”

Ensure that xprtrdma and svcrdma are uncommented in /etc/rdma/modules/rdma.conf so client and server RDMA support is loaded persistently. The default NFS-over-RDMA port is 20049 and requires no /etc/nfs.conf change. To select a non-default port, set only rdma-port in the [nfsd] section, for example:

[nfsd]
rdma-port=20500
# firewall-cmd –zone=internal –permanent \
  –add-port={20049/tcp,20049/udp}
# firewall-cmd –reload
# systemctl restart nfs-server

For the non-default example, open 20500/tcp and 20500/udp instead. Test from an RDMA-capable client and confirm proto=rdma rather than assuming the mount used the requested transport:

# mount -t nfs -o rdma nfs01.example.com:/projects /mnt/projects
$ findmnt -no SOURCE,FSTYPE,OPTIONS /mnt/projects

Keep an ordinary TCP path or rollback plan until the RDMA service is proven under failure and maintenance scenarios.

Performance Tuning and Capacity Planning

NFS performance is the combined result of storage, network, CPU, server threads, export semantics, client mount behaviour, file-size distribution, and application locking. Measure all layers before changing settings. Do not use async to disguise slow storage without accepting its crash-consistency risk.

Baseline Commands

$ uptime
$ free -h
$ df -hT /nfs/projects
$ df -ih /nfs/projects
$ iostat -xz 1
$ sar -n DEV,EDEV,TCP,ETCP 1
$ nfsstat -s 1
$ ss -tin sport = :2049
$ ip -s -s link show dev enp1s0
$ ethtool -S enp1s0

Tune nfsd Threads Carefully

[nfsd]
threads=32
$ cat /proc/fs/nfsd/threads
# systemctl restart nfs-server
$ cat /proc/fs/nfsd/threads

Increase threads only when measured concurrency and RPC backlog justify it and CPU/storage have headroom. More threads do not fix high disk latency, packet loss, or a serialized application.

Performance Co-Pilot and sar

# dnf install -y pcp pcp-system-tools sysstat
# systemctl enable –now pmcd pmlogger sysstat
$ pmstat 1
$ sar -n NFS,NFSD 1 2>/dev/null || true
$ sar -n DEV,EDEV 1

Controlled Test Tools

# iperf3 -s
# fio –name=nfs-backing-test –directory=/nfs/projects \
  –rw=write –bs=1M –size=4G –direct=1 –iodepth=16 \
  –runtime=60 –time_based
$ iostat -xz 1

Warning: Run fio only in an approved empty test directory. A mistaken directory or filename can destroy data. Final validation must use the actual NFS client and workload, not only local storage benchmarks.

Interpretation Guide

Evidence

Likely direction

High storage await/utilisation with low network use

Backing storage or stable-write latency.

NIC errors, drops, retransmissions, or pause storms

Physical/data-link/fabric problem.

Only one client slow

Client route, NIC, mount options, identity, or workload.

RPC backlog and all nfsd threads active

Thread limit may matter after CPU/storage checks.

Metadata workload slow

Directory contention, storage metadata latency, ACL/label overhead, or application serialization.

Kerberos privacy slower than sec=sys

Expected cryptographic CPU cost; measure capacity and use acceleration/CPU sizing rather than weakening policy casually.

TLS handshake errors or fallback

Certificate, trust, name, tlshd, kernel capability, or export xprtsec policy.

 

Monitoring, Metrics, Active Clients, and Packet Capture

NFS and Client State

$ exportfs -v
$ nfsstat -s
$ nfsstat -s 1
$ cat /proc/net/rpc/nfsd
$ nfsdclnts –clientinfo 2>/dev/null
$ nfsdclnts –type open 2>/dev/null
$ showmount -a localhost 2>/dev/null

showmount is an NFSv3-era view and is not a complete NFSv4 client inventory. Combine nfsdclnts, TCP connections, application inventory, and monitoring data.

Sockets and Network State

$ ss -lntup | grep -E “:2049\b|rpc”
$ ss -tn sport = :2049
$ ss -tin sport = :2049
$ firewall-cmd –get-active-zones
# nft list ruleset

Packet Capture

# tcpdump -ni enp1s0 tcp port 2049
# tcpdump -ni enp1s0 host 192.0.2.21 and port 2049 \
  -w /var/tmp/nfs-client01.pcap
# tcpdump -ni enp1s0 port 111 or port 2049 or port 5555 or port 6666

Logs and SELinux Audit

# journalctl -u nfs-server -u rpc-statd -u gssproxy -u tlshd -b
# journalctl -k -b | grep -Ei “nfs|rpc|lockd|sunrpc|stale|I/O error”
# ausearch -m AVC,USER_AVC -ts recent
# journalctl -t setroubleshoot –since “-30 minutes”

Maintenance, Backup, High Availability, and Disaster Recovery

Planned Maintenance

  1. Inventory clients, open files, locks, and applications that cannot tolerate a pause.
  2. Quiesce applications and take an application-consistent storage snapshot or backup where required.
  3. Back up exports, nfs.conf, firewalld, SELinux local customisations, IdM/GSS settings, and TLS configuration. Handle private keys separately.
  4. Perform maintenance through console access and verify file systems before starting nfs-server.
  5. Verify exportfs -v, protocol versions, listeners, firewalld, SELinux labels, and storage health.
  6. Run ordinary-user create/read/rename/lock/delete tests from a client before reopening the workload.

Configuration Backup

# tar –xattrs –acls -czf /root/nfs-config-$stamp.tar.gz \
  /etc/exports /etc/exports.d /etc/nfs.conf /etc/nfs.conf.d \
  /etc/firewalld /etc/gssproxy /etc/idmapd.conf 2>/dev/null
# exportfs -v > /root/exportfs-$stamp.txt
# getsebool -a | grep -i nfs > /root/nfs-selinux-$stamp.txt
# semanage fcontext -l > /root/selinux-fcontext-$stamp.txt

Back up /etc/krb5.keytab and TLS private keys only through the organisation’s approved secrets and recovery process.

High Availability Principles

  • Use a supported cluster stack, shared or replicated storage, and fencing. Never allow split-brain writable exports.
  • Move the service address, storage activation, exports, and nfs-server resource in a controlled dependency order.
  • Keep SELinux labels, firewalld rules, keytabs, certificates, UID/GID sources, and export files consistent on every node.
  • Preserve NFSv4 client recovery state and understand the grace period during failover.
  • Test abrupt node loss, fence delay, lock recovery, open files, client retries, and restoration to the preferred node.

Pacemaker resource design varies with storage and subscription support. Follow the Red Hat High Availability Add-On or Oracle Linux cluster documentation and the storage vendor procedure for the exact environment.

Troubleshooting Workflow

1. Verify Storage and Mounts

$ findmnt -R /nfs
$ df -hT /nfs/projects
$ df -ih /nfs/projects
$ ls -Zd /nfs/projects
$ touch /nfs/projects/server-local-test && rm /nfs/projects/server-local-test
# journalctl -k -b | grep -Ei “I/O error|xfs|ext4|nvme|scsi|multipath”

2. Verify NFS Service and Versions

$ systemctl status nfs-server –no-pager
$ cat /proc/fs/nfsd/versions
$ ss -lntup | grep -E “:2049\b|rpcbind|mountd”
$ rpcinfo -p localhost
$ journalctl -u nfs-server -b

3. Verify Effective Exports

$ exportfs -v
$ exportfs -s
$ grep -R –line-number . /etc/exports /etc/exports.d 2>/dev/null

4. Verify Firewall and Route

$ firewall-cmd –get-active-zones
$ firewall-cmd –list-all-zones
# nft list ruleset
$ ip route get 192.0.2.21
# tcpdump -ni any host 192.0.2.21 and port 2049

5. Verify SELinux and Local Permissions

$ getenforce
$ ls -Zd /nfs/projects /data/projects
$ namei -om /nfs/projects
$ ls -ldn /nfs/projects
$ getfacl -pn /nfs/projects
# ausearch -m AVC,USER_AVC -ts recent

6. Verify Identity or Kerberos

$ id projectuser
$ getent passwd projectuser
$ getent group nfswriters
$ klist
$ kvno nfs/nfs01.example.com 2>/dev/null
# klist -k /etc/krb5.keytab

7. Reproduce from a Client

$ getent hosts nfs01.example.com
$ nc -vz -w 3 nfs01.example.com 2049
# mount -vvv -t nfs4 -o vers=4.2 nfs01.example.com:/projects /mnt/projects
$ nfsstat -m
$ sudo -u projectuser touch /mnt/projects/testfile

Common Errors and Corrective Direction

Symptom

Likely causes

Checks

access denied by server while mounting

Wrong path, host not allowed, security-flavour mismatch, DNS selector issue, stale export table.

exportfs -v; exact client address; exportfs -rav; mountd/GSS logs.

Permission denied after mount

POSIX ACL/mode, UID/GID mismatch, root_squash, SELinux, quota, read-only storage.

id; ls -ln; getfacl -n; ls -Z; ausearch; findmnt; quota tools.

read-only file system

ro export/mount, storage remounted ro, file-system error, snapshot.

exportfs -v; nfsstat -m; findmnt; kernel logs.

stale file handle

Object or file-system identity changed after restore/remount/snapshot; subtree moved.

Fix server identity first, then remount clients; inspect storage and export changes.

server not responding

Service, firewall, route, loss, overloaded storage, hung I/O, failover issue.

ss; tcpdump both ends; firewall; iostat; link errors; server console.

NFSv4 works but showmount fails

MOUNT protocol not available on v4-only server.

Use exportfs -v and a direct v4 mount; do not reopen v3 solely for showmount.

NFSv3 mount works but lock fails

lockd/statd port blocked or recovery path broken.

rpcinfo -p; fixed-port rules; rpc-statd logs; controlled lock/reboot test.

nobody ownership

Squashing, unknown numeric ID, or ID-mapping mismatch.

export options; ls -ln; getent; idmapd settings.

SELinux AVC denial

Wrong label, boolean, bind-mount context, key/certificate context, or unsupported access.

ausearch; sealert; ls -Z; restorecon; semanage; sepolicy.

Kerberos mount fails

DNS/time/principal/keytab/GSS/sec mismatch.

chronyc; forward/reverse DNS; klist; kvno; keytab; gssproxy logs.

TLS handshake fails

Certificate name, trust, key permissions/context, tlshd, kernel/package capability.

openssl certificate inspection; trust list; journalctl -u tlshd; ausearch.

Slow writes

Stable-write storage latency, network loss, threads, crypto CPU, workload pattern.

nfsstat; iostat; sar; ss -ti; ethtool; client mount/workload.

 

Diagnostic Snapshot Collection

# stamp=$(date +%F-%H%M%S)
# out=/var/tmp/nfs-diag-$stamp
# mkdir -p “$out”
# exportfs -v > “$out/exportfs-v.txt” 2>&1
# exportfs -s > “$out/exportfs-s.txt” 2>&1
# cat /proc/fs/nfsd/versions > “$out/versions.txt” 2>&1
# cat /proc/net/rpc/nfsd > “$out/proc-nfsd.txt” 2>&1
# nfsstat -s > “$out/nfsstat-s.txt” 2>&1
# rpcinfo -p localhost > “$out/rpcinfo.txt” 2>&1
# ss -lntup > “$out/ss-listen.txt” 2>&1
# ss -tin sport = :2049 > “$out/ss-2049.txt” 2>&1
# firewall-cmd –list-all-zones > “$out/firewalld.txt” 2>&1
# nft list ruleset > “$out/nftables.txt” 2>&1
# getenforce > “$out/getenforce.txt” 2>&1
# getsebool -a | grep -i nfs > “$out/nfs-booleans.txt” 2>&1
# ausearch -m AVC,USER_AVC -ts boot > “$out/avc.txt” 2>&1
# findmnt -R /nfs > “$out/findmnt.txt” 2>&1
# df -hT > “$out/df-hT.txt” 2>&1
# df -ih > “$out/df-ih.txt” 2>&1
# journalctl -b -u nfs-server -u rpc-statd -u gssproxy \
  -u tlshd –no-pager > “$out/journal.txt” 2>&1
# dmesg -T > “$out/dmesg.txt” 2>&1
# tar -C /var/tmp -czf “$out.tar.gz” “$(basename “$out”)”
# printf “%s\n” “$out.tar.gz”

Review for hostnames, addresses, usernames, exports, audit data, and confidential paths before sharing. Never add keytabs or private keys to a normal diagnostic archive.

Security Hardening Checklist

  • Prefer NFSv4 and disable NFSv3 only after a complete client and RPC dependency inventory.
  • Restrict firewalld zones or rich rules to explicit client sources.
  • Restrict /etc/exports to explicit hosts or CIDR networks; avoid writable wildcard exports.
  • Keep root_squash and sync; document every exception.
  • Keep SELinux Enforcing and use supported labels or booleans rather than disabling policy.
  • Use centrally managed UID/GID data and test ordinary application identities.
  • Use sec=krb5i or sec=krb5p where user authentication and integrity/privacy are required.
  • Use NFS TLS or an approved encrypted overlay for transport protection on supported releases.
  • Protect keytabs and TLS private keys, rotate them, and remove obsolete trust anchors.
  • Patch kernel, nfs-utils, SELinux policy, firewalld, storage drivers, and firmware through supported channels.
  • Monitor capacity, quota, RPC errors, SELinux AVCs, service restarts, export changes, and network errors.
  • Use fencing and supported cluster resources for HA; test split-brain prevention and lock recovery.

Command Reference Summary

Task

Command

Install server

dnf install -y nfs-utils

Start at boot

systemctl enable –now nfs-server

Show exports

exportfs -v

Apply exports

exportfs -rav

Show normalised exports

exportfs -s

Unexport one path

exportfs -u client:/path

Show NFS versions

cat /proc/fs/nfsd/versions

Show RPC programs

rpcinfo -p localhost

Server statistics

nfsstat -s

Inspect NFSv4 clients

nfsdclnts –clientinfo

Open NFSv4 service

firewall-cmd –zone=internal –permanent –add-service=nfs

Show active zones

firewall-cmd –get-active-zones

Show NFS booleans

getsebool -a | grep -i nfs

Recent AVC denials

ausearch -m AVC,USER_AVC -ts recent

Restore labels

restorecon -Rv /nfs /data/projects

NFS logs

journalctl -u nfs-server -b

Capture NFS traffic

tcpdump -ni any tcp port 2049 -w nfs.pcap

Check path permissions

namei -om /nfs/projects; getfacl -pn /nfs/projects

 

Authoritative References

Use the installed manual pages first: man 5 exports; man 8 exportfs; man 5 nfs.conf; man 8 rpc.nfsd; man 8 rpc.mountd; man 8 nfsdclnts; man 8 nfs_selinux; and man 8 firewalld and firewall-cmd.

Validate release-specific commands against the installed system and vendor documentation. Features such as NFS TLS, mutual TLS, labeled NFS, RDMA, and exact SELinux policy controls depend on the release, kernel, packages, and support policy.

 

Check out our other Cheat Sheets and Blogs and if you would like us to write a cheat sheet for you, for FREE, (and we find it suitable) Contact Us.