Illustration of a Linux server environment depicting NFS (Network File System) setup and file sharing. The image highlights system administration tools, command-line interface, and networking elements, representing best practices for configuring an NFS server on Linux.

NFS Server on Linux – Setup and Best Practices Guide

Author:
Željko Jagušt
Publish Date:
February 16, 2025
Estimated Reading Time:
18 minutes

Setting up an NFS server on Linux is an essential step for creating efficient and reliable file-sharing solutions in any networked environment. Whether for personal projects or enterprise use, an NFS server on Linux provides the flexibility and performance needed for seamless data access. In this guide, we will cover everything from the initial setup to best practices, helping you achieve secure and optimized configurations for your system.

Introduction

Network File System (NFS) is a robust protocol that allows seamless file sharing across multiple Linux systems, making it an essential tool for enterprises and home networks alike. By setting up an NFS server on Linux, users can centralize storage, simplify file management, and provide seamless access to shared data across multiple clients. Unlike other network-based file-sharing solutions, NFS offers high performance with minimal overhead, integrating deeply with Linux’s native file permissions and authentication mechanisms.

In this guide, we will walk you through the entire process of setting up an NFS server on Linux, from installing the necessary packages to configuring exports and managing client access. We’ll cover key considerations such as optimizing performance, ensuring security, and troubleshooting common issues. Whether you’re a system administrator looking to deploy NFS in a production environment or a home user setting up a simple file-sharing solution, this guide provides the necessary insights.

Prerequisites

You can install and configure an NFS server on any Linux machine for file sharing. However, setting it up solely to share files between two computers is impractical. NFS is primarily intended to be installed on a server and used as centralized storage for all computers on the network. For this article, I will illustrate the process using a machine equipped with five 3TB disks and running a Debian operating system. Please feel free to check out my articles on how to install and initially configure the Debian operating system on any computer:

Featured image for "Debian 11 Server - Minimal Installation Guide" article on Zacks.eu, showing a stylized Debian logo on a carbon fiber like surface background.

Debian 11 Server – Minimal Installation Guide

Follow this guide for a Debian 11 Server minimal installation, providing a solid foundation for any server setup or project you want to build.

Featured image for "Debian 11 Server - Initial Customization Guide" article on Zacks.eu, showing a Debian logo on a striped dark blue background.

Debian 11 Server – Initial Customization Guide

Discover introductory steps to streamline performance, security, and administration in our Debian Server Initial Customization guide.

You can also check my articles on how to configure the RAID array(s) and file systems for your multiple disks:

An array of hard disks connected to a motherboard, illustrating RAID-10 configuration on Linux for enhanced performance and data redundancy.

RAID-10 Configuration on Linux – Everything You Need to Know

RAID-10 configuration on Linux made simple! Discover how to set up, monitor, and recover your RAID-10 array for unmatched performance and data protection.

A robust storage setup featuring hard disks in ZFS RAID-Z1 configuration connected to a server with a futuristic, tech-inspired background.

ZFS RAID-Z on Linux – Guide to Data Protection and Performance

Learn to set up and configure ZFS RAID-Z on Linux with this step-by-step guide for reliable storage setup on your system.

Once you have your machine ready, I will show you how to install and configure the NFS server on Linux in the following sections of this guide.

NFS Server on Linux – NFS Server Setup

In this section, I will explain how to configure the server side of this setup. I have a machine running Debian with a ZFS RAID-Z1 configured on my disk array, which consists of five 3TB WD Red HDDs. Additionally, I have a 10 Gigabit network setup throughout my premises. I needed to decide whether to use NFSv3 or NFSv4, so let’s take a brief look at the differences between the two.

