Skip to main content
  1. Tutorials/

Fixing a Read-Only NFS Mount Blocking Hugo Deploys

Status In Progress
Difficulty Intermediate
Time ~20 min
Stack
Unraid NFS Bash

My bash deploy script started failing with a read-only filesystem error on an NFS mount that looked completely healthy. This is the full path from symptom to fix.

Executive Summary
#

The root cause was two separate issues compounding each other. The NFS mount was pointing to the wrong path on the Unraid server, and rsync’s default behavior of syncing directory metadata is not compatible with NFS mounts where the target directory is owned by root. Fixing both got the deploy running clean.

Prerequisites
#

  • A working Unraid server with an NFS share configured
  • A Linux workstation with the NFS share mounted
  • A deploy script using rsync to push files to the share
  • SSH access to the Unraid server

Implementation
#

Step 1: Check the Mount
#

When you get a read-only error, the first thing to check is whether the filesystem is actually mounted read-only:

mount | grep unraid

If the output shows rw for your NFS mounts, the mount itself is not the problem. Move on to checking the server.

Step 2: Check the Array on Unraid
#

A read-only NFS export can happen when Unraid’s array stops or a disk errors, as the server protects itself by making shares read-only. SSH into your Unraid server and check:

mdcmd status | grep -E "mdState|rdevStatus"

If the array shows STARTED and all active disks show DISK_OK, the server side is healthy.

Step 3: Remount to Clear Stale NFS State
#

If the server is fine but the client is still getting read-only errors, the likely cause is a stale NFS state. The client cached a read-only condition from a previous hiccup and never recovered. Remount to clear it:

sudo umount /mnt/unraid/websites
sudo mount /mnt/unraid/websites

If the mount fails with can't find in /etc/fstab, the share was mounted manually at some point and never persisted. Mount it explicitly instead:

sudo mount -t nfs YOUR_SERVER_IP:/mnt/user/websites /mnt/unraid/websites

Step 4: Verify the Correct Export Path
#

If writing still fails after remounting, the mount may be pointing to the wrong path. Check the actual NFS exports on the Unraid server:

exportfs -v | grep websites

Unraid exports shares from /mnt/cache/sharename when the share is configured to use cache-only storage, not /mnt/user/sharename. If the export path does not match what you are mounting, unmount and remount with the correct path:

sudo umount /mnt/unraid/websites
sudo mount -t nfs YOUR_SERVER_IP:/mnt/cache/websites /mnt/unraid/websites
touch /mnt/unraid/websites/test.txt && echo "Writable!"

Step 5: Fix the NFS Security Rule on Unraid
#

If the mount is denied entirely, check the NFS security settings for the share in the Unraid web UI under Shares > your-share > NFS Security Settings. If Security is set to Private with no rule defined, no client is allowed to connect.

Add a rule:

*(rw,sec=sys,insecure,anongid=100,anonuid=99,no_root_squash,lock)

Key flags:

  • rw allows read-write access
  • no_root_squash allows rsync’s chgrp operations to pass through
  • insecure allows connections from ports above 1024, required for most Linux NFS clients

Step 6: Fix rsync Metadata Flags
#

If files transfer but rsync still exits with errors like this:

rsync: [generator] chgrp "/mnt/unraid/websites/hofiverse/." failed: Operation not permitted
rsync: [generator] failed to set times on "/mnt/unraid/websites/hofiverse/.": Operation not permitted

The problem is rsync trying to sync ownership, timestamps, and permissions on the root target directory, which NFS rejects because the directory is owned by root on the server. Add these flags to your rsync command:

rsync -av --delete --no-group --omit-dir-times --no-perms "$SITE_DIR/public/" "$PROD_DIR/"
  • --no-group skips syncing group ownership
  • --omit-dir-times skips setting timestamps on directories
  • --no-perms skips syncing permissions

Step 7: Persist the Mount
#

Add the correct mount to /etc/fstab so it survives reboots:

echo 'YOUR_SERVER_IP:/mnt/cache/websites  /mnt/unraid/websites  nfs  rw,relatime,vers=3,hard,proto=tcp,timeo=600,retrans=2,_netdev  0  0' | sudo tee -a /etc/fstab
sudo mount -a

Lab Notes & Troubleshooting
#

The unmount fails with “target is busy”. A terminal or file manager has the mount open. Close anything accessing the path and try again, or use sudo umount -l /mnt/unraid/websites to lazy unmount.

The mount keeps dropping after a server restart. Make sure _netdev is in your fstab options. Without it, the system tries to mount the NFS share before the network is ready and silently fails.

rsync errors persist after adding the flags. Double check the flags are on the rsync line in your deploy script and not somewhere else. Run the rsync command manually first to confirm it works before testing through the script.

Summary
#

Two things were wrong. The NFS mount was pointing to /mnt/user/websites when the actual export path was /mnt/cache/websites because the share was configured to use cache-only storage on Unraid. Once that was fixed, rsync’s default metadata syncing caused permission errors on the target directory. Adding --no-group --omit-dir-times --no-perms to the rsync command resolved those. Both fixes together got the deploy running clean.