Read-only NFS exports let a Linux server publish shared files while preventing clients from changing the exported path. They fit installer mirrors, reports, reference data, and other content that should be consumed from many hosts but updated only on the server.
Linux NFS servers load export rules from /etc/exports and from files ending in .exports under /etc/exports.d. The ro option denies write operations through the export, while exportfs loads the saved rule into the active export table that clients actually use.
Server-side ownership still controls which files exist and who can update them locally. After the rule is loaded, a client-side smoke test should show one readable file and one denied write from a host allowed by the selector.
Related: How to create an NFS export
Related: How to reload NFS exports
Related: How to list NFS exports on a server
$ sudo install -d -o root -g root -m 0755 /srv/nfs/projects
Replace /srv/nfs/projects with the directory clients should read. Add or update files from the server side before relying on the export; clients will not be able to write through this rule.
$ sudo install -d -o root -g root -m 0755 /etc/exports.d
exportfs reads files in /etc/exports.d only when their names end with .exports.
$ sudoedit /etc/exports.d/projects.exports
/srv/nfs/projects 192.0.2.0/24(ro,sync,no_subtree_check,root_squash)
Keep no whitespace between the client selector and its option list. 192.0.2.0/24(ro,sync) applies those options to that subnet, while 192.0.2.0/24 (ro,sync) changes how exports(5) parses the rule.
Use a specific host, subnet, or netgroup instead of * unless every reachable client is allowed to read the content.
$ sudo exportfs -rv exporting 192.0.2.0/24:/srv/nfs/projects
exportfs -r reconciles the active table with saved export files, including option changes and removed entries.
Related: How to reload NFS exports
$ sudo exportfs -v /srv/nfs/projects 192.0.2.0/24(sync,wdelay,hide,no_subtree_check,sec=sys,ro,root_squash,no_all_squash)
exportfs may show defaults such as wdelay, hide, sec=sys, and no_all_squash in addition to the options saved in the file.
Related: How to list NFS exports on a server
$ sudo systemctl is-active nfs-server active
On current Ubuntu packages, nfs-kernel-server.service is an alias for nfs-server.service.
$ sudo mkdir --parents /mnt/projects
Files already inside /mnt/projects become hidden while the NFS filesystem is mounted there.
$ sudo mount -t nfs4 files.example.net:/srv/nfs/projects /mnt/projects
Replace files.example.net with the NFS server name. The client must match the host, subnet, or netgroup used in the export rule.
Related: How to mount an NFS export on Linux
$ findmnt -o TARGET,SOURCE,FSTYPE /mnt/projects TARGET SOURCE FSTYPE /mnt/projects files.example.net:/srv/nfs/projects nfs4
$ cat /mnt/projects/README.txt reference build
Use a file that should already exist in the exported directory. A successful read proves the client can consume the shared content.
$ touch /mnt/projects/client-write-test touch: cannot touch '/mnt/projects/client-write-test': Read-only file system
The write denial is expected for an export loaded with ro. If the command succeeds, check whether the client mounted a different path or whether the active export table still shows rw.
$ sudo umount /mnt/projects