FeatureNFSv3NFSv4
Protocol TypeUses both TCP & UDPUses only TCP (more reliable)
Port UsageRequires portmapper (rpcbind) and dynamic portsUses only port 2049 (simpler firewall rules)
SecurityNo built-in authenticationSupports Kerberos (krb5), encryption, and ACLs
Locking MechanismUses separate nlockmgr daemon (not atomic)Built-in stateful file locking (atomic)
PerformanceFaster in simple LAN environmentsBetter over WAN/VPN, handles latency better
ReliabilityStateless (no server-side session tracking)Stateful (better consistency, but requires tracking)
PermissionsUses traditional UNIX permissionsSupports extended ACLs
File Access ControlRequires UID/GID matching on client & serverUses UID mapping for better cross-platform support
Symbolic Links & Hard LinksFully supportedFully supported
Firewall ConfigurationComplex (multiple dynamic ports required)Simple (only TCP 2049 needed)
Exporting DirectoriesAllows per-directory exportsRequires one root directory (fsid=0)
Performance Over High-Latency NetworksStruggles over WAN due to UDP usageBetter for WAN, VPN, and cloud setups
NFSv3 vs. NFSv4 – Feature Comparison

The table above may appear complex at first, but there’s no need to worry; configuring and maintaining NFS is relatively straightforward. Since I have only several clients on the network, and I only intend to use the NFS server machine as a file storage, NFSv3 will perfectly meet my requirements. I don’t require the advanced features and options offered by NFSv4. However, for reference, let’s compare some essential advantages and disadvantages of NFSv3 and NFSv4:

PROS:
✔️ Faster in low-latency LAN environments
✔️ Simpler setup (no state tracking)
✔️ Easier to debug (less strict authentication)
✔️ Supports both TCP & UDP (suitable for older networks)

CONS:
✖️ No built-in authentication or encryption (less secure)
✖️ Requires rpcbind (extra security risks)
✖️ Complex firewall rules (dynamic ports like mountd, nlockmgr, etc.)
✖️ Stateless locking (less reliable for concurrent access)

PROS:
✔️ More Secure (Kerberos authentication, encryption, ACLs)
✔️ Simpler Firewall Rules (only uses TCP 2049)
✔️ No rpcbind required (easier setup & less security risk)
✔️ Better Performance over WAN & VPN
✔️ Stateful File Locking (more reliable for concurrent access)
✔️ Supports IPv6 Fully

CONS:
✖️ Requires more setup for security features (Kerberos, ACLs)
✖️ Slightly higher overhead in LAN environments
✖️ Exports must be under a single root (fsid=0)

In my opinion, if you don’t have a massive network (lots of devices) and you don’t intend to use NFS to host stuff like databases and cloud applications, NFSv3 will suit you just fine.

Required Packages – NFS Server Installation

The only package to install an NFS server on Linux, and here I am talking about Debian and Debian-based distributions specifically, is nfs-kernel-server. To do so, execute the following in the console:

apt install -y nfs-kernel-server

It will automatically install nfs-common and rpcbind as additional packages. To enable and activate those services by executing the following in the console:

systemctl enable --now nfs-server rpcbind
systemctl start nfs-server rpcbind

Now both nfs-server and rpcbind services should be active:

systemctl status nfs-server.service rpcbind.service
...
● nfs-server.service - NFS server and services
     Loaded: loaded (/lib/systemd/system/nfs-server.service; enabled; preset: enabled)
     Active: active (exited) since Wed 2025-02-12 10:39:25 CET; 1min 18s ago
   Main PID: 4252 (code=exited, status=0/SUCCESS)
        CPU: 4ms

Feb 12 10:39:24 debian-bookworm-test systemd[1]: Starting nfs-server.service - NFS server and services...
Feb 12 10:39:24 debian-bookworm-test exportfs[4251]: exportfs: can't open /etc/exports for reading
Feb 12 10:39:25 debian-bookworm-test systemd[1]: Finished nfs-server.service - NFS server and services.

● rpcbind.service - RPC bind portmap service
     Loaded: loaded (/lib/systemd/system/rpcbind.service; enabled; preset: enabled)
     Active: active (running) since Wed 2025-02-12 10:39:22 CET; 1min 21s ago
TriggeredBy: ● rpcbind.socket
       Docs: man:rpcbind(8)
   Main PID: 3800 (rpcbind)
      Tasks: 1 (limit: 4638)
     Memory: 600.0K
        CPU: 6ms
     CGroup: /system.slice/rpcbind.service
             └─3800 /sbin/rpcbind -f -w

Feb 12 10:39:22 debian-bookworm-test systemd[1]: Starting rpcbind.service - RPC bind portmap service...
Feb 12 10:39:22 debian-bookworm-test systemd[1]: Started rpcbind.service - RPC bind portmap service.

With services active and running, let’s check out the configuration files next.

Initial Configuration

We need to examine the configuration options in the /etc/default directory, specifically in two files: nfs-common and nfs-kernel-server. I believed these were the correct files to modify. However, when I attempted to change the options in these files and restarted the necessary services to apply the changes, nothing happened. As has often been the case with Linux, I found myself embarking on a little “witch hunt” to figure out the issue.

I started by reviewing similar guides on installing an NFS server on Linux. I found that information regarding changing the configuration options I mentioned earlier was limited and almost nonexistent, which was quite disappointing. So, I continued my search through various mailing lists, which ultimately led me to the source of the issue. I examined commits related to the nfs-utils source package and discovered one that clarified why the changes in the previously mentioned files were ineffective. You can examine it here.

To summarize, I ignored files in the /etc/default directory and performed all the required changes in the main configuration file /etc/nfs.conf. More specifically, I opened a local “snippet” file at /etc/nfs.cond.d/local.conf, and I pasted in the following content:

[lockd]
port=32768
udp-port=32768
[mountd]
udp=no
port=32767
[nfsd]
udp=n
tcp=y
vers2=n
vers3=y
vers4=n
vers4.0=n
vers4.1=n
vers4.2=n
[statd]
port=32765
outgoing-port=32766

To apply the changes, several services must be restarted (or just simply reboot the machine):

systemctl restart rpcbind.service rpc-statd.service nfs-mountd.service nfs-server.service

When “allocating” ports to services, Linux operating systems check the /etc/services file to see if a specific port has been assigned to a service. If you open that file, you will see that RPC/portmapper and NFS have their respective ports assigned (111 and 2049). You can add “local ports” assignments specific to your system at the bottom of the file. To satisfy our scenario, you can add the following ports:

# Local services

#
# RPC/NFS ports
# Listing here does not mean they will bind to these ports.
#
rpc.statd-bc    32765/tcp                       # RPC statd broadcast
rpc.statd-bc    32765/udp                       # RPC statd broadcast
rpc.statd       32766/tcp                       # RPC statd listen
rpc.statd       32766/udp                       # RPC statd listen
rpc.mountd      32767/tcp                       # RPC mountd
rpc.mountd      32767/udp                       # RPC mountd
rpc.lockd       32768/tcp                       # RPC lockd/nlockmgr
rpc.lockd       32768/udp                       # RPC lockd/nlockmgr

Security and Firewall

If you are running NFS on your home server and storing non-essential data, security may not be an issue. But still, I am going to show you how to secure and harden your NFS server. As a prerequisite, I will use 192.168.100.0/24 as a local network subnet (please change that to your local network subnet). If you have no other services besides NFS on your machine, the following set of firewall rules should do the trick:

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp -s 192.168.100.0/24 --dport 111  -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp -s 192.168.100.0/24 --dport 2049 -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp -s 192.168.100.0/24 --dport 32765 -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp -s 192.168.100.0/24 --dport 32767 -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp -s 192.168.100.0/24 --dport 32768 -m state --state NEW -j ACCEPT
iptables -A INPUT -p icmp --icmp-type echo-request -s 192.168.100.0/24 -j ACCEPT

