Shared directories get awkward when owner, group, and other permission bits are too blunt. The setfacl command in Linux lets you grant a specific user or group access without changing file ownership or opening the file to everyone.
Use ACLs when normal chmod permissions cannot express the access rule cleanly: a web server needs read access to one upload folder, a backup account needs traversal rights, or a project group should inherit access on new files.
Understand the setfacl Command in Linux
setfacl edits POSIX Access Control Lists, usually shortened to ACLs. An ACL adds named user, named group, mask, and default-directory entries beside the familiar owner, group, and other permissions.
What setfacl Changes Beyond chmod
chmod changes the base permission bits for the owner, owning group, and everyone else. setfacl keeps those base entries but can add extra rules for named accounts or groups. After a file has an extended ACL, ls -l normally shows a plus sign after the permission string.
ls -l report.txt
Example output for a file with an extended ACL looks like:
-rw-rw-r--+ 1 user group 6 May 9 13:00 report.txt
The plus sign tells you to inspect the ACL with getfacl before assuming the visible mode bits tell the full story. The Linux ACL manual describes access ACLs for files and default ACLs for directories.
setfacl Command Syntax
The common syntax modifies or removes ACL entries on one or more paths:
setfacl [OPTIONS] -m ACL_ENTRY FILE...
setfacl [OPTIONS] -x ACL_ENTRY FILE...
-mor--modifyadds or changes an ACL entry.-xor--removeremoves one ACL entry.-bremoves all extended ACL entries while leaving the base owner, group, and other entries.-kremoves default ACL entries from a directory.-Rapplies the change recursively, which should be previewed and scoped carefully.
The setfacl manual page documents the full option set, including file-based ACL input with -M, removal input with -X, dry-run output with --test, and backup restoration with --restore.
Essential setfacl Options by Task
| Task | Command Pattern | What It Does |
|---|---|---|
| Grant a user access | setfacl -m u:alice:rw file | Adds or updates read and write access for the named user. |
| Grant a group access | setfacl -m g:developers:r-x dir | Adds read and traversal access for the named group. |
| Set inherited directory access | setfacl -m d:g:developers:rwx dir | Adds a default ACL entry that new files and subdirectories inherit. |
| Remove one named entry | setfacl -x u:alice file | Deletes the named user ACL entry without changing base permissions. |
| Remove all extended entries | setfacl -b file | Returns the path to base owner, group, and other ACL entries. |
| Preview the result | setfacl --test -m u:alice:r file | Prints the ACL that would result without changing the file. |
ACL Entry Format for setfacl
An ACL entry has three main fields separated by colons:
type:name:permissions
uorusertargets a named user, such asu:alice:rw.gorgrouptargets a named group, such asg:developers:r-x.mormasksets the maximum effective access for named users, named groups, and the owning group.oorothertargets everyone not matched by owner, user, group, or named-group entries.d:ordefault:marks a directory default ACL entry, such asd:g:developers:rwx.
Use r, w, and x for read, write, and execute or directory traversal. Capital X is useful in recursive changes because it adds execute only to directories and to files that already have at least one execute bit.
Install the setfacl Command on Linux
Many desktop and server installs already include setfacl and getfacl. Minimal containers, cloud images, and custom server builds may omit the ACL utilities even when the filesystem itself supports ACLs.
Verify setfacl and getfacl Are Available
Check that the shell can find setfacl:
command -v setfacl
/usr/bin/setfacl
Confirm the utility version if the command exists:
setfacl --version
getfacl --version
setfacl 2.3.2 getfacl 2.3.2
The exact version can differ by distribution. The important result is that both commands exist, because setfacl changes ACLs and getfacl verifies them.
Install ACL Utilities by Distribution
Most package databases name the utility package acl. Official package indexes list getfacl and setfacl in the Ubuntu acl package, Debian acl package, Fedora acl package, Arch acl package, and Alpine acl package. Gentoo exposes the same utilities through the Gentoo sys-apps/acl package.
If your minimal distribution does not include sudo, open a root shell first or use the privilege tool configured for that system, such as doas on some Alpine installs.
Debian, Ubuntu, and Linux Mint:
sudo apt update
sudo apt install acl
Fedora, RHEL, CentOS Stream, Rocky Linux, and AlmaLinux:
sudo dnf install acl
Arch Linux and Manjaro:
sudo pacman -S acl
Alpine Linux:
sudo apk add acl
Gentoo Linux:
sudo emerge --ask sys-apps/acl
sudo zypper install acl
Practical setfacl Command Examples
The examples use local files so you can practice without changing system paths. Replace placeholder names such as alice and developers with real accounts and groups before running commands that name them.
Create a Safe setfacl Practice Fixture
Create a small working directory and sample file. The chmod lines make the example output consistent even when your shell uses a stricter umask:
mkdir -p acl-demo/shared
cd acl-demo
printf 'draft\n' > report.txt
chmod 664 report.txt
chmod 775 shared
The mkdir command creates the practice directory tree. Keep your terminal inside acl-demo for the remaining examples.
Grant a User Read and Write Access
Grant a named user read and write access to a file without changing the file owner:
setfacl -m u:alice:rw report.txt
getfacl -c report.txt
user::rw- user:alice:rw- group::rw- mask::rw- other::r--
The user:alice:rw- line is the new named-user entry. The mask::rw- line allows those read and write permissions to remain effective.
Grant a Group Access to a Directory
Directory access needs execute permission for traversal. Use rwx when the group should list, enter, create, and edit content in the directory:
setfacl -m g:developers:rwx shared
getfacl -c shared
user::rwx group::rwx group:developers:rwx mask::rwx other::r-x
That change affects the shared directory itself. Existing files inside the directory keep their own ACLs until you change them separately.
Remove a User ACL Entry
Remove a named user entry with -x. Do not include the permission field when deleting an entry:
setfacl -x u:alice report.txt
getfacl -c report.txt
user::rw- group::rw- mask::rw- other::r--
The named-user line is gone, while the base owner, group, and other entries remain.
Set Default ACLs for New Files
A default ACL belongs to a directory and affects files or subdirectories created later. Pair a normal access ACL with a default ACL when the directory itself and future content both need the same group access:
setfacl -m g:developers:rwx shared
setfacl -m d:g:developers:rwx shared
touch shared/new-file
getfacl -c shared/new-file
user::rw- group::rwx #effective:rw- group:developers:rwx #effective:rw- mask::rw- other::r--
The new file inherits the named group entry, but the effective access is rw- because regular files are normally created without execute permission. New directories can inherit traversal permission because directories need execute access to be usable.
Limit Effective Rights with the ACL Mask
The ACL mask caps the effective permissions for named users, named groups, and the owning group. This explains cases where an entry appears to grant access but getfacl shows a narrower effective result:
setfacl -m u:alice:rwx,m::r report.txt
getfacl -c report.txt
user::rw- user:alice:rwx #effective:r-- group::rw- #effective:r-- mask::r-- other::r--
The entry says rwx, but the mask allows only read access. To allow the full named-user entry, widen the mask deliberately:
setfacl -m m::rwx report.txt
getfacl -c report.txt
user::rw- user:alice:rwx group::rw- mask::rwx other::r--
Preview a setfacl Change Before Applying It
--test prints the resulting ACL without changing the file. Use it when you are testing a mask, default entry, or recursive pattern:
setfacl --test -m u:alice:r report.txt
report.txt: u::rw-,u:alice:r--,g::rw-,m::rw-,o::r--,*
The asterisk marks the ACL that would be written. If the preview is not what you expected, adjust the ACL entry before making the real change.
Copy ACLs Between Files
getfacl output can feed directly into setfacl. This copies the access ACL from one file to another:
printf 'source\n' > source.txt
printf 'dest\n' > dest.txt
setfacl -m u:alice:rw source.txt
getfacl --access source.txt | setfacl --set-file=- dest.txt
getfacl -c dest.txt
user::rw- user:alice:rw- group::rw- mask::rw- other::r--
Use this pattern when a template file has the exact ACL you want and another file should match it.
Use setfacl Recursively Without Surprises
Recursive ACL changes are powerful because they can repair a whole project tree in one pass. They are also easy to over-apply, so preview the target list before changing anything.
Recursive permission changes can expose or break many files at once. Preview the affected paths first, keep the target directory narrow, and avoid running recursive ACL changes from
/,/etc, or a whole home directory unless you have a tested recovery plan.
Preview Recursive setfacl Targets
Create a separate tree for recursive tests, then list the paths that would be affected before applying a recursive ACL:
mkdir -p recursive-demo/subdir
printf 'plain\n' > recursive-demo/subdir/plain.txt
chmod 664 recursive-demo/subdir/plain.txt
find recursive-demo -print
recursive-demo recursive-demo/subdir recursive-demo/subdir/plain.txt
For narrower matches, use the patterns from the find command with exec guide before applying ACLs to selected files or directories.
Apply Recursive setfacl Access with Capital X
Capital X keeps directories traversable without making every regular file executable:
setfacl -R -m u:alice:rwX recursive-demo
getfacl -c recursive-demo
user::rwx user:alice:rwx group::rwx mask::rwx other::r-x
The directory gets execute permission for traversal. Check the regular file to confirm capital X did not turn it into an executable file:
getfacl -c recursive-demo/subdir/plain.txt
user::rw- user:alice:rw- group::rw- mask::rw- other::r--
Use rwX for shared trees where directories need traversal and existing executable files should stay executable, but ordinary data files should not become programs.
Follow or Skip Symbolic Links Recursively
Recursive setfacl can treat symbolic links differently depending on the walk option. The default behavior follows symbolic link arguments but skips symbolic links found inside subdirectories. Add -P for a physical walk that does not follow symbolic links to directories, or -L for a logical walk that follows them.
setfacl -R -P -m g:developers:rX recursive-demo
Use -P for the safer default in backup, deployment, and shared-directory repair workflows where a symlink could point outside the intended tree.
Back Up and Restore ACLs with setfacl
ACL changes are easier to trust when you can roll them back. getfacl -R creates a text backup that setfacl --restore can read later.
getfacl -R shared > acl-backup.txt
setfacl -m g:developers:r-- shared/new-file
The getfacl manual notes that its output can be used as setfacl input. The second command narrows one entry so the restore step has a visible change to undo.
Restoring an ACL backup can reset permissions across the recorded subtree. Review
acl-backup.txtfirst, especially if the file was created on another system or before ownership changes.
Restore the recorded ACLs when you need to undo the subtree change:
setfacl --restore=acl-backup.txt
Verify one affected file after the restore:
getfacl -c shared/new-file
user::rw- group::rwx #effective:rw- group:developers:rwx #effective:rw- mask::rw- other::r--
Remove ACLs with setfacl
Removing ACLs should be as deliberate as adding them. Decide whether you want to remove one entry, remove all extended entries, or remove only directory defaults.
Remove One setfacl Entry
Use -x for one named entry:
setfacl -x u:alice report.txt
Verify that the named-user entry is gone:
getfacl -c report.txt
user::rw- group::rw- mask::rw- other::r--
This is the safest cleanup when only one temporary user or group should lose access.
Remove All Extended setfacl Entries
Use -b when the file should return to base owner, group, and other entries:
setfacl -b report.txt
getfacl -c report.txt
user::rw- group::rw- other::r--
After -b, ls -l should no longer show the plus sign for that file unless another ACL was added again.
Remove Default setfacl Entries from a Directory
Use -k when future files should stop inheriting default ACL entries from a directory:
setfacl -k shared
getfacl -c shared
user::rwx group::rwx group:developers:rwx mask::rwx other::r-x
Existing files keep their current ACLs. -k only removes the directory’s default ACL template for future content.
Use setfacl Safely and Effectively
Verify ACLs Before and After Changes
Use getfacl before changing important paths, then run it again after the change. That makes the mask, default entries, and inherited rules visible instead of leaving you to infer behavior from ls -l.
getfacl -c shared
user::rwx group::rwx group:developers:rwx mask::rwx other::r-x
Prefer Group ACLs for Shared Workflows
Granting a group ACL is easier to maintain than adding many individual user entries. Add or remove users from the group with normal account-management tools, then keep the ACL focused on the shared role.
Remember What ACLs Do Not Override
ACLs do not bypass ownership rules, root privileges, SELinux, AppArmor, read-only mounts, or application-level checks. If access still fails after the ACL looks correct, inspect the full path, the mount options, and any mandatory access-control layer that applies to the service.
Troubleshoot Common setfacl Errors
Most setfacl failures come from missing utilities, invalid account names, insufficient ownership rights, a restrictive ACL mask, or a filesystem that does not support POSIX ACLs.
Fix setfacl Command Not Found
A minimal system may not include the ACL utilities:
bash: setfacl: command not found
Install the package for your distribution, then confirm the command path:
command -v setfacl
/usr/bin/setfacl
Fix Invalid setfacl User or Group Entries
An invalid ACL entry, missing user, or missing group can trigger this error:
setfacl: Option -m: Invalid argument near character 3
Check that the account or group exists before applying the ACL:
id -un alice
getent group developers | cut -d: -f1
Successful checks print the account and group names:
alice developers
If either line is missing, correct the name or create the account or group through your normal user-management workflow before rerunning setfacl.
Fix setfacl Operation Not Permitted
setfacl requires file ownership or elevated privileges. A file owned by another account can produce this error:
setfacl: report.txt: Operation not permitted
Check ownership first:
ls -l report.txt
Example output for a root-owned file looks like:
-rw-r--r-- 1 root root 6 May 9 13:00 report.txt
Use sudo only when the file should remain owned by another account and you administer the system:
sudo setfacl -m u:alice:rw report.txt
sudo getfacl -c report.txt
user::rw- user:alice:rw- group::r-- mask::rw- other::r--
Fix ACL Mask Permissions That Hide Access
If getfacl shows #effective comments, the mask is limiting the real access:
user:alice:rwx #effective:r-- mask::r--
Widen the mask only as far as the named entries should actually allow:
setfacl -m m::rwx report.txt
getfacl -c report.txt
user::rw- user:alice:rwx group::rw- mask::rwx other::r--
Fix Default ACLs Not Affecting Existing Files
A default ACL affects new content only. If existing files need the same access, apply both an access ACL to existing paths and a default ACL for future paths:
Preview the target tree before running the recursive repair:
find shared -print
shared shared/new-file
setfacl -R -m g:developers:rwX shared
find shared -type d -exec setfacl -m d:g:developers:rwx {} +
The first command updates current files and directories. The second command updates default ACLs on directories so new content inherits the group entry.
Confirm the directory has both access and default entries for the group:
getfacl -c shared
user::rwx group::rwx group:developers:rwx mask::rwx other::r-x default:user::rwx default:group::rwx default:group:developers:rwx default:mask::rwx default:other::r-x
Fix Filesystem ACL Support Problems
Some network, removable, or special-purpose filesystems may not support POSIX ACLs, or they may be mounted with ACL support disabled:
setfacl: report.txt: Operation not supported
Check the filesystem type and mount options for the target path:
findmnt -T report.txt -o TARGET,FSTYPE,OPTIONS
Example output on an ACL-capable ext4 filesystem looks like:
TARGET FSTYPE OPTIONS / ext4 rw,relatime
If the options include noacl, or the filesystem does not support POSIX ACLs, move the workload to a compatible filesystem or adjust the mount configuration according to your distribution’s storage policy.
Conclusion
ACL-backed permissions are manageable once you treat setfacl, getfacl, the mask, and default directory entries as one workflow. Start with a narrow path, verify the effective rights, and keep recursive changes backed up so shared access stays intentional instead of becoming another hard-to-debug permission problem.


Formatting tips for your comment
You can use basic HTML to format your comment. Useful tags currently allowed in published comments:
<code>command</code>command<strong>bold</strong><em>italic</em><a href="https://example.com">link</a><blockquote>quote</blockquote>