How to Set Up an NFS Server on Fedora

Install nfs-utils, create a shared directory, configure /etc/exports, and start the nfs-server service on Fedora.

You need a shared directory across Linux machines

You have a Fedora machine with a large data directory and a second machine that needs access to those files without copying them over the network every time. You want a lightweight, POSIX-compliant share that feels like a local mount. You tried setting up Samba, but the authentication overhead feels excessive for a trusted internal network. NFS is the right tool. You need to export a directory from the server and mount it on the client with minimal friction.

How NFS maps remote files to local paths

NFS stands for Network File System. It works by exposing a directory on the server as a remote resource. The client mounts that resource into its own filesystem tree. The kernel handles the file operations over the network. To the user and most applications, the remote files look local.

The server runs a daemon that listens for requests. The client sends RPC calls to read or write data. The server translates those calls into local filesystem operations and sends the results back. The magic is in the translation layer. You configure what gets shared, who can access it, and what permissions apply.

NFS relies on rpcbind to manage port mapping. The NFS daemons use dynamic ports for some operations. rpcbind tracks which port each service is using and tells the client where to connect. This is why the firewall must allow the NFS service group, not just a single port. If rpcbind is blocked, the client cannot discover the ports and the mount fails with a timeout.

Run exportfs -v before you blame the network. The server might not be advertising the share.

Install and configure the server

Install the NFS utilities package. This provides the server daemon, client tools, and configuration helpers.

sudo dnf install nfs-utils
# nfs-utils provides the kernel module support, user-space daemons, and configuration tools.
# It includes both server and client components.
# The package pulls in rpcbind as a dependency.

Create a dedicated directory for the export. Using a standard path keeps the configuration predictable and separates shared data from system files.

sudo mkdir -p /srv/nfs/share
# /srv follows the Filesystem Hierarchy Standard for data served by this system.
# Using a dedicated path keeps exports isolated from system directories.
# -p creates parent directories if they do not exist.

Edit the exports configuration file. This file defines which directories are shared and what options apply. Edit /etc/exports. Never edit files in /usr/lib/exports. The system packages manage those files and your changes will be overwritten on upgrade.

# /etc/exports
/srv/nfs/share 192.168.1.0/24(rw,sync,no_subtree_check)
# rw grants read-write access. sync forces writes to disk before acknowledging.
# no_subtree_check improves reliability by skipping checks for parent directory changes.
# Restricting by IP range is safer than using * for production shares.
# Replace 192.168.1.0/24 with your actual client network range.

Reload the export table. This applies the configuration without restarting the service.

sudo exportfs -ra
# -r re-exports all directories. -a exports all.
# This reloads /etc/exports without restarting the service.
# Always run this after editing exports.
# If you see warnings about unrecognized options, check the syntax in /etc/exports.

Start the NFS server service. Enable it to persist across reboots.

sudo systemctl enable --now nfs-server
# Enable ensures the service starts on boot. Now starts it immediately.
# nfs-server pulls in rpcbind and nfs-mountd as dependencies.
# Check status with systemctl status nfs-server if the service fails to start.

Configure the firewall. NFS uses multiple ports for different operations. The service definition handles the port range automatically.

sudo firewall-cmd --add-service=nfs --permanent
# The nfs service definition includes nfs, rpc-bind, and mountd ports.
# Adding the service is safer than opening individual ports manually.
# --permanent saves the rule to the persistent configuration.

Reload the firewall. Changes do not take effect until you reload. The runtime config and persistent config diverge if you skip this step.

sudo firewall-cmd --reload
# Reloads the firewall rules.
# Runtime and persistent configs diverge if you skip this step.
# Verify the service is active with firewall-cmd --list-services.

Check SELinux contexts. Fedora enforces SELinux by default. The NFS daemon cannot access arbitrary directories without the correct label.

sudo semanage fcontext -a -t nfs_t "/srv/nfs/share(/.*)?"
# Adds a file context rule. nfs_t is the label NFS daemons are allowed to access.
# Without this label, SELinux denies access even if permissions look correct.
# The regex matches the directory and all files inside it.

Apply the context to the filesystem. semanage defines the rule. restorecon applies it to the disk.

