getfacl & setfacl

Access Control Lists - Fine-Grained Permission Management

About ACLs (Access Control Lists)

The getfacl (get file access control list) and setfacl (set file access control list) commands manage POSIX Access Control Lists, which extend beyond traditional Unix permissions (owner/group/other). ACLs allow you to grant specific permissions to specific users and groups, providing much more granular control over file and directory access.

Traditional Permissions Limitations:

  • Standard Unix: owner, group, other (3 permission sets)
  • Problem: What if you need to grant access to 5 different users with different permission levels?
  • Solution: ACLs allow unlimited users and groups with specific permissions

Key Concepts:

  • getfacl: Displays ACLs for files and directories
  • setfacl: Sets or modifies ACLs
  • Access ACLs: Control access to the file/directory itself
  • Default ACLs: Apply to new files created in a directory (directories only)
  • Mask: Defines maximum permissions for named users/groups
  • Effective Permissions: Actual permissions = ACL entry AND mask

Common Use Cases:

  • Multi-user collaboration with different permission levels
  • Shared directories requiring complex access patterns
  • Web server directories with multiple application users
  • Database directories with separate backup user access
  • Project directories with team-specific permissions
  • Drop boxes where users can write but not read others' files
ACL Entry Types
Entry Type Format Description
User (owner) user::rwx Permissions for the file owner
Named user user:username:rwx Permissions for a specific user
Group (owning) group::rwx Permissions for the owning group
Named group group:groupname:rwx Permissions for a specific group
Mask mask::rwx Maximum effective permissions for named users/groups
Other other::rwx Permissions for everyone else
setfacl Common Options
Option Description
-m Modify ACL - add or change entries
-x Remove specific ACL entries
-b Remove all ACL entries (keep base permissions)
-k Remove default ACL entries
-d Set default ACL (for directories)
-R Recursive - apply to directory tree
--set Replace entire ACL (not merge)
--set-file Read ACL entries from file
--restore Restore ACLs from getfacl output
Detailed Examples

Example 1View Current ACLs

Display ACLs for a file to see current permissions:

$ touch testfile.txt $ ls -l testfile.txt
-rw-r--r-- 1 craig users 0 Dec 16 12:00 testfile.txt
$ getfacl testfile.txt
# file: testfile.txt # owner: craig # group: users user::rw- group::r-- other::r--