The rules above will allow access to your NFS server from all computers on the 192.168.100.0/24 network. As an option (such as in case you have more subnets), you can also block everything else from accessing the NFS:

iptables -A INPUT -p tcp --dport 111  -j DROP
iptables -A INPUT -p tcp --dport 2049 -j DROP
iptables -A INPUT -p tcp --dport 32765 -j DROP
iptables -A INPUT -p tcp --dport 32767 -j DROP
iptables -A INPUT -p tcp --dport 32768 -j DROP

If you have followed my guides from the prerequisites above, you should already have some general, sane rules in your firewall. If so, you must only set the “allow” rules in a dedicated chain. To do so, first, create a new chain:

iptables -N NFS-SERVICES

Now, you must define a “jump” from the INPUT chain to the NFS-SERVICES chain:

iptables -I INPUT -m tcp -p tcp -s 192.168.100.0/24 -m comment --comment "NFS Specific Rules" -j NFS-SERVICES

Since the local subnet (192.168.100.0/24) is already defined in the jump rule, you don’t have to define it again in NFS-specific rules:

iptables -A NFS-SERVICES -p tcp -m tcp --dport 111 -m state --state NEW -m comment --comment "RPC Bind" -j ACCEPT
iptables -A NFS-SERVICES -p tcp -m tcp --dport 2049 -m state --state NEW -m comment --comment "NFS Daemon" -j ACCEPT
iptables -A NFS-SERVICES -p tcp -m tcp --dport 32765 -m state --state NEW -m comment --comment "RPC Statd" -j ACCEPT
iptables -A NFS-SERVICES -p tcp -m tcp --dport 32767 -m state --state NEW -m comment --comment "RPC Mountd" -j ACCEPT
iptables -A NFS-SERVICES -p tcp -m tcp --dport 32768 -m state --state NEW -m comment --comment "RPC Lockd" -j ACCEPT

There is also no need to define “DROP” rules as the chain that drops “everything else” is also in place. You can examine it by executing the following in the console:

