How To Configure Static Ports for NFS on Linux
— ny_wk

Configuring static NFS ports on Linux means pinning the helper RPC services (lockd, statd, mountd, and rquotad) to fixed TCP/UDP port numbers instead of the random ports portmap normally hands out. That single change is what makes NFS workable through a firewall, because you can finally write specific allow rules instead of opening huge port ranges.
By default the NFS stack relies on the RPC portmapper (now rpcbind) to assign ephemeral ports to its auxiliary daemons each time they start. Those ports change across reboots, so any firewall, security group, or NAT rule between client and server breaks the moment the daemon picks a different port. The fix is to assign static NFS ports to every RPC service so the firewall rules stay valid forever.
The Problem: NFS Uses Random Ports Behind a Firewall
An NFS server is not a single listener. The kernel nfsd service itself sits on the well-known port 2049, but mounting and locking depend on several user-space helper daemons that each register with the portmapper and grab whatever free port is available:
- rpc.mountd — handles mount requests (the actual
mounthandshake). - rpc.statd (part of
nfs-lock/ NSM) — status monitoring used by file locking. - lockd (in-kernel NLM) — the Network Lock Manager for NFSv2/v3 advisory locks.
- rpc.rquotad — serves disk-quota queries to remote clients.
Because these ports are randomly assigned, a stateful firewall cannot pre-authorize them. Clients hang on mount, locking fails silently, and quota lookups time out. Pinning each service to a known port number solves all three symptoms at once. Note that this random-port problem is largely specific to NFSv2 and NFSv3; if you can move to NFSv4, the entire conversation simplifies (covered near the end).
The Solution: Assign Static NFS Ports
The approach is the same on every modern Linux distribution: tell each RPC daemon which port to bind, restart the NFS services so the new ports take effect, then open exactly those ports on the firewall. The configuration file differs by distribution and version, which is the single most common source of confusion.
Where the configuration lives (this matters)
- Modern systems (RHEL/CentOS/Rocky/AlmaLinux 8+, Fedora, recent Debian/Ubuntu with nfs-utils ≥ 1.3) use
/etc/nfs.conf— an INI-style file with[mountd],[statd],[lockd]sections. This is the current, supported method. - Legacy systems (RHEL/CentOS 6 and 7, older derivatives) use the shell-style
/etc/sysconfig/nfswith variables likeMOUNTD_PORT. - Debian/Ubuntu legacy used
/etc/default/nfs-kernel-serverand/etc/default/nfs-common.
RHEL/CentOS 7 are a transition case: /etc/sysconfig/nfs still works, but the values are read in and translated. If you are on a current release, prefer /etc/nfs.conf.
Step-by-Step: Static NFS Ports on RHEL/Rocky/Alma 8+ (nfs.conf)
This is the recommended path for any supported system. All commands run as root (or with sudo).
- Back up the config first.
cp /etc/nfs.conf /etc/nfs.conf.bak - Edit
/etc/nfs.confand set explicit ports in the relevant sections. Pick ports that are free and easy to remember — the example below uses the 10001–10005 range:[mountd]port = 20048[statd]port = 32765outgoing-port = 32766[lockd]port = 32803udp-port = 32769 - Set the rquotad port if you export quotas. On nfs-utils-based systems rquotad reads its port from
/etc/sysconfig/rpc-rquotad(RHEL) via theRPCRQUOTADOPTSvariable, e.g.RPCRQUOTADOPTS="-p 875"
Port 875 is the conventional rquotad port. - Restart the NFS server and lock services so the new bindings apply:
systemctl restart nfs-serversystemctl restart rpc-statd
On some systems statd is socket-activated;systemctl restart nfs-serverplus a reboot guarantees a clean state if a daemon refuses to rebind. - Enable the services at boot so the configuration survives a reboot:
systemctl enable --now rpcbind nfs-server
Step-by-Step: Static NFS Ports on Legacy RHEL/CentOS 6/7 (sysconfig)
If you are maintaining an older server — this is the method described in many older runbooks — the file is /etc/sysconfig/nfs. Important: RHEL 6/7 reached end of maintenance; treat this section as life-support for legacy hosts and plan a migration. The mechanics:
- Log in as root and back up the file:
cp /etc/sysconfig/nfs /etc/sysconfig/nfs.bak - Uncomment or append the port variables. A clean, internally consistent set looks like this (each service gets its own dedicated port; only lockd shares one number across TCP and UDP, which is expected):
STATD_PORT=10002STATD_OUTGOING_PORT=10003MOUNTD_PORT=10004LOCKD_TCPPORT=10001LOCKD_UDPPORT=10001RQUOTAD_PORT=10005 - Save and close the file, then restart the stack. The correct order matters — restart the portmapper before NFS so the daemons can register on the new ports:
service nfs stopservice rpcbind restartservice nfs start
(On very old RHEL/CentOS 6 the portmapper service is namedportmap; on 7 it isrpcbind.service nfslock restartmay also be needed to rebind statd/lockd.)
The original sample many admins copy from the stock file lists defaults such as LOCKD_TCPPORT=32803, LOCKD_UDPPORT=32769, MOUNTD_PORT=892, STATD_PORT=662, and RQUOTAD_PORT=875. Those are perfectly valid choices too — the only requirement is that the ports are free and that your firewall rules match whatever you pick.
Recommended Port Map for the Firewall
Once your services are pinned, document the assignments so the networking and security teams can build matching rules. A typical layout:
| Service | Protocol | Example port | Conventional default |
| rpcbind / portmapper | TCP + UDP | 111 | 111 (fixed) |
| nfsd | TCP + UDP | 2049 | 2049 (fixed) |
| rpc.mountd | TCP + UDP | 10004 | 20048 / 892 |
| rpc.statd | TCP + UDP | 10002 | 662 |
| statd outgoing | UDP | 10003 | 2020 |
| lockd (NLM) | TCP + UDP | 10001 | 32803 / 32769 |
| rpc.rquotad | TCP + UDP | 10005 | 875 |
With firewalld, open them like this (adjust to your chosen numbers):
firewall-cmd --permanent --add-service=nfs(covers 2049)firewall-cmd --permanent --add-service=rpc-bind(covers 111)firewall-cmd --permanent --add-service=mountdfirewall-cmd --permanent --add-port=10001-10005/tcpfirewall-cmd --permanent --add-port=10001-10005/udpfirewall-cmd --reload
The built-in nfs, rpc-bind, and mountd firewalld services handle the standard ports; the explicit port range covers the helper daemons you pinned.
Verification: Confirm the Static NFS Ports Are Live
Never assume the change took — verify it. The authoritative check is rpcinfo, which queries the portmapper and lists every registered RPC program with its program number, version, protocol, and port.
- Dump the RPC registration table:
rpcinfo -p
Output should show your chosen ports next tomountd,nlockmgr(lockd),status(statd), andrquotad, for example:program vers proto port service100000 4 tcp 111 portmapper100003 3 tcp 2049 nfs100005 3 tcp 10004 mountd100021 4 tcp 10001 nlockmgr100024 1 tcp 10002 status100011 2 tcp 10005 rquotad - Confirm the daemons are actually bound to those sockets:
ss -tlnp | grep -E '10001|10002|10004|10005'
(ornetstat -tulpnon older hosts). - Test from a client — the real proof:
showmount -e nfs-server.example.commount -t nfs nfs-server.example.com:/export /mnt
then create a file and test a lock withflockto confirm lockd/statd work end-to-end.
Common Pitfalls When Pinning Static NFS Ports
- Editing the wrong file. On RHEL 8+ edits to
/etc/sysconfig/nfsmay be ignored — use/etc/nfs.conf. On RHEL 6/7 the reverse can apply. Always verify withrpcinfo -pafterward. - Forgetting UDP. NFSv3 locking and statd use UDP as well as TCP. A firewall rule that only opens TCP will produce mounts that work but locks that hang.
- Skipping the statd outgoing port.
rpc.statdsends notifications from a port too; if you do not pinoutgoing-port/STATD_OUTGOING_PORT, reboot-recovery notifications can be blocked. - Leaving lockd random. lockd is in-kernel; on some kernels its ports are set via sysctl (
fs.nfs.nlm_tcpport/fs.nfs.nlm_udpport) rather than the config file. Ifnlockmgrstill shows a random port after a restart, set those and reboot. - Port collisions. Pick ports that nothing else uses. Check with
ss -tlnpbefore assigning. - Not restarting rpcbind. If a daemon registered on an old port, restart
rpcbindand the NFS services so stale registrations are cleared. - SELinux. SELinux generally permits the standard NFS ports, but very unusual port numbers can be denied. If a daemon fails to bind with SELinux enforcing, check
ausearch -m avc -ts recentand label the port if needed withsemanage port.
The Modern Shortcut: Just Use NFSv4
The entire static-port exercise exists because of the RPC sideband services in NFSv2/v3. NFSv4 collapses all of this onto a single port — 2049. Locking is integrated into the protocol, there is no separate lockd/statd negotiation over random ports, and you do not even strictly need rpcbind. If your clients and server support it, exporting NFSv4-only is by far the cleanest firewall story:
- Ensure exports advertise v4 (it is the default on modern nfs-utils).
- Mount with
mount -t nfs -o vers=4.2 server:/export /mnt. - Open only TCP 2049 on the firewall — done.
Stick with the static-port method only when you must support legacy NFSv3 clients (older appliances, storage filers, or applications that depend on NLM locking). For everything else, NFSv4 is the right answer and avoids the random-port problem entirely.
Key Takeaways
- Static NFS ports exist to make NFSv3 work through a firewall by pinning mountd, statd, lockd, and rquotad to fixed numbers instead of random portmapper assignments.
- Use
/etc/nfs.confon RHEL/Rocky/Alma 8+ and modern distros;/etc/sysconfig/nfsonly on legacy RHEL/CentOS 6/7. - Open both TCP and UDP for every pinned service, including the statd outgoing port, or locking will mysteriously hang.
- Always verify with
rpcinfo -pand a real client mount — never assume the edit applied. - If you can, switch to NFSv4, which uses only port 2049 and eliminates the static-port juggling completely.
Frequently Asked Questions
What port does NFS use by default?
The core NFS service (nfsd) always listens on TCP/UDP 2049, and the RPC portmapper (rpcbind) uses 111. The helper daemons — mountd, statd, lockd, and rquotad — get random ephemeral ports unless you pin them, which is exactly why static configuration is needed behind a firewall.
How do I find which ports NFS is currently using?
Run rpcinfo -p on the NFS server. It prints every registered RPC program with its protocol and port, so you can read off the live ports for mountd (mountd), lockd (nlockmgr), statd (status), and quotas (rquotad). Cross-check the listening sockets with ss -tlnp.
Why does my NFS mount succeed but file locking hangs?
That is the classic sign of a blocked lockd/statd port or a missing UDP rule. The mount handshake (mountd, port 2049) got through, but the Network Lock Manager could not reach its random port. Pin lockd and statd to static ports, open them on both TCP and UDP, and include the statd outgoing port.
Do I still need static ports if I use NFSv4?
No. NFSv4 carries locking and all operations over a single port, 2049, so there are no random sideband ports to pin. Open TCP 2049 and you are done. Static ports are only required when supporting older NFSv2/v3 clients that rely on separate RPC services.
For more Linux and system-administration walkthroughs, subscribe on YouTube @explorenystream.