Explanation:

  • getfacl: Displays ACL for file
  • Comments (# lines): Show file, owner, group
  • user::: Owner permissions (rw-)
  • group::: Group permissions (r--)
  • other::: World permissions (r--)
  • No extended ACLs yet - just standard permissions
  • Matches what ls -l shows
Note: When no extended ACLs exist, getfacl shows the same information as traditional Unix permissions. The power comes when you add additional users and groups beyond the basic owner/group/other model.

Example 2Grant Access to Additional User

Give specific user read access without changing group or other permissions:

$ touch project-data.txt $ chmod 600 project-data.txt $ ls -l project-data.txt
-rw------- 1 craig users 0 Dec 16 12:05 project-data.txt
$ setfacl -m user:alice:r-- project-data.txt $ ls -l project-data.txt
-rw-r-----+ 1 craig users 0 Dec 16 12:05 project-data.txt
$ getfacl project-data.txt
# file: project-data.txt # owner: craig # group: users user::rw- user:alice:r-- group::--- mask::r-- other::---

Explanation:

  • -m user:alice:r--: Grant alice read permission
  • Note the '+' in ls -l: indicates extended ACL
  • user:alice:r--: Alice can read the file
  • mask::r--: Auto-created, limits max permissions
  • Group and other still have no access
  • Only craig (owner) and alice can access this file
Tip: The '+' symbol in ls -l output is your quick indicator that a file has extended ACLs. Always check getfacl to see the full picture when you see that plus sign.

Example 3Grant Access to Multiple Users

Give different permissions to several specific users:

$ mkdir shared-project $ setfacl -m user:alice:rwx shared-project/ $ setfacl -m user:bob:r-x shared-project/ $ setfacl -m user:charlie:r-- shared-project/ $ getfacl shared-project/
# file: shared-project/ # owner: craig # group: users user::rwx user:alice:rwx user:bob:r-x user:charlie:r-- group::r-x mask::rwx other::r-x

Explanation:

  • Multiple setfacl -m commands add entries
  • alice: Full access (rwx)
  • bob: Read and execute (r-x) - can list and enter
  • charlie: Read only (r--) - can list but not enter
  • mask::rwx: Allows up to full permissions
  • Each user has exactly the access they need
Note: Multiple setfacl commands can be combined: setfacl -m user:alice:rwx,user:bob:r-x,user:charlie:r-- shared-project/ achieves the same result in one command.

Example 4Default ACLs for New Files

Set default ACLs so new files automatically inherit permissions:

$ mkdir project-dir $ setfacl -d -m user:alice:rw- project-dir/ $ setfacl -d -m user:bob:r-- project-dir/ $ getfacl project-dir/
# file: project-dir/ # owner: craig # group: users user::rwx group::r-x other::r-x default:user::rwx default:user:alice:rw- default:user:bob:r-- default:group::r-x default:mask::rwx default:other::r-x
$ touch project-dir/newfile.txt $ getfacl project-dir/newfile.txt
# file: project-dir/newfile.txt # owner: craig # group: users user::rw- user:alice:rw- user:bob:r-- group::r-x #effective:r-- mask::rw- other::r-x

Explanation:

  • -d: Sets default ACL (directories only)
  • Default ACLs shown with "default:" prefix
  • New files automatically inherit these permissions
  • alice automatically gets rw- on new files
  • bob automatically gets r-- on new files
  • No need to set ACLs on each new file
Tip: Default ACLs are essential for shared project directories. Set them once on the parent directory, and all new files and subdirectories automatically inherit the proper permissions. Saves enormous administrative overhead!

Example 5Grant Access to Groups

Give permissions to entire groups rather than individual users:

$ mkdir /data/reports $ setfacl -m group:analysts:r-x /data/reports/ $ setfacl -m group:managers:rwx /data/reports/ $ getfacl /data/reports/
# file: data/reports/ # owner: root # group: root user::rwx group::r-x group:analysts:r-x group:managers:rwx mask::rwx other::---

Explanation:

  • group:analysts:r-x: All analysts can read/list
  • group:managers:rwx: Managers have full access
  • Any user in 'analysts' group gets read access
  • Any user in 'managers' group gets full access
  • Cleaner than listing individual users
  • Easier maintenance - add users to groups, not ACLs
Best Practice: Use group-based ACLs when possible rather than individual user ACLs. Managing group membership is easier than managing hundreds of individual ACL entries. Keep ACLs simple and maintainable.

Example 6Understanding the Mask

The mask limits maximum effective permissions for named users/groups:

$ touch important.txt $ setfacl -m user:alice:rwx important.txt $ getfacl important.txt
# file: important.txt # owner: craig # group: users user::rw- user:alice:rwx group::r-- mask::rwx other::r--
$ chmod g-w important.txt # Changes the mask! $ getfacl important.txt
# file: important.txt # owner: craig # group: users user::rw- user:alice:rwx #effective:r-- group::r-- mask::r-- other::r--

Explanation:

  • alice granted rwx permissions
  • Initial mask is rwx (allows full permissions)
  • chmod g-w removes group write, affects mask
  • Mask becomes r-- (read only)
  • alice's effective permissions: rwx AND r-- = r--
  • Mask provides safety limit on ACL permissions
Important: The mask can restrict ACL permissions! Even if you grant rwx to a user, the mask limits actual permissions. When using chmod on files with ACLs, you're actually modifying the mask, which affects all named users and groups. Use setfacl -m mask::rwx to explicitly set the mask.

Example 7Remove Specific ACL Entries

Remove ACL entries for specific users or groups:

$ touch shared.txt $ setfacl -m user:alice:rw- shared.txt $ setfacl -m user:bob:r-- shared.txt $ setfacl -m user:charlie:rw- shared.txt $ getfacl shared.txt
user::rw- user:alice:rw- user:bob:r-- user:charlie:rw- group::r-- mask::rw- other::r--
$ setfacl -x user:bob shared.txt $ getfacl shared.txt
user::rw- user:alice:rw- user:charlie:rw- group::r-- mask::rw- other::r--

Explanation:

  • -x user:bob: Remove ACL entry for bob
  • bob's entry is completely removed
  • alice and charlie entries remain
  • bob now has only "other" permissions
  • Use -x to revoke specific access
  • Can also remove group entries: -x group:groupname
Tip: To remove multiple ACL entries: setfacl -x user:alice,user:bob,group:staff file. Comma-separate entries for batch removal.

Example 8Remove All ACLs

Strip all extended ACLs and return to basic permissions:

$ touch complex.txt $ setfacl -m user:alice:rw- complex.txt $ setfacl -m user:bob:r-- complex.txt $ setfacl -m group:staff:rw- complex.txt $ ls -l complex.txt
-rw-rw----+ 1 craig users 0 Dec 16 13:00 complex.txt
$ setfacl -b complex.txt $ ls -l complex.txt
-rw-r----- 1 craig users 0 Dec 16 13:00 complex.txt
$ getfacl complex.txt
# file: complex.txt # owner: craig # group: users user::rw- group::r-- other::---

Explanation:

  • -b: Remove all ACL entries
  • '+' disappears from ls -l output
  • Only base permissions remain (owner/group/other)
  • alice, bob, and staff lose special access
  • Returns file to traditional permission model
  • Useful for cleanup or troubleshooting
Warning: setfacl -b removes ALL extended ACLs immediately. This is permanent and cannot be undone. Consider backing up ACLs first: getfacl file > file.acl.backup before using -b.

Example 9Backup and Restore ACLs

Save ACLs to file and restore them later:

$ mkdir project/ $ setfacl -m user:alice:rwx project/ $ setfacl -m user:bob:r-x project/ $ setfacl -d -m user:alice:rw- project/ # Backup ACLs $ getfacl -R project/ > project-acls.txt $ cat project-acls.txt
# file: project/ # owner: craig # group: users user::rwx user:alice:rwx user:bob:r-x group::r-x mask::rwx other::r-x default:user::rwx default:user:alice:rw- default:group::r-x default:mask::rwx default:other::r-x
# Simulate loss of ACLs $ setfacl -b project/ # Restore ACLs $ setfacl --restore=project-acls.txt $ getfacl project/
# file: project/ # owner: craig # group: users user::rwx user:alice:rwx user:bob:r-x group::r-x mask::rwx other::r-x default:user::rwx default:user:alice:rw- default:group::r-x default:mask::rwx default:other::r-x

Explanation:

  • getfacl -R: Backup all ACLs recursively
  • Output saved to text file
  • --restore: Restore ACLs from file
  • All ACLs restored exactly as saved
  • Essential for disaster recovery
  • Useful for cloning ACLs to similar directories
Tip: Include ACL backups in your regular backup procedures: getfacl -R /data > /backup/acls-$(date +%Y%m%d).txt. When restoring from backup, you'll need both the files AND their ACLs to restore complete access control.

Example 10Recursive ACL Application

Apply ACLs to entire directory tree at once:

$ mkdir -p webapp/{config,logs,data} $ touch webapp/config/settings.conf $ touch webapp/logs/access.log $ touch webapp/data/users.db # Apply ACLs recursively $ setfacl -R -m user:webuser:r-x webapp/ $ setfacl -R -m user:webuser:rw- webapp/logs/ $ setfacl -R -m user:webuser:rw- webapp/data/ # Set default ACLs for future files $ setfacl -R -d -m user:webuser:r-x webapp/ $ setfacl -d -m user:webuser:rw- webapp/logs/ $ setfacl -d -m user:webuser:rw- webapp/data/ $ getfacl webapp/logs/access.log
# file: webapp/logs/access.log # owner: craig # group: users user::rw- user:webuser:rw- group::r-- mask::rw- other::r--

Explanation:

  • -R: Apply ACLs recursively to all files/dirs
  • webuser gets r-x on whole tree (read/execute)
  • webuser gets rw- on logs/ and data/ (read/write)
  • -d: Set default ACLs for new files
  • New files in logs/ will auto-get rw- for webuser
  • Perfect for web application directories
Real-World Example: This is a classic web application setup. The web server user (webuser) needs: (1) read access to config files, (2) read/write to logs for writing, (3) read/write to data for database operations. Default ACLs ensure new log files are automatically writable.
Related Commands and Tools
Common Pitfalls and Solutions
Pitfall 1: Not Understanding the Mask

Setting ACL permissions that are restricted by the mask without realizing it.

Solution: Always check getfacl output for "#effective:" comments. If permissions don't work as expected, explicitly set mask: setfacl -m mask::rwx file. Remember: effective permissions = ACL entry AND mask.

Pitfall 2: Forgetting Default ACLs

Setting ACLs on directory but not default ACLs - new files don't inherit permissions.

Solution: For directories, always set both access AND default ACLs: setfacl -m user:alice:rwx dir/ && setfacl -d -m user:alice:rw- dir/. Default ACLs determine what new files inherit.

Pitfall 3: ACL/Backup Tool Incompatibility

Many backup tools (rsync, tar) don't preserve ACLs by default.

Solution: Use ACL-aware options: rsync -A, tar --acls, cp --preserve=all. Or backup ACLs separately: getfacl -R / > /backup/all-acls.txt. Test restore procedures!

Pitfall 4: Filesystem Doesn't Support ACLs

NFS, FAT32, some network mounts don't support ACLs.

Solution: Check filesystem: mount | grep acl. ext4, XFS, Btrfs support ACLs. Some need mount option: mount -o acl. NFSv4 has different ACL system. For unsupported filesystems, use groups and traditional permissions.

Pitfall 5: chmod Unexpectedly Modifying ACLs

Using chmod on ACL-enabled files changes the mask, affecting multiple users.

Solution: Understand that chmod group permissions modify the mask. To change only base permissions without affecting mask: remove ACLs first, chmod, re-add ACLs. Or use setfacl exclusively.

Pitfall 6: ACL Complexity Spiraling

Adding too many individual user ACLs becomes unmaintainable.

Solution: Use groups! Create groups for roles (developers, analysts, viewers) and grant ACLs to groups, not individuals. Much easier to manage. Keep it simple - if you have >10 ACL entries per file, rethink your design.

Pro Tips and Best Practices
Tip 1: Test ACLs as Target User

Verify ACLs work as intended:

sudo -u alice cat /path/to/file sudo -u bob ls -l /path/to/directory

Actually testing as the user reveals mask issues and unexpected restrictions.

Tip 2: Document ACL Strategy

Create README files explaining ACL structure:

cat > /data/ACL-POLICY.txt << 'EOF' /data/project/ - developers: rwx (full access) - testers: r-x (read/list only) - backup: r-- (backup user, read only) Default ACLs ensure new files inherit permissions EOF

Helps future administrators understand the design.

Tip 3: Periodic ACL Audits

Regularly review ACLs for unexpected changes:

find /data -type f -perm /u+x,g+x -exec getfacl {} \; | \ grep "^user:[^:]" > /var/log/acl-audit-$(date +%Y%m%d).log

Catches unauthorized ACL modifications. Compare with previous audits.

Tip 4: Use ACLs with SELinux/AppArmor

ACLs and MAC systems work together (defense in depth):

setfacl -m user:webuser:rw- /var/www/uploads/ # Plus SELinux context: chcon -t httpd_sys_rw_content_t /var/www/uploads/

ACLs control discretionary access, SELinux controls mandatory access.

Tip 5: Copy ACLs Between Similar Directories

Clone ACL structure to similar directories:

getfacl /data/project1 | setfacl --set-file=- /data/project2

Pipe getfacl output directly to setfacl for quick cloning. Great for creating similar project directories.

Tip 6: Monitor ACL Changes with auditd

Track who modifies ACLs:

auditctl -w /usr/bin/setfacl -p x -k acl_changes ausearch -k acl_changes

Security monitoring - alerts when ACLs are changed.

Historical Note: POSIX ACLs were defined in the withdrawn POSIX 1003.1e draft standard in 1997, though never officially ratified. Linux implemented them starting with kernel 2.6 for ext2/ext3 filesystems. They're based on the NFSv4 ACL model and have become essential for enterprise file sharing and complex permission scenarios. While not part of the official POSIX standard, they're supported across Linux, BSD, and other Unix-like systems with consistent behavior.
Quick Reference Cheat Sheet
Task Command
View ACLs getfacl file
Grant user access setfacl -m user:username:rwx file
Grant group access setfacl -m group:groupname:rx file
Remove user ACL setfacl -x user:username file
Remove all ACLs setfacl -b file
Set default ACL setfacl -d -m user:username:rwx directory/
Recursive ACLs setfacl -R -m user:username:rx directory/
Backup ACLs getfacl -R directory/ > backup.acl
Restore ACLs setfacl --restore=backup.acl
Set mask explicitly setfacl -m mask::rwx file
Multiple entries setfacl -m user:alice:rwx,user:bob:rx file
Common Use Case Templates

Ready-to-Use ACL Patterns

Scenario Command Template
Shared project directory setfacl -m user:user1:rwx,user:user2:rx dir/
setfacl -d -m user:user1:rw-,user:user2:r-- dir/
Drop box (write-only) setfacl -m user:dropuser:-wx dir/
chmod 733 dir/
Read-only for group setfacl -R -m group:readers:r-x dir/
setfacl -d -m group:readers:r-- dir/
Web application dir setfacl -R -m user:www-data:rwx /var/www/app/
setfacl -R -d -m user:www-data:rw- /var/www/app/
Backup user access setfacl -R -m user:backup:r-x /data/
setfacl -R -d -m user:backup:r-- /data/
Multi-tier access setfacl -m user:admin:rwx,group:editors:rw-,group:viewers:r-- dir/