Problem: Static NFS Ports Are Not Applied After Upgrading to UCS 5.2

Problem

After upgrading to UCS 5.2, administrators may observe that the UCR variable nfs/ports=static no longer results in static port assignments for NFS-related services. Despite the variable being configured as documented, services such as rpc.mountd may continue to use dynamically assigned ports.

This behavior differs from UCS 5.0, where static NFS port assignments were automatically applied through the NFS service configuration.

This article explains the root cause, how to verify the issue, and how to implement a workaround to restore static NFS port assignments.

According to the UCR variable documentation, configuring the following setting should enforce static NFS ports:

nfs/ports: static

If this variable is set to 'static', fixed ports are used for the NFS services:
32767 for RPC mounts,
32765/32766 for statd and
32769 for the quota service.

Otherwise the ports are assigned dynamically.

Despite the configuration being present, systems running UCS 5.2 may still assign dynamic ports to rpc.mountd.

netstat -tulpen | grep rpc.mountd

tcp        0      0 0.0.0.0:35401           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:44333           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:57059           0.0.0.0:*               LISTEN
tcp6       0      0 :::51221                :::*                    LISTEN
tcp6       0      0 :::48273                :::*                    LISTEN
tcp6       0      0 :::37089                :::*                    LISTEN
udp        0      0 0.0.0.0:38389           0.0.0.0:*
udp        0      0 0.0.0.0:59057           0.0.0.0:*
udp        0      0 0.0.0.0:51186           0.0.0.0:*
udp6       0      0 :::36656                :::*
udp6       0      0 :::41513                :::*
udp6       0      0 :::46866                :::*

The rpc.mountd process is started without any static port parameters:

ps aufx | grep rpc.mountd

root       672  0.0  0.0   5040   436 ?        Ss   May18   0:00 /usr/sbin/rpc.mountd

The RPC registration confirms dynamically assigned ports:

rpcinfo -p localhost | grep mountd

100005    1   udp  51186  mountd
100005    1   tcp  35401  mountd
100005    2   udp  38389  mountd
100005    2   tcp  44333  mountd
100005    3   udp  59057  mountd
100005    3   tcp  57059  mountd

Environment

  • Univention Corporate Server (UCS) 5.2
  • Systems running nfs-kernel-server
  • Environments requiring static NFS ports for firewall rules, network segmentation, or compliance requirements

Example affected system:

UCS: 5.2-5 errata410
Installed: cups=2.4.2 dhcp-server=16.0 samba4=4.21 squid=5.7 ucsschool=5.2v4 5.0/ucsschool-veyon-proxy=4.9.1.12-ucs1
Upgradable: ucsschool

Root Cause

The behavior is caused by upstream changes in nfs-utils.

The following upstream commit removed the legacy nfs-config.service:

commit 2662e1ba98707014b6167e1e5bd3162d6d8f52af

Author: Neil Brown
Date: Tue Dec 6 13:27:22 2016 -0500

systemd: Remove the nfs-config.service

The changelog explains:

Now that we have /etc/nfs.conf, a lot of configuration can be read directly. So nfs-config isn’t really needed any more.

The upstream documentation further states that distributions relying on environment files should provide dedicated systemd drop-in files to continue passing daemon-specific command-line parameters.

As a consequence, the UCS mechanism that previously supplied UCR-generated values through:

/run/sysconfig/nfs-utils

is no longer consumed by the active service definitions on UCS 5.2. Therefore, parameters such as:

RPCMOUNTDOPTS="--manage-gids --port 32767"

are never passed to rpc.mountd.


Investigation

Comparison with UCS 5.0

The same configuration works as expected on UCS 5.0.

Reference system:

UCS: 5.0-10 errata1362
Installed: collabora-online=24.04.12.4 fetchmail=6.3.26 mailserver=12.0 nextcloud=31.0.9-0 ox-connector=2.3.3 oxseforucs=7.10.6-ucs5

Verification:

ucr search --brief nfs/ports

nfs/ports: static

Listening sockets:

netstat -tulpen | grep rpc.mountd

tcp        0      0 0.0.0.0:32767           0.0.0.0:*               LISTEN
tcp6       0      0 :::32767                :::*                    LISTEN
udp        0      0 0.0.0.0:32767           0.0.0.0:*
udp6       0      0 :::32767                :::*

Process arguments:

ps aufx | grep rpc.mountd

root       716  0.0  0.0  31676   152 ?        Ss   May19   0:00 /usr/sbin/rpc.mountd --manage-gids --port 32767

RPC registration:

rpcinfo -p localhost | grep mountd

100005    1   udp  32767  mountd
100005    1   tcp  32767  mountd
100005    2   udp  32767  mountd
100005    2   tcp  32767  mountd
100005    3   udp  32767  mountd
100005    3   tcp  32767  mountd

