Nf
Storage Azure

NFS File Server on Ubuntu 24.04 on Azure User Guide

| Product: NFS File Server on Ubuntu 24.04 LTS on Azure

Overview

This image runs a production ready NFS (Network File System) file server built on the operating system's own kernel NFS server, the standard, battle tested file sharing service used across Linux. The service is fully configured and security hardened, so you can share a directory over the network to your trusted clients within minutes of launch without hand editing the export table or the NFS daemon configuration.

The server exports a dedicated, independently resizable Azure data disk mounted at /srv/nfs, kept separate from the operating system disk. The data disk is part of the image, so every VM you deploy is provisioned with it automatically and your shared data never competes with the OS for space.

The image is secure by default. The shipped export is restricted to the loopback address (127.0.0.1) only, so no machine on the network can mount the share until you explicitly open it to a client network you trust. The server runs NFSv4 only (NFSv2 and NFSv3 are disabled), which removes the rpcbind and statd services entirely and leaves a single well known port, TCP 2049. Every export uses root_squash, so a remote root user is mapped to an unprivileged account and can never own or overwrite files as root. A single management tool, nfs-share, is the primary interface: it adds and removes client networks and refuses any world open export as a hard guardrail.

On the first boot of every deployed VM, a one shot service ensures the export directory and its ownership, derives a per VM NFSv4 identity mapping domain, and records the server's details, its address and the exact commands to open the share, in a root only information file.

What is included:

  • OS-native kernel NFS server (Ubuntu 24.04 noble main), configured NFSv4-only (TCP 2049)
  • Dedicated 50 GiB data disk at /srv/nfs (ext4) — separate from the OS disk, captured in the image
  • Secure-by-default export: loopback-only until you open it, with root_squash, sync, no_subtree_check
  • nfs-share management tool in /usr/local/sbin (status, list, allow, deny) with world-open guardrails
  • Per-VM first-boot initialisation writing server details to /root/nfs-server-info.txt
  • All packages from the Ubuntu archive (kernel / nfs-utils) — clean open source, no third-party repository
  • 24/7 cloudimg support

Prerequisites

Before you deploy this image you need:

  • An active Microsoft Azure subscription where you can create virtual machines
  • An SSH key pair for administrator access to the VM
  • A virtual network and subnet in the target region. NFS clients mount the server over the private network, so put your clients in the same VNet (or a peered one)
  • A network security group (NSG) that allows inbound TCP 2049 to the server from the client subnets that will mount the share, and inbound TCP 22 from your administrator network
  • The Azure CLI installed locally if you plan to deploy from the command line, and one or more Linux client machines with nfs-common (or the equivalent NFS client package) installed to mount the share

Standard_B2s (2 vCPU / 4 GiB RAM) is a balanced default; size the VM to the number of clients and the throughput you expect. NFSv4 uses only TCP 2049, so that is the single service port to allow on the NSG.

Step 1: Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, and search the Marketplace for NFS File Server by cloudimg. Select the listing and choose Create.

On the Basics tab pick your subscription and resource group, a region, and a VM size (Standard_B2s or larger). Under Administrator account select SSH public key, set the username, and paste your public key. Under Inbound port rules allow SSH (22) for administration; you will add the NFS rule (TCP 2049) scoped to your client subnets after deployment. Review the dedicated data disk on the Disks tab — it is included in the image and holds your shared data. Select Review + create, then Create. First-boot initialisation completes within a few seconds of the VM reaching the Running state.

Step 2: Deploy from the Azure CLI

The following block creates a VM from the cloudimg NFS File Server image into an existing VNet and subnet. Replace the placeholders with your own values. The dedicated /srv/nfs data disk is part of the image and is attached automatically.

az vm create \
  --resource-group <your-rg> \
  --name nfs-file-server \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard

# Allow NFS (TCP 2049) from your client subnet only — never from the internet.
az vm open-port --resource-group <your-rg> --name nfs-file-server --port 2049 --priority 1010

Step 3: Connect as the Administrator over SSH

Connect to the VM with SSH as the administrator user you set at deploy time (azureuser by default on Ubuntu). The administrator account is SSH key only.

ssh azureuser@<vm-public-ip>

Step 4: Confirm the Server is Running

The NFS server starts automatically on boot. Confirm the service is active, that it is serving NFSv4 only, that the dedicated data disk is mounted, and inspect the live export table:

systemctl is-active nfs-server.service
cat /proc/fs/nfsd/versions
findmnt -no SOURCE,SIZE,FSTYPE,TARGET /srv/nfs
sudo exportfs -v

The versions line shows -3 +4 — NFSv3 is disabled and NFSv4 is enabled. The export table lists /srv/nfs/share restricted to 127.0.0.1, which is the secure default.

NFS File Server status: the nfs-server service is active, the kernel is serving NFSv4 only, the dedicated /srv/nfs data disk is mounted, and the live export table shows the loopback-only default export

Step 5: The Secure by Default Export Model

Read the first-boot information file and the export summary at any time with the nfs-share tool. The file records the server's private IP and the exact command to open the share to your clients.

sudo cat /root/nfs-server-info.txt
sudo nfs-share status

