NFS: File Sharing between Linux Systems

NFS: File Sharing between Linux Systems

Bitnesia Aug 28, 2026 2 ID

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.

VersionKey Characteristics
NFSv2Initial version from the 1980s era, limited to file sizes under 2 GB and UDP transport. This version has long been irrelevant for modern deployments.
NFSv3Released 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.
NFSv4Modern 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

  1. On the main server, update the package list, then install nfs-kernel-server. This package automatically pulls in several supporting dependencies such as rpcbind, 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
  2. 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.
    cat /proc/fs/nfsd/versions
    An output such as -2 -3 +4 +4.1 +4.2 indicates 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

  1. On app-02, install nfs-common, a collection of client tools providing NFS mounting support along with utilities like showmount.
    sudo apt update
    sudo apt install -y nfs-common

Verification and Troubleshooting

  • Test basic connectivity from app-02 to the server to verify the NFS port is reachable before proceeding to export configuration.
    nc -zv 192.168.1.10 2049
    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.

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

  1. 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.conf for the basic scenarios in this chapter, but knowing this file exists is important for advanced requirements such as restricting the mountd port 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

  1. 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
  2. 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 the www-data group.
    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

  1. Open /etc/exports, then add an export entry line for the upload directory.
    sudo nano /etc/exports
    /srv/nfs/uploads  192.168.1.0/24(rw,sync,no_subtree_check,root_squash)
    Each option within parenthesis carries vital meaning. The rw option permits write activities, not just read access. The sync option requires the server to write changes to disk before responding to the client with a success status; this option is slower than async but significantly safer against data corruption risks during sudden server power outages. The no_subtree_check option 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. The root_squash option (default value even if omitted explicitly) maps the root user on the client side to the nobody user 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.
  2. Note the access target 192.168.1.0/24. We intentionally restrict access to the internal subnet range where app-02 resides, 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/exports level serves as the first line of defense before the firewall in the next step.

Verification and Troubleshooting

  • Run exportfs in verbose mode to catch typos immediately. exportfs does 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.
    sudo exportfs -av
    The message exportfs: Failed to stat /srv/nfs/uploads indicates 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

  1. Apply all lines in /etc/exports to the kernel's active export table. Combining the -r flag (re-export, which resynchronizes all contents including purging removed entries) and -a (export all lines) is the safest practice whenever /etc/exports edits are complete.
    sudo exportfs -ra
  2. Open firewall ports for NFSv4, restricted strictly to the same internal subnet specified in /etc/exports, rather than opening it globally to all networks.
    sudo ufw allow from 192.168.1.0/24 to any port 2049 proto tcp
    Since we rely solely on NFSv4 using a single port, we do not need to open extra ports like 111 (rpcbind) or dynamic port ranges for mountd required 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.
    showmount -e 192.168.1.10
    This command functions even when focusing on NFSv4, because rpc.mountd runs on the server for legacy MOUNT protocol handling as well as tooling like showmount.
  • The message clnt_create: RPC: Port mapper failure - Unable to receive: errno 113 (No route to host) when running showmount almost always indicates server-side firewall rules are blocking traffic; recheck previous steps using sudo 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

  1. 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
  2. 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 on app-02.
    ls -l /srv/nfs/uploads
  • The error mount.nfs4: access denied by server while mounting typically indicates that the IP address of app-02 falls outside the allowed subnet range specified in Section 25.3.2, or export entries have not been reloaded using exportfs -ra.

25.4.2 Permanent Mounting via /etc/fstab

Hands-on Steps

  1. Unmount the manual mount to avoid conflicts during /etc/fstab testing.
    sudo umount /mnt/nfs/uploads
  2. Add the following entry to /etc/fstab on app-02.
    192.168.1.10:/srv/nfs/uploads  /mnt/nfs/uploads  nfs4  defaults,_netdev  0  0
    Similar to CIFS mounts in Section 24.5.2, the _netdev option tells systemd that this filesystem relies on network connectivity, delaying mount execution during boot until the network is ready.
  3. Test the entry without rebooting the server.
    sudo mount -a
    df -hT /mnt/nfs/uploads

Verification and Troubleshooting

  • If sudo mount -a executes without error but the mount does not appear in df, verify /etc/fstab syntax using findmnt --verify, a tool designed specifically to validate /etc/fstab without 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

  1. Install the autofs package on app-02.
    sudo apt install -y autofs
  2. Register a new master map in /etc/auto.master.d/ pointing to mount point /mnt/nfs/auto and a separate map file named auto.nfs. Using the auto.master.d/ directory is safer than editing /etc/auto.master directly, matching the sudoers.d/ drop-in pattern from Chapter 4.
    sudo nano /etc/auto.master.d/nfs.autofs
    /mnt/nfs/auto  /etc/auto.nfs  --timeout=60
  3. Create an indirect map file /etc/auto.nfs defining subdirectories under /mnt/nfs/auto.
    sudo nano /etc/auto.nfs
    uploads  -fstype=nfs4,rw  192.168.1.10:/srv/nfs/uploads
    This line configures autofs to automatically mount 192.168.1.10:/srv/nfs/uploads via NFSv4 as soon as a process accesses /mnt/nfs/auto/uploads.
  4. Restart the autofs service 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=60 parameter.
  • If ls /mnt/nfs/auto/uploads returns an empty listing without error and mount shows no entries, inspect autofs logs via journalctl -u autofs -n 30 to 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

  1. Align the Domain parameter in /etc/idmapd.conf on both the server and app-02, using the same internal domain as the DNS zone from Chapter 9.
    sudo nano /etc/idmapd.conf
    [General]
    Domain = example.local
  2. 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.
    ls -l /mnt/nfs/uploads
    Ownership should reflect www-data instead of nobody:nogroup.
  • Field note: The most effective long-term solution goes beyond matching Domain settings by ensuring numeric UIDs and GIDs for key service accounts like www-data match 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

  1. Display general NFS server operational statistics to verify server traffic from expected clients.
    nfsstat -s
  2. View active export lists prior to modifying /etc/exports entries.
    sudo exportfs -v

Verification and Troubleshooting

  • NFS does not offer real-time connection dashboards comparable to smbstatus in 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.