NAME
nfsdiag — diagnose NFS from both sides of the wire.
SYNOPSIS
nfsdiag client
[OPTIONS]
<server-ip-or-hostname>
nfsdiag server
[OPTIONS]
nfsdiag diff
<before.json>
<after.json>
DESCRIPTION
client tests an NFS server from a client machine. It
walks the stack from the wire up: TCP reachability, rpcbind, NFS
v2/v3/v4/v4.1/v4.2 probes, mountd, exports, mount cascade,
permissions, root squash, ACLs, locking, stale handles, performance.
server runs on the NFS server itself and audits its
configuration, starting with the exports file: syntax errors,
exports without a client list, no_root_squash,
insecure, world-writable wildcards.
Both modes share the report engine — compact text by default, JSON
and standalone HTML when you need it — and the same exit codes. Safe
by default: validated inputs, trusted helper execution, automatic
mount namespace, O_NOFOLLOW reports, and opt-in
dangerous probes.
Written in C99 against libtirpc. MIT.
Current version: 0.22.0.
$ sudo nfsdiag client 192.168.1.10 nfsdiag 0.22.0: 192.168.1.10 [OK] rpcbind on tcp/111 [OK] nfs on tcp/2049 [OK] 1 export(s) discovered [OK] mounted /tmp/nfsdiag-AbC/export-1 (v4.2) [OK] read · write · fsync passed [OK] root_squash detected (uid 0 → nobody) summary: ok=13 warn=0 fail=0 $
# two modes
NFS problems have two possible homes: the path between the machines, or the server's own configuration. nfsdiag covers both with one binary.
| client | runs on any machine that can reach the server · discovers and mounts the exports, then exercises them: reads, writes, locks, ACLs, identity simulation, benchmarks · answers "what does this server look like from where my users are?" · client documentation |
|---|---|
| server |
runs on the NFS server itself, no second machine involved ·
audits the configuration, starting with
/etc/exports: syntax errors,
missing client lists, no_root_squash,
insecure · answers "is this server
configured the way I think it is?" ·
server documentation
|
$ sudo nfsdiag server --exports-audit nfsdiag 0.22.0: exports audit of /etc/exports [WARN] exports /srv/data: '*(rw,no_root_squash)': no_root_squash lets remote root act as local root summary: ok=0 warn=1 fail=0 $
The server namespace runs on the NFS server itself and
covers the whole
checks — exports audit,
security, live state, a Prometheus exporter, eBPF latency profiling,
HA and nfs-ganesha checks — up to paired mode, correlating a client
run and a server run to tell which side of the wire the problem is on.
# install
# Debian / Ubuntu
sudo apt-get install -y \
build-essential \
pkg-config \
libtirpc-dev \
nfs-common
git clone https://github.com/lsferreira42/nfsdiag
cd nfsdiag && make
sudo make install
# Fedora / RHEL
sudo dnf install -y \
gcc make \
pkgconf-pkg-config \
libtirpc-devel \
nfs-utils
git clone https://github.com/lsferreira42/nfsdiag
cd nfsdiag && make
sudo make install
# OCI image — no build required
docker run --rm --privileged \
ghcr.io/lsferreira42/nfsdiag \
client 192.168.1.10
Pre-built binaries (amd64 & arm64), .deb,
.rpm, and .apk on the
latest GitHub release ↗.
Releases also include checksums, SBOM, provenance, and an OCI image.
Packaging templates for Homebrew, AUR, Nix, Docker, DEB, RPM and APK
live under packaging/.
# what it checks
| network |
rpcbind tcp/111 · NFS
tcp/2049 · IPv4/IPv6 with fallback
· optional UDP probe
|
|---|---|
| rpc |
service map from rpcbind · mountd v1/v2/v3 · NFS v2/v3/v4/v4.1/v4.2
NULLPROC probes · lockd/NLM · statd/NSM
|
| mount |
v4.2 → v4.1 → v4 → v3 cascade · effective options parsed from
/proc/self/mountinfo
|
| fs |
close-to-open consistency · read · write ·
fsync · directory listing ·
copy_file_range ·
fallocate ·
O_DIRECT
|
| acl | POSIX ACLs · NFSv4 ACLs · generic xattrs · SELinux contexts |
| perm |
UID/GID/supplemental groups simulation · practical
root_squash detection
|
| lock |
fcntl advisory locks · NLM · NSM
|
| perf |
throughput smoke test · metadata latency · external
fio backend · deep metrics from
/proc/self/mountstats
|
| stale |
ESTALE loop · pNFS layouts ·
NFSoRDMA hints
|
| filenames | 255-byte names · spaces · colons · UTF-8 multibyte · per-rejection errno |
| delegation |
NFSv4 delegation activity via
/proc/self/mountstats
(DELEGRETURN operations)
|
| report | tagged text · UTF-8 table · NDJSON · Prometheus · JSON · HTML · evidence bundle · stable check IDs · remediation text |
# usage
client: full diagnostic — needs root for mount
sudo nfsdiag client 192.168.1.10
client: network and RPC only — no mount, no root
nfsdiag client --no-mount 192.168.1.10
simulate a specific identity (UID/GID + groups)
sudo nfsdiag client --uid 1000 --gid 1000 --groups 10,20 192.168.1.10
machine-readable report for CI / scripts
nfsdiag client --json=report.json 192.168.1.10
production audit — read-only, dry run, rate-limited
nfsdiag client --dry-run --read-only --delay-ms 500 prod-nfs.example.com
shareable HTML for a support ticket
sudo nfsdiag client --html=report.html 192.168.1.10
continuous monitoring — re-run every 60 s
sudo nfsdiag client --watch 60 192.168.1.10
stream failures with jq
sudo nfsdiag client --output-format=ndjson \
192.168.1.10 | jq 'select(.level=="fail")'
safe preset — read-only diagnostics
sudo nfsdiag client --profile safe 192.168.1.10
evidence bundle for tickets
sudo nfsdiag client --output-dir ./nfsdiag-report 192.168.1.10
server: audit /etc/exports on the NFS server
sudo nfsdiag server --exports-audit
server: audit a staged exports file before applying
nfsdiag server --exports-audit --exports-file /tmp/exports.new
compare before / after reports
nfsdiag diff before.json after.json
audit a fleet from a hosts file
sudo nfsdiag client \
--hosts-file /etc/nfs-servers.txt \
--json=audit.json
Full CLI reference with all flags, defaults, and advanced recipes in the documentation.
# documentation
The documentation is split by namespace. The client reference covers every CLI flag, all 14 Docker test fixtures, all output formats (text, table, NDJSON, Prometheus, JSON, HTML), evidence bundles, report diffing, packaging (deb/rpm/apk/OCI/Homebrew/AUR/Nix), security notes, architecture, limitations, and the changelog. The server reference covers the server-side checks.
→ client documentation→ server documentation