iptables -L REJECT-ALL -v -n
...
Chain REJECT-ALL (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REJECT     6    --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with tcp-reset
    0     0 REJECT     17   --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable
    0     0 DROP       1    --  *      *       0.0.0.0/0            0.0.0.0/0

In both cases, you must save the firewall rules by executing the following in the console:

iptables-save > /etc/iptables/rules.v4

The set of rules above should “satisfy all” for small networks. A more fine-grained approach may be required for larger networks.

NFS Server on Linux – NFS Exports

With NFSv3, you can export any directory on your server, although I do not recommend doing this indiscriminately. In my example, I will export only one directory: my entire ZFS storage array. First, I created the directory /mnt/zfs-data/storage, which I intend to export. After that, I defined the export by opening the /etc/exports file and adding the following line at the bottom:

/mnt/zfs-data/storage   172.17.0.0/24(rw,sync,no_subtree_check)

Let’s examine the options a bit:

  • rw: Allows clients to read & write.
  • sync: Ensures data is written to disk immediately (safer).
  • no_subtree_check: Improves performance and reliability.

For a more fine-grained approach, you could do something like in the following example:

/mnt/zfs-data/storage/backup/computer01   172.17.0.10/32(rw,sync,no_subtree_check)
/mnt/zfs-data/storage/backup/computer02   172.17.0.11/32(rw,sync,no_subtree_check)
/mnt/zfs-data/storage/movies   172.17.0.0/24(rw,sync,no_subtree_check)
/mnt/zfs-data/storage/tv   172.17.0.0/24(rw,sync,no_subtree_check)
/mnt/zfs-data/storage/music   172.17.0.0/24(rw,sync,no_subtree_check)
/mnt/zfs-data/storage/docs   172.17.0.0/24(rw,sync,no_subtree_check)

In the example above, a dedicated backup export is created for each individual computer on the network, while the other exports can be accessed by any device on the network. Regardless of the approach you choose, be sure to apply the changes by executing the following commands in the console:

exportfs -a
systemctl restart nfs-server

Non-Linux Clients Options

In my scenario, I want to connect my Windows 11 computer to my NFS server and access media files from my Android TV using VLC Player. This requires additional configuration on the NFS server to ensure compatibility.

Firstly, please don’t take this for granted, but I’m pretty sure that Windows still only supports NFSv3. Additionally, Windows and Android handle permissions differently, so a minor adjustment to the NFS configuration is needed.

/mnt/zfs-data/storage   172.17.0.0/24(rw,sync,no_subtree_check,all_squash)

As you may have noticed, I have added the all_squash option. This option will treat all non-Linux clients as anonymous users, resolving any compatibility issues between the NFS server on Linux and non-Linux clients. To apply the change, please execute the following in the console:

exportfs -ra

With all this in place, you can start connecting your clients. Let’s observe how.

Connecting Clients

To mount an NFS share on a Linux client (e.g., your desktop computer, or another server), you must install the nfs-common package. To do so, please execute the following in the console:

sudo apt install -y nfs-common

Once installed, you must modify /etc/fstab and define a persistent NFS mount. To do so, open the file and add the following at the bottom:

# NFS Share /mnt/zfs-data/storage
172.17.0.2:/mnt/zfs-data/storage    /mnt/storage    nfs  rw,noatime,hard,intr,retrans=2,timeo=600,vers=3,actimeo=2   1   0

Save and close the file. To “activate” the share, you can either restart your computer, or execute the following command:

sudo mount /mnt/storage

From here, you can symlink NFS share to wherever you need, for instance, in your user home directory:

cd
ln -sf /mnt/storage Storage

Optional – Windows 11

You must enable NFS Client for Windows to connect NFS share on Windows. To do so, open a PowerShell (Admin) and execute the following:

dism /online /enable-feature /featurename:ServicesForNFS-ClientOnly

At this point, you will need to restart your computer. Once it is back, start PowerShell again and execute the following:

mount -o anon,mtype=hard,tcp 172.17.0.2:/mnt/zfs-data/storage Z:

To make it persistent, please execute the following in the PowerShell also:

net use Z: \\172.17.0.2\mnt\zfs-data\storage /persistent:yes

Optional – VLC Player on Android TV

Connecting to your NFS share from VLC Player on Android TV is pretty simple. Start the VLC Player application and go to “Browsing” → Select “NFS.” Once there, enter the following details:

  • Server Address: nfs://172.17.0.2/mnt/zfs-data/storage
  • No authentication required (due to all_squash in server settings)

Since most Android apps (like VLC) rely on NFSv3 over UDP by default, and I enforced TCP above in this guide, an additional step of allowing the UDP protocol may be required in the main NFS server configuration file. It is up to you to allow this, and if you do, please remember to allow UDP connections in the firewall as well.

Conclusion

Setting up an NFS server on Linux provides a powerful and efficient way to share files across multiple systems, including Linux, Windows, and even Android-based devices. While NFSv4 offers security and performance improvements, NFSv3 remains widely used for its simplicity and compatibility. Key considerations include UID/GID mapping, firewall rules, and ensuring proper permission settings to maintain both accessibility and security.

For a smooth cross-platform experience, carefully configuring export options such as all_squash, and optionally anonuid, and anongid helps maintain consistency, especially when connecting from non-Linux clients. Additionally, limiting unnecessary services, enforcing iptables rules, and securing access through authentication mechanisms like Kerberos can significantly enhance the security of your NFS setup.

By following best practices for configuration, security, and user management, you can ensure a stable, secure, and high-performance NFS environment tailored to your needs. Whether for personal media storage or enterprise file sharing, a well-configured NFS server on Linux remains a reliable and scalable solution.


Spread The Word


Leave a Comment

MONTHLY POLL

What are your preferred resources for learning about system administration?

View Results

Loading ... Loading ...