The image ships with the share exported to 127.0.0.1 only. This is deliberate: no client on the network can mount the share until you explicitly allow its network. The export uses root_squash (a remote root is mapped to the unprivileged nobody account), sync (writes are committed before the server acknowledges them), and no_subtree_check (stable, reliable exports). The image never ships a wildcard (*) or 0.0.0.0/0 export.

The nfs-share status view showing the NFSv4-only server, the configured clients, the live export table, the secure-by-default loopback-only /etc/exports, and the first-boot server information file

Step 6: Open the Share to Your Client Network

Grant a trusted client network read/write access to the share with nfs-share allow, passing a CIDR range or a single host. Use your client subnet's CIDR — the value below is only an example. Add --ro for a read-only export.

sudo nfs-share allow 10.0.0.0/24
sudo nfs-share list

The tool appends the export, reloads the export table, and confirms it. World-open exports are refused as a hard guardrail: nfs-share allow '*' and nfs-share allow 0.0.0.0/0 are both rejected, and the --no-root-squash option is refused, so you cannot accidentally expose the share to the whole internet or hand remote root full ownership.

Opening the share to a trusted client network with nfs-share allow, then the world-open guardrail refusing an export to '*' and to 0.0.0.0/0

Step 7: Mount the Share from a Linux Client

On a client machine in the allowed network, install the NFS client tools and mount the share using the server's private IP address (shown in /root/nfs-server-info.txt). NFSv4 mounts the exported path directly.

# On the client (Ubuntu/Debian):
sudo apt-get update && sudo apt-get install -y nfs-common
sudo mkdir -p /mnt/nfs
sudo mount -t nfs <server-private-ip>:/srv/nfs/share /mnt/nfs

# Verify and use it:
df -h /mnt/nfs
echo "hello from the client" | sudo tee /mnt/nfs/test.txt

To mount automatically at boot, add a line to the client's /etc/fstab:

<server-private-ip>:/srv/nfs/share  /mnt/nfs  nfs  defaults,_netdev  0  0

Step 8: Verify the Share Locally

You can prove the export works end to end directly on the server with a loopback mount, without any client. This mounts the share over 127.0.0.1, writes a file, reads it back, and unmounts:

sudo mkdir -p /mnt/nfs-check
sudo mount -t nfs 127.0.0.1:/srv/nfs/share /mnt/nfs-check
echo "cloudimg NFS shared storage" | sudo tee /mnt/nfs-check/hello.txt
cat /mnt/nfs-check/hello.txt
sudo rm -f /mnt/nfs-check/hello.txt
sudo umount /mnt/nfs-check

A successful write and read back confirms the server, the export, and the dedicated data disk are all working.

A loopback NFS mount round-trip on the server: mount 127.0.0.1:/srv/nfs/share, write a file, read it back, showing the data disk serving over NFSv4

Step 9: Managing Exports

Inspect, add and remove client networks with the nfs-share tool. It is the primary interface to the export allow-list:

sudo nfs-share status
sudo nfs-share list

Revoke a client network's access when it no longer needs the share (this reloads the export table immediately):

sudo nfs-share deny 10.0.0.0/24

The full set of commands is:

Command Purpose
nfs-share status Show the server, the configured clients and the live export table
nfs-share list Show the live NFS export table (exportfs -v)
nfs-share allow <CIDR\|host> [--ro] Grant a client network read/write (or read-only) access
nfs-share deny <CIDR\|host> Revoke a client network's access

You can also edit /etc/exports directly and run sudo exportfs -ra to apply changes; the nfs-share guardrails only apply to the tool.

Step 10: The Dedicated Data Disk

Shared data lives on a dedicated Azure data disk mounted at /srv/nfs, separate from the OS disk, with the exported directory at /srv/nfs/share. Because the disk is captured into the image, every VM you deploy has it automatically. To grow the share, resize the data disk in the Azure portal or CLI and then extend the filesystem:

# After increasing the data disk size in Azure:
sudo growpart /dev/disk/azure/scsi1/lun0 1 2>/dev/null || true
sudo resize2fs $(findmnt -no SOURCE /srv/nfs)

The export root /srv/nfs/share is owned by the unprivileged nobody:nogroup account so that clients writing through root_squash can read and write, while the mount is never world-writable.

Step 11: Hardening Notes

The image is hardened out of the box: the server runs NFSv4 only, so rpcbind and statd are not present and the only listening port is TCP 2049; the shipped export is loopback-only until you open it; every export uses root_squash so remote root has no privileged access; and the nfs-share tool refuses world-open exports. Keep it locked down in production: scope the NSG rule for TCP 2049 to only the client subnets that need the share, never expose 2049 to the internet, grant the narrowest CIDR ranges you can, prefer --ro exports for read-only consumers, and keep the OS patched (sudo apt update && sudo apt upgrade). For sensitive data over untrusted networks, consider Kerberos (sec=krb5p) or a private, encrypted network path.

Support

This image is backed by 24/7 cloudimg support. Contact us by email and chat for help with NFS export configuration, client mounting, the dedicated data disk, NFSv4 identity mapping, root_squash and access control, and shared storage architecture on Azure.

All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.