NFS File Server on Ubuntu 24.04 on Azure User Guide
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-sharemanagement 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.

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.

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.

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.

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.