Systemd Unit Comparison

On UCS 5.0 the NFS service unit references the generated runtime configuration:

Wants=nfs-config.service
After=nfs-config.service

EnvironmentFile=-/run/sysconfig/nfs-utils

ExecStart=/usr/sbin/rpc.nfsd $RPCNFSDARGS

The generated runtime file exists:

ls -lah /run/sysconfig/nfs-utils

Output:

-rw-r--r-- 1 root root 159 Dec 19 16:36 /run/sysconfig/nfs-utils

The effective service definition also confirms that runtime arguments are passed to the NFS daemons:

systemctl show nfs-kernel-server -p ExecStart

Output:

ExecStart={ path=/usr/sbin/rpc.nfsd ; argv[]=/usr/sbin/rpc.nfsd $RPCNFSDARGS ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }

On UCS 5.2 the integration is no longer present.

Relevant section of the service unit:

ExecStart=/usr/sbin/rpc.nfsd

Verification:

systemctl show nfs-kernel-server -p ExecStart

Output:

ExecStart={ path=/usr/sbin/rpc.nfsd ; argv[]=/usr/sbin/rpc.nfsd ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }

The generated runtime file is also missing:

ls -lah /run/sysconfig/nfs-utils

Output:

ls: cannot access '/run/sysconfig/nfs-utils': No such file or directory

Workaround

Create a dedicated systemd override for nfs-mountd.service.

Create the Drop-In Directory

mkdir -p /etc/systemd/system/nfs-mountd.service.d

Create the Override Configuration

cat >/etc/systemd/system/nfs-mountd.service.d/ucr.conf <<'EOF'
[Service]
EnvironmentFile=/etc/default/nfs-kernel-server
ExecStart=
ExecStart=/usr/sbin/rpc.mountd $RPCMOUNTDOPTS
EOF

Reload systemd

systemctl daemon-reload

Restart the Service

systemctl restart nfs-mountd

Verification

Verify the RPC registration:

rpcinfo -p localhost | grep mountd

Expected output:

100005    1   udp  32767  mountd
100005    1   tcp  32767  mountd
100005    2   udp  32767  mountd
100005    2   tcp  32767  mountd
100005    3   udp  32767  mountd
100005    3   tcp  32767  mountd

Verify the listening sockets:

netstat -tulpen | grep rpc.mountd

Expected output:

tcp        0      0 0.0.0.0:32767           0.0.0.0:*               LISTEN
tcp6       0      0 :::32767                :::*                    LISTEN
udp        0      0 0.0.0.0:32767           0.0.0.0:*
udp6       0      0 :::32767                :::*

Verify the process arguments:

ps aufx | grep rpc.mountd

Expected output:

/usr/sbin/rpc.mountd --manage-gids --port 32767

References

Upstream nfs-utils changelog:

Relevant upstream change:

commit 2662e1ba98707014b6167e1e5bd3162d6d8f52af
Author: NeilBrown <neilb@suse.com>
Date:   Tue Dec 6 13:27:22 2016 -0500

    systemd: Remove the nfs-config.service
    
    Now that we have /etc/nfs.conf, a lot of configuration can be
    read directly.  So nfs-config isn't really needed any more.
    
    Some distributions allow command-line arguments for various
    daemons to be set in an environment file (/etc/sysconfig,
    /etc/defaults).
    Passing these through /etc/nfs.conf is not possible.
    
    Instead, a distro that needs this functionality can create drop-in
    files which select the required value.  As no commands are given
    default arguments by systemd unit files, the drop-in can just add
    distro-specific args.
    For example
      /lib/systemd/system/nfs-mountd.service.d/local.conf
       [Service]
       EnvironmentFile=/etc/sysconfig/nfs
       ExecStart=
       ExecStart=/usr/sbin/rpc.mountd $RPCMOUNTDOPTS
    
    Note the need for the empty assignment to remove existing definitions
    first.
    
    Signed-off-by: NeilBrown <neilb@suse.com>
    Signed-off-by: Steve Dickson <steved@redhat.com>

Conclusion

On UCS 5.2, the UCR variable nfs/ports=static may no longer be sufficient to enforce static NFS port assignments because the legacy nfs-config.service integration from older nfs-utils releases is no longer present. As a result, UCR-generated parameters are not automatically passed to rpc.mountd, causing dynamic port allocation.

Until the integration is adapted to the current upstream architecture, administrators requiring static NFS ports can restore the previous behavior by creating a systemd drop-in that explicitly passes the generated mountd parameters to the service.

This issue is currently tracked by Univention as Bug #59467. For the latest status and implementation progress, please refer to: