An NFS permission denial usually means the client reached the mounted export but the server rejected a file operation for the user behind the request. It often appears after a mount succeeds, when an application account or shell user cannot create, list, rename, or change files under the shared path.

The server decision combines the active export rule with filesystem ownership, mode bits, ACLs, and the identity sent by the client. With sec=sys, numeric UID, GID, and supplementary group values matter; with Kerberos security flavors, a missing credential or mismatched sec= value can block access before Unix mode bits become the deciding factor.

Test as the affected user, not only as root, because root_squash maps client UID 0 to the export's anonymous UID and GID. Tie each fix to the observed signal. Reload exports when /etc/exports changed, adjust account or group mapping when numeric IDs do not match, and change directory modes only after confirming the server path should allow that access.

Steps to troubleshoot NFS permission denied errors:

  1. Reproduce the denied operation from the client as the affected user.
    $ sudo -u projectuser touch /mnt/projects/report.txt
    touch: cannot touch '/mnt/projects/report.txt': Permission denied

    Use the same account, service context, and mounted path that first reported the failure. If only client-root access fails, root_squash may be working as intended.

  2. Identify the active NFS mount and security flavor.
    $ findmnt -t nfs,nfs4 /mnt/projects
    TARGET        SOURCE                              FSTYPE OPTIONS
    /mnt/projects files.example.net:/srv/nfs/projects nfs4   rw,relatime,vers=4.2,proto=tcp,sec=sys

    If the mount is read-only or uses a different sec= flavor than the export permits, fix that boundary before changing ownership or modes.

  3. Check the active export rule on the NFS server.
    $ sudo exportfs -v
    /srv/nfs/projects
            192.0.2.0/24(sync,wdelay,hide,no_subtree_check,sec=sys,rw,root_squash,no_all_squash)

    If the output shows ro, a missing client selector, or a different sec= value from the client mount, correct the saved export definition and reload it before changing filesystem ownership.

  4. Check the server-side directory ownership and mode with numeric IDs.
    $ ls -ldn /srv/nfs/projects
    drwxrws--- 2 0 2000 4096 Jul  5 09:20 /srv/nfs/projects

    Numeric IDs avoid name-service confusion. A trailing + on the mode, such as drwxrws---+, means POSIX ACL entries also affect access and should be inspected before changing the base mode.

  5. Check the affected user's numeric identity on the client.
    $ id projectuser
    uid=1001(projectuser) gid=1001(projectuser) groups=1001(projectuser)

    For sec=sys mounts, the server receives these numeric IDs. For centrally managed accounts, fix the identity service or group membership source rather than only one client host.

  6. Add the affected user to the shared group when that group should grant access.
    $ sudo usermod --append --groups projectusers projectuser

    Start a new login session for projectuser or restart the affected service so the process receives the updated supplementary group list.

  7. Correct the exported directory group when the server path uses the wrong group.
    $ sudo chgrp projectusers /srv/nfs/projects

    Change ownership only after confirming which group should control the shared data. A group change on an active export affects every client using that path.

  8. Set group-write and setgid mode on the exported directory.
    $ sudo chmod 2770 /srv/nfs/projects

    The setgid bit keeps new entries under the directory's group. Use a narrower mode or a POSIX ACL when only selected users should write.

  9. Reload exports only if the saved export rule changed.
    $ sudo exportfs -rv
    exporting 192.0.2.0/24:/srv/nfs/projects

    Ownership, mode, and ACL changes take effect through the filesystem and normally do not require an export reload.

  10. Confirm that the client session now includes the shared group.
    $ id projectuser
    uid=1001(projectuser) gid=1001(projectuser) groups=1001(projectuser),2000(projectusers)

    If the group is still missing, refresh the user's login session, restart the affected service, or fix the directory-service membership before retesting the NFS path.

  11. Retest the original client write as the affected user.
    $ sudo -u projectuser touch /mnt/projects/report.txt

    No output from touch means the file was created or its timestamp was updated successfully.

  12. Verify the created file ownership through the mounted path.
    $ sudo -u projectuser stat -c '%U %G %A %n' /mnt/projects/report.txt
    projectuser projectusers -rw-r--r-- /mnt/projects/report.txt

    If the owner or group appears as nobody, compare the NFSv4 identity mapping domain and clear stale idmap cache entries before changing directory permissions again.
    Related: How to troubleshoot NFS ID mapping

  13. Remove the temporary probe file.
    $ sudo -u projectuser rm /mnt/projects/report.txt