sudo restorecon -Rv /srv/nfs/share
# Applies the new context to existing files. -R recurses. -v shows changes.
# If the directory is empty, this command runs quickly with no output.
# Verify with ls -Z /srv/nfs/share to see the nfs_t label.

Check SELinux logs before disabling the policy. A context label fix is faster than turning off security.

Verify the export and firewall

Confirm the server is advertising the share. This command lists active exports with their options.

sudo exportfs -v
# Lists active exports with their options. Confirms the server is advertising the share.
# Output shows the directory, client range, and applied options.
# If the share is missing, check /etc/exports for syntax errors.

Query the mount daemon. This is useful for debugging client connection issues.

showmount -e localhost
# Queries the mountd daemon to see what is available.
# Useful for debugging client connection issues.
# If this fails, rpcbind or nfs-mountd may not be running.
# Run systemctl status rpcbind to check the port mapper.

Mount the share on a client

Create a mount point on the client machine. This is where the remote directory will appear.

sudo mkdir -p /mnt/nfs-share
# Creates the local directory for the mount point.
# The path can be anywhere, but /mnt is standard for temporary mounts.
# Ensure the directory is empty before mounting.

Mount the share manually. This tests the connection before making it permanent.

sudo mount -t nfs server:/srv/nfs/share /mnt/nfs-share
# -t nfs specifies the filesystem type.
# The server address and export path identify the remote resource.
# /mnt/nfs-share is the local mount point. Create it first.
# Replace server with the IP or hostname of the NFS server.

Verify the mount. Check that files are accessible and permissions look correct.

ls -l /mnt/nfs-share
# Lists files in the mounted directory.
# Permissions reflect the server-side ownership mapped to local UIDs.
# If you see permission denied, check UID/GID mapping between server and client.

Add the mount to /etc/fstab for persistence. This ensures the share mounts on boot.

# /etc/fstab
server:/srv/nfs/share /mnt/nfs-share nfs defaults,_netdev 0 0
# _netdev delays mounting until the network is up.
# Without _netdev, the boot process might hang waiting for the share.
# defaults applies rw, suid, dev, exec, auto, nouser, and async options.
# Replace server with the IP or hostname of the NFS server.

Test the fstab entry. This checks for syntax errors without mounting.

sudo mount -a
# Attempts to mount all filesystems in /etc/fstab.
# Useful for testing fstab changes without rebooting.
# If there is an error, the output points to the problematic line.
# Fix the error before rebooting to avoid boot failure.

Reboot before you debug. Half the time the symptom is gone after a clean boot cycle.

Common pitfalls and error patterns

The mount command will refuse to proceed and print mount.nfs: Connection timed out. The firewall is likely blocking rpcbind or nfs. Run firewall-cmd --list-services on the server. Ensure nfs is in the list. Reload the firewall if you added the service recently.

If you see mount.nfs: access denied by server while mounting, check the client IP against /etc/exports. The server might be restricting access to a specific subnet. Verify the client IP matches the range. Also check SELinux denials on the server with journalctl -t setroubleshoot. SELinux blocks access if the directory lacks the nfs_t label.

The error stale file handle appears when the client cache references a file that has been removed or renamed on the server. The client kernel holds a stale reference. Unmount and remount the share to clear the cache. Use umount -l /mnt/nfs-share for a lazy unmount if the mount is busy.

Using no_root_squash in /etc/exports allows root on the client to act as root on the server. This is a security risk. Only use no_root_squash when you explicitly need root access from the client. The default root_squash maps root to nobody, which is safer for most setups.

NFS performance degrades if the client and server have different time zones or NTP sources. File timestamps can drift. Ensure both machines are synchronized with NTP. Run timedatectl status to check synchronization.

Trust the package manager. Manual file edits drift, snapshots stay.

Choose the right sharing protocol

Use NFS when you need high-performance file sharing between Linux systems on a trusted network. Use Samba when you must interoperate with Windows clients or macOS users who expect SMB semantics. Use SSHFS when you need to mount a remote directory over an encrypted tunnel without configuring a server daemon. Use iSCSI when you need block-level storage access rather than file-level sharing. Stick to local storage when the data resides on a single machine and network latency is unacceptable.

Where to go next