DevOps · K8s · Volleyball · Travel  •  DevOps · K8s · Volleyball · Travel  •  DevOps · K8s · Volleyball · Travel
Explore NY Stream

How To Configure Static Ports for NFS on Linux

— ny_wk

How To Configure Static Ports for NFS on Linux

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 mount handshake).
  • 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/nfs with variables like MOUNTD_PORT.
  • Debian/Ubuntu legacy used /etc/default/nfs-kernel-server and /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).

  1. Back up the config first.
    cp /etc/nfs.conf /etc/nfs.conf.bak
  2. Edit /etc/nfs.conf and 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 = 32765
    outgoing-port = 32766
    [lockd]
    port = 32803
    udp-port = 32769
  3. Set the rquotad port if you export quotas. On nfs-utils-based systems rquotad reads its port from /etc/sysconfig/rpc-rquotad (RHEL) via the RPCRQUOTADOPTS variable, e.g.
    RPCRQUOTADOPTS="-p 875"
    Port 875 is the conventional rquotad port.
  4. Restart the NFS server and lock services so the new bindings apply:
    systemctl restart nfs-server
    systemctl restart rpc-statd
    On some systems statd is socket-activated; systemctl restart nfs-server plus a reboot guarantees a clean state if a daemon refuses to rebind.
  5. 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:

  1. Log in as root and back up the file:
    cp /etc/sysconfig/nfs /etc/sysconfig/nfs.bak
  2. 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=10002
    STATD_OUTGOING_PORT=10003
    MOUNTD_PORT=10004
    LOCKD_TCPPORT=10001
    LOCKD_UDPPORT=10001
    RQUOTAD_PORT=10005
  3. 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 stop
    service rpcbind restart
    service nfs start
    (On very old RHEL/CentOS 6 the portmapper service is named portmap; on 7 it is rpcbind. service nfslock restart may 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:

ServiceProtocolExample portConventional default
rpcbind / portmapperTCP + UDP111111 (fixed)
nfsdTCP + UDP20492049 (fixed)
rpc.mountdTCP + UDP1000420048 / 892
rpc.statdTCP + UDP10002662
statd outgoingUDP100032020
lockd (NLM)TCP + UDP1000132803 / 32769
rpc.rquotadTCP + UDP10005875

With firewalld, open them like this (adjust to your chosen numbers):

  1. firewall-cmd --permanent --add-service=nfs (covers 2049)
  2. firewall-cmd --permanent --add-service=rpc-bind (covers 111)
  3. firewall-cmd --permanent --add-service=mountd
  4. firewall-cmd --permanent --add-port=10001-10005/tcp
  5. firewall-cmd --permanent --add-port=10001-10005/udp
  6. firewall-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.

  1. Dump the RPC registration table:
    rpcinfo -p
    Output should show your chosen ports next to mountd, nlockmgr (lockd), status (statd), and rquotad, for example:
    program vers proto  port  service
    100000   4   tcp   111  portmapper
    100003   3   tcp  2049  nfs
    100005   3   tcp 10004  mountd
    100021   4   tcp 10001  nlockmgr
    100024   1   tcp 10002  status
    100011   2   tcp 10005  rquotad
  2. Confirm the daemons are actually bound to those sockets:
    ss -tlnp | grep -E '10001|10002|10004|10005'
    (or netstat -tulpn on older hosts).
  3. Test from a client — the real proof:
    showmount -e nfs-server.example.com
    mount -t nfs nfs-server.example.com:/export /mnt
    then create a file and test a lock with flock to 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/nfs may be ignored — use /etc/nfs.conf. On RHEL 6/7 the reverse can apply. Always verify with rpcinfo -p afterward.
  • 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.statd sends notifications from a port too; if you do not pin outgoing-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. If nlockmgr still shows a random port after a restart, set those and reboot.
  • Port collisions. Pick ports that nothing else uses. Check with ss -tlnp before assigning.
  • Not restarting rpcbind. If a daemon registered on an old port, restart rpcbind and 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 recent and label the port if needed with semanage 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:

  1. Ensure exports advertise v4 (it is the default on modern nfs-utils).
  2. Mount with mount -t nfs -o vers=4.2 server:/export /mnt.
  3. 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.conf on RHEL/Rocky/Alma 8+ and modern distros; /etc/sysconfig/nfs only 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 -p and 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.