setfacl Command in Linux: ACL Permissions Examples

Learn the setfacl command in Linux for ACL permissions, including user and group access, defaults, recursion, backups, and fixes.

PublishedAuthorJoshua JamesRead time9 minGuide typeLinux Commands

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...
  • -m or --modify adds or changes an ACL entry.
  • -x or --remove removes one ACL entry.
  • -b removes all extended ACL entries while leaving the base owner, group, and other entries.
  • -k removes default ACL entries from a directory.
  • -R applies 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

TaskCommand PatternWhat It Does
Grant a user accesssetfacl -m u:alice:rw fileAdds or updates read and write access for the named user.
Grant a group accesssetfacl -m g:developers:r-x dirAdds read and traversal access for the named group.
Set inherited directory accesssetfacl -m d:g:developers:rwx dirAdds a default ACL entry that new files and subdirectories inherit.
Remove one named entrysetfacl -x u:alice fileDeletes the named user ACL entry without changing base permissions.
Remove all extended entriessetfacl -b fileReturns the path to base owner, group, and other ACL entries.
Preview the resultsetfacl --test -m u:alice:r filePrints 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
  • u or user targets a named user, such as u:alice:rw.
  • g or group targets a named group, such as g:developers:r-x.
  • m or mask sets the maximum effective access for named users, named groups, and the owning group.
  • o or other targets everyone not matched by owner, user, group, or named-group entries.
  • d: or default: marks a directory default ACL entry, such as d: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

openSUSE Tumbleweed:

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.txt first, 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.

Share this guide

Help another Linux user troubleshoot faster

Share this guide with someone troubleshooting Linux systems or saving it for later.

Follow LinuxCapable

Want more LinuxCapable guides in Google?

Add LinuxCapable as a preferred source so Google can show our tutorials more often in Top Stories and mark them as preferred in AI Mode and AI Overviews when relevant.

Add LinuxCapable as a preferred source on Google
Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffeeBuy me a coffee
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<a href="https://example.com">link</a> link
<blockquote>quote</blockquote> quote block

Add to the discussion

Questions, fixes, command output, and version notes help keep this guide current.

Verify before posting: