Chapter 24 addresses cross-platform file sharing needs through Samba, suitable for situations where Windows and Linux must share the same folder. The scenario in Chapter 25 is slightly different. Suppose the Developer team has added a second application server (app-02) behind the load balancer we built in Chapter 16, and the first report comes in: files uploaded by users through app-01 do not appear when subsequent requests are served by app-02, because both are still storing files on their respective local disks. This is a classic horizontal scaling architecture issue, and the most common solution in a pure Linux environment is NFS (Network File System), a file sharing protocol designed specifically for fellow Unix/Linux systems, without the Windows compatibility overhead brought by SMB/CIFS. We will understand the concepts and evolution of NFS, install the NFS server and client on Ubuntu Server 26.04 LTS, export a shared directory via /etc/exports, and then close the chapter with two mounting methods from the client side: permanent mounting via /etc/fstab and automatic on-demand mounting via autofs.
25.1 NFS Concepts and Use Cases
This section equips us with a foundational understanding of NFS before diving into installation: what sets it apart from Samba, how its versions evolved, and when this protocol is truly the right choice.
25.1.1 What Is NFS and How It Works
NFS is a network protocol that allows one system (NFS server) to share a portion of its disk directories, and another system (NFS client) to mount that directory so that it appears and behaves exactly like a local directory. The protocol was originally developed by Sun Microsystems in 1984 and has since become the de facto standard for file sharing in Unix and Linux environments, long before Samba emerged to bridge Linux with the Windows world.
The fundamental difference between NFS and Samba lies in its authentication layer. Samba requires every user to log in with dedicated Samba credentials, whereas classic NFS (NFSv3 and default NFSv4 without Kerberos) uses host-based trust, where the server only checks which IP address or subnet the request originates from, and simply trusts the UID and GID sent by the client. This trust model makes NFS much lighter and faster to set up for trusted internal networks, such as between application servers behind a load balancer, but it also means NFS must never be exposed indiscriminately to untrusted networks. These security details are discussed in depth in Sections 25.3 and 25.5.
25.1.2 Version Evolution: NFSv2, NFSv3, and NFSv4
Like SMB in Chapter 24, NFS has also gone through several major generations that affect how we configure it today.
| Version | Key Characteristics |
|---|---|
| NFSv2 | Initial version from the 1980s era, limited to file sizes under 2 GB and UDP transport. This version has long been irrelevant for modern deployments. |
| NFSv3 | Released in 1995, adding support for large files (64-bit file size) and asynchronous operations. Purely stateless: each request stands alone without the server needing to remember client sessions, thus still requiring separate helper services such as rpcbind, mountd, and lockd for mounting and file locking. |
| NFSv4 | Modern generation (NFSv4.0 released in 2000, refined through NFSv4.1 and NFSv4.2). Stateful, consolidating all mounting, locking, and file access functions into a single TCP connection on port 2049, no longer depending on rpcbind for normal operations. This version supports string-based user identity representations (user@domain) rather than raw numerical UIDs/GIDs like NFSv3, and optionally supports Kerberos authentication for tighter security. |
Ubuntu Server 26.04 LTS, like previous releases, automatically negotiates the highest NFS version supported mutually between server and client as soon as the client uses the generic filesystem type nfs when mounting, so in practice NFSv4 is always the first choice without needing to force it via additional parameters. We will still write out versions explicitly in several examples throughout this chapter so that behavior remains clear and easy to diagnose during troubleshooting.
25.1.3 NFS vs Samba: When to Choose Which
A question frequently raised by Sysadmins new to these two technologies: if Samba is already available, why is NFS still needed? The answer lies in the domain of audience and overhead. Samba is mandatory as soon as there are Windows or macOS clients that need to share access, whereas NFS is significantly lighter and simpler for pure Linux-to-Linux scenarios, such as shared storage between cluster nodes, centralized home directories for multiple servers, or the app-02 case discussed in the opening of this chapter. There is no strict rule forbidding both from running simultaneously on a single server, as each protocol serves different shares, tailored to whichever client will be accessing them.
25.2 Installing NFS Server and Client
This section installs NFS components on both sides: nfs-kernel-server on our main server (192.168.1.10), and nfs-common on app-02 as the client that will later mount the shared upload directory.
25.2.1 Installing Packages on the Server
Hands-on Steps
- On the main server, update the package list, then install
nfs-kernel-server. This package automatically pulls in several supporting dependencies such asrpcbind, which is still required for NFSv3 client compatibility even though our primary focus in this chapter is NFSv4.sudo apt update sudo apt install -y nfs-kernel-server - Ensure the main service is active and enabled to start automatically on boot.
sudo systemctl enable --now nfs-kernel-server
Verification and Troubleshooting
- Confirm the service status.
systemctl status nfs-kernel-server --no-pager - Check the NFS versions currently supported by the server kernel.
An output such ascat /proc/fs/nfsd/versions-2 -3 +4 +4.1 +4.2indicates that NFSv4 and its minor versions (4.1 and 4.2) are active, while NFSv2 and NFSv3 (marked with minuses) are disabled by default.
25.2.2 Installing Packages on the Client
Hands-on Steps
- On
app-02, installnfs-common, a collection of client tools providing NFS mounting support along with utilities likeshowmount.sudo apt update sudo apt install -y nfs-common
Verification and Troubleshooting
- Test basic connectivity from
app-02to the server to verify the NFS port is reachable before proceeding to export configuration.
If the connection is refused, it is highly likely that the firewall on the server has not yet opened port 2049, a step performed in Section 25.3.3.nc -zv 192.168.1.10 2049
25.2.3 Understanding /etc/nfs.conf
Since recent releases of nfs-utils, all operational NFS settings (number of nfsd threads, mountd ports, and others) are centralized into a single INI-style file at /etc/nfs.conf, supplemented by a drop-in directory /etc/nfs.conf.d/ for additional configuration snippets without directly editing the main file. This pattern is similar to systemd unit drop-ins covered in Chapter 5.
Hands-on Steps
- View the effective configuration currently used by NFS, which combines default values and all active configuration files.
sudo nfsconf --dump
Verification and Troubleshooting
- We do not need to modify
/etc/nfs.conffor the basic scenarios in this chapter, but knowing this file exists is important for advanced requirements such as restricting themountdport range for easier whitelisting by strict firewalls.
25.3 Exporting Directories via /etc/exports
This section prepares the directory /srv/nfs/uploads on the main server as the shared file upload storage location, then exports it so it can be accessed by app-02 and other application servers that Developers might add in the future.
25.3.1 Preparing Directory and Permissions
Hands-on Steps
- Create the directory where upload files will be stored, then assign ownership to user
www-data, the same user used by Nginx and PHP-FPM workers since Chapter 12 and Chapter 14.sudo mkdir -p /srv/nfs/uploads sudo chown www-data:www-data /srv/nfs/uploads - Apply permission
2775, following the same setgid bit pattern as in Section 24.3.1 so that new files created by any process retain ownership under thewww-datagroup.sudo chmod 2775 /srv/nfs/uploads
Verification and Troubleshooting
- Verify ownership and setgid bit are properly configured.
ls -ld /srv/nfs/uploads
25.3.2 Writing Export Lines and Key Options
Hands-on Steps
- Open
/etc/exports, then add an export entry line for the upload directory.sudo nano /etc/exports
Each option within parenthesis carries vital meaning. The/srv/nfs/uploads 192.168.1.0/24(rw,sync,no_subtree_check,root_squash)rwoption permits write activities, not just read access. Thesyncoption requires the server to write changes to disk before responding to the client with a success status; this option is slower thanasyncbut significantly safer against data corruption risks during sudden server power outages. Theno_subtree_checkoption disables extra subtree checking within the same filesystem; this option has become the default recommendation for nfs-utils as subtree checking frequently causes issues, particularly when opened files are renamed. Theroot_squashoption (default value even if omitted explicitly) maps therootuser on the client side to thenobodyuser when writing to the share, preventing root on a client from freely modifying files owned by other users over NFS. This is a security layer that should never be disabled (no_root_squash) unless there is a specific, well-understood requirement. - Note the access target
192.168.1.0/24. We intentionally restrict access to the internal subnet range whereapp-02resides, rather than using a wildcard*that allows universal access. Because NFS relies on host-based trust as explained in Section 25.1.1, client restriction at the/etc/exportslevel serves as the first line of defense before the firewall in the next step.
Verification and Troubleshooting
- Run
exportfsin verbose mode to catch typos immediately.exportfsdoes not feature a separate "check-only" mode, so this command applies the newly written line as long as no errors are present, exactly as we will officially do in Section 25.3.3.
The messagesudo exportfs -avexportfs: Failed to stat /srv/nfs/uploadsindicates that the specified path contains a typo or the directory was not actually created in Section 25.3.1.
25.3.3 Applying Exports and Opening Firewalls
Hands-on Steps
- Apply all lines in
/etc/exportsto the kernel's active export table. Combining the-rflag (re-export, which resynchronizes all contents including purging removed entries) and-a(export all lines) is the safest practice whenever/etc/exportsedits are complete.sudo exportfs -ra - Open firewall ports for NFSv4, restricted strictly to the same internal subnet specified in
/etc/exports, rather than opening it globally to all networks.
Since we rely solely on NFSv4 using a single port, we do not need to open extra ports like 111 (sudo ufw allow from 192.168.1.0/24 to any port 2049 proto tcprpcbind) or dynamic port ranges formountdrequired when legacy NFSv3 clients are supported.
Verification and Troubleshooting
- Display currently active exports and options directly from the server.
sudo exportfs -v - From
app-02, confirm the share is visible client-side prior to performing actual mounting.
This command functions even when focusing on NFSv4, becauseshowmount -e 192.168.1.10rpc.mountdruns on the server for legacyMOUNTprotocol handling as well as tooling likeshowmount. - The message
clnt_create: RPC: Port mapper failure - Unable to receive: errno 113 (No route to host)when runningshowmountalmost always indicates server-side firewall rules are blocking traffic; recheck previous steps usingsudo ufw status numbered.
25.4 Mounting NFS Shares from Linux Clients
The share is exported and accessible. This section handles mounting from app-02, ensuring persistence across server reboots, and concludes with automatic on-demand mounting via autofs for dynamic scenarios.
25.4.1 Manual Mounting and Read/Write Testing
Hands-on Steps
- Create a mount point on
app-02, then mount the share manually for initial verification.sudo mkdir -p /mnt/nfs/uploads sudo mount -t nfs4 192.168.1.10:/srv/nfs/uploads /mnt/nfs/uploads - Test file writing from
app-02, then verify the file is stored on the server.touch /mnt/nfs/uploads/test-dari-app02.txt ls -l /mnt/nfs/uploads
Verification and Troubleshooting
- Confirm the mount point is mounted using NFSv4.
df -hT /mnt/nfs/uploads - Return to the server and confirm the test file appears in
/srv/nfs/uploads, proving writes from the client land on server storage rather than local storage onapp-02.ls -l /srv/nfs/uploads - The error
mount.nfs4: access denied by server while mountingtypically indicates that the IP address ofapp-02falls outside the allowed subnet range specified in Section 25.3.2, or export entries have not been reloaded usingexportfs -ra.
25.4.2 Permanent Mounting via /etc/fstab
Hands-on Steps
- Unmount the manual mount to avoid conflicts during
/etc/fstabtesting.sudo umount /mnt/nfs/uploads - Add the following entry to
/etc/fstabonapp-02.
Similar to CIFS mounts in Section 24.5.2, the192.168.1.10:/srv/nfs/uploads /mnt/nfs/uploads nfs4 defaults,_netdev 0 0_netdevoption tells systemd that this filesystem relies on network connectivity, delaying mount execution during boot until the network is ready. - Test the entry without rebooting the server.
sudo mount -a df -hT /mnt/nfs/uploads
Verification and Troubleshooting
- If
sudo mount -aexecutes without error but the mount does not appear indf, verify/etc/fstabsyntax usingfindmnt --verify, a tool designed specifically to validate/etc/fstabwithout mounting filesystems.
25.4.3 On-Demand Mounting with autofs
Permanent mounts via /etc/fstab suit shares that are continuously required, such as /srv/nfs/uploads on app-02. Consider a different scenario: Developers manage dozens of project directories on an NFS server, and workstations only occasionally access specific ones. Permanently mounting all shares via /etc/fstab wastes resources because mounts remain connected when idle. autofs solves this issue: NFS directories are mounted dynamically upon first access and automatically unmounted after an idle timeout period (defaulting to approximately 10 minutes, configurable via the timeout option).
Hands-on Steps
- Install the
autofspackage onapp-02.sudo apt install -y autofs - Register a new master map in
/etc/auto.master.d/pointing to mount point/mnt/nfs/autoand a separate map file namedauto.nfs. Using theauto.master.d/directory is safer than editing/etc/auto.masterdirectly, matching thesudoers.d/drop-in pattern from Chapter 4.sudo nano /etc/auto.master.d/nfs.autofs/mnt/nfs/auto /etc/auto.nfs --timeout=60 - Create an indirect map file
/etc/auto.nfsdefining subdirectories under/mnt/nfs/auto.sudo nano /etc/auto.nfs
This line configuresuploads -fstype=nfs4,rw 192.168.1.10:/srv/nfs/uploadsautofsto automatically mount192.168.1.10:/srv/nfs/uploadsvia NFSv4 as soon as a process accesses/mnt/nfs/auto/uploads. - Restart the
autofsservice to reload map configurations.sudo systemctl restart autofs
Verification and Troubleshooting
- Access the directory and check if the mount triggers automatically.
ls /mnt/nfs/auto/uploads mount | grep uploads - Wait over 60 seconds without accessing the directory, then recheck with
mount | grep uploads. The mount entry should disappear, verifying that automatic unmounting works according to the configured--timeout=60parameter. - If
ls /mnt/nfs/auto/uploadsreturns an empty listing without error andmountshows no entries, inspectautofslogs viajournalctl -u autofs -n 30to check for map mapping rejection messages.
25.5 NFS Troubleshooting and Security Practices
This concluding section addresses two common operational issues in production NFS environments: file ownership discrepancies and tracking active share connections.
25.5.1 The UID/GID Issue: Why Files Display as nobody:nogroup
This is a common pitfall encountered when configuring NFSv4. Unlike NFSv3, which passes raw numerical UIDs and GIDs, NFSv4 sends ownership identities across the network protocol formatted as user@domain strings. The process converting local numeric UIDs into strings (and vice versa) is called ID mapping, handled by nfsidmap based on the Domain parameter in /etc/idmapd.conf. If the Domain values on the server and client mismatch, translation fails silently, causing mounted share files to appear owned by nobody:nogroup even if numeric UIDs on both hosts match.
Hands-on Steps
- Align the
Domainparameter in/etc/idmapd.confon both the server andapp-02, using the same internal domain as the DNS zone from Chapter 9.sudo nano /etc/idmapd.conf[General] Domain = example.local - Clear cached ID mappings that may store old translations, then remount the share.
sudo nfsidmap -c sudo umount /mnt/nfs/uploads sudo mount -a
Verification and Troubleshooting
- After remounting, verify ownership of the test file created in Section 25.4.1.
Ownership should reflectls -l /mnt/nfs/uploadswww-datainstead ofnobody:nogroup. - Field note: The most effective long-term solution goes beyond matching
Domainsettings by ensuring numeric UIDs and GIDs for key service accounts likewww-datamatch across all servers connected over NFS. For large server environments, adjusting UIDs/GIDs manually becomes impractical; this is where centralized identity sources such as LDAP mentioned in Chapter 4 become essential.
25.5.2 Monitoring Active Connections and Exports
Hands-on Steps
- Display general NFS server operational statistics to verify server traffic from expected clients.
nfsstat -s - View active export lists prior to modifying
/etc/exportsentries.sudo exportfs -v
Verification and Troubleshooting
- NFS does not offer real-time connection dashboards comparable to
smbstatusin Samba. To audit active mounts, check server firewall connection logs (sudo ufw status verbose) or inspect active TCP connections on port 2049.sudo ss -tnp | grep :2049
At this stage, our primary server functions as an NFS server, exporting /srv/nfs/uploads with defined permissions and security options, accessed from app-02 via permanent /etc/fstab mounting as well as on-demand autofs mounting. Together with Samba in Chapter 24, this section completes file sharing requirements for both cross-platform and pure Linux environments. Chapter 26 introduces Part VII with containerization topics via Docker, covering fundamental concepts through initial container execution commands.

