Understanding Linux File Permissions and ACLs
Misconfigured file permissions are one of the most common causes of security breaches, data leaks, and operational headaches on Linux systems. If you’ve ever needed to give specific users access to a file, or troubleshoot a “Permission denied” error that makes no sense, you’ve run into the limitations of the traditional Linux permission model. In this article, you’ll learn how to confidently use both classic Linux permissions and Access Control Lists (ACLs) to solve real-world problems—without creating an unmanageable mess.
Key Takeaways:
- Linux’s classic user-group-other permission model is fast and simple, but limited for complex, multi-user environments.
- ACLs allow you to assign granular permissions to multiple users and groups per file or directory.
- Proper use of
chmod,setfacl, andgetfaclwill solve most permission problems, but beware of ACL “mask” and backup/restore gotchas.- ACLs are powerful, but they add complexity and can be misunderstood—always document and monitor your permissions model in production.
Classic Linux Permissions
Every file and directory on a Linux filesystem has a set of permissions that define who can read, write, or execute it. The model is simple: each file has an owner, a group, and permissions for three classes—user (u), group (g), and others (o).
$ ls -l /var/log/syslog
-rw-r----- 1 root adm 49312 Mar 15 12:00 /var/log/syslog
# | | | | | |
# | | | | | +-- filename
# | | | +---------+---------- size and timestamp
# | | +--- group (adm)
# | +--- owner (root)
# +--- permissions (rw-r-----)
The permissions string (rw-r-----) means:
rw-(owner): read/write for rootr--(group): read for adm---(others): no access for anyone else
Permissions are set with chmod. Here’s a common pattern:
# Allow only the owner to read and write, deny all others
$ chmod 600 secrets.txt
$ ls -l secrets.txt
-rw------- 1 alice devs 42 Mar 15 11:00 secrets.txt
To change the owner or group (useful for shared filesystems):
# Set owner to bob and group to admin
$ sudo chown bob:admin financials.xlsx
$ ls -l financials.xlsx
-rw-r--r-- 1 bob admin 8160 Mar 15 10:00 financials.xlsx
Why Classic Permissions Aren’t Enough
- Only one user and one group can be assigned per file.
- To give multiple users different permissions, you must create special groups or duplicate files.
- No way to set default permissions for new files in a directory (other than
umask). - Complex team setups (dev, QA, ops) quickly become unmanageable.
For most single-user or simple group environments, this model is perfect: it’s fast, clear, and easy to audit. But for shared folders, multi-team projects, or secure collaboration, you need something more flexible.
Access Control Lists (ACLs)
ACLs extend the classic model by allowing you to assign permissions to multiple users and groups on a single file or directory—without creating new Unix groups for every project.
Modern Linux distributions (Ubuntu, RHEL, Debian, CentOS) support ACLs on ext4, xfs, and btrfs by default. You may need to ensure your filesystem is mounted with acl support:
$ mount | grep acl
/dev/sda1 on / type ext4 (rw,relatime,acl)
/dev/sdb1 on /data type xfs (rw,relatime,attr2,inode64,acl)
Viewing and Editing ACLs
You’ll use getfacl to view and setfacl to edit ACLs. Here’s a real-world workflow:
# Give bob read-write and devops group read-only access to a config file
$ setfacl -m u:bob:rw config.yaml
$ setfacl -m g:devops:r config.yaml
# See the ACL details
$ getfacl config.yaml
# file: config.yaml
# owner: alice
# group: devs
user::rw-
user:bob:rw-
group::r--
group:devops:r--
mask::rw-
other::---
The “mask” line is crucial: it limits the effective permissions for any named user/group (except the owner/others). If you later run chmod 600 config.yaml, the mask will change and could silently break access for bob or devops.
Setting Default ACLs
Default ACLs make new files and subdirectories inherit permissions. This is essential for shared team folders.
# All new files in /srv/project inherit group rw access and QA read-only
$ setfacl -d -m g:devs:rwX /srv/project
$ setfacl -d -m g:qa:rX /srv/project
Now, files and folders created under /srv/project will automatically get these permissions. The capital X means “execute only if directory or already executable”.
Removing ACLs
# Remove all ACLs from a file
$ setfacl --remove-all config.yaml
This resets the file back to classic permissions.
Practical Examples and Usage
Let’s walk through realistic, production-inspired scenarios that highlight both models.
Scenario 1: Shared Upload Directory
Your web app lets users upload files. You want the www-data user (web server) and the devops group to both have full access, but all others denied.
# Classic permissions can't do this easily—so use ACLs
$ mkdir /srv/uploads
$ chown www-data:devops /srv/uploads
$ chmod 770 /srv/uploads
$ setfacl -m u:www-data:rwx /srv/uploads
$ setfacl -m g:devops:rwx /srv/uploads
# Optional: make all new files inherit ACLs
$ setfacl -d -m u:www-data:rwx /srv/uploads
$ setfacl -d -m g:devops:rwx /srv/uploads
Scenario 2: Secure Logs for Multiple Teams
Ops, dev, and security teams all need different levels of access:
- Ops: read/write
- Dev: read-only
- Security: read/write
Classic groups can’t handle this, but ACLs can:
$ setfacl -m g:ops:rw /var/log/app.log
$ setfacl -m g:dev:r /var/log/app.log
$ setfacl -m g:security:rw /var/log/app.log
Scenario 3: Recursive ACL Application for Large Trees
When working with large project trees, you need to apply permissions recursively and set defaults:
# Recursively give QA read-only, DevOps full access, and set as default
$ setfacl -R -m g:qa:rX /srv/codebase
$ setfacl -R -m g:devops:rwX /srv/codebase
$ setfacl -R -d -m g:qa:rX /srv/codebase
$ setfacl -R -d -m g:devops:rwX /srv/codebase
If you don’t use -R and -d (default), new files might have unexpected permissions.
Comparison: Classic Permissions vs. ACLs
| Feature | Classic Permissions | ACLs |
|---|---|---|
| Granularity | User, group, others only (1 each) | Multiple users and groups, custom per file |
| Default inheritance | No | Yes (default ACLs) |
| Tooling | chmod, chown, ls | setfacl, getfacl, chmod, chown, ls |
| Complexity | Low (easy to audit; fast) | Medium-High (can be confusing; needs documentation) |
| Filesystem Support | Universal | Requires ACL-enabled filesystem and mount options |
| Backup/Restore | All tools support (tar, rsync, cp) | Need tar --acls, rsync -A to preserve ACLs |
| Performance Impact | Negligible | Minimal, but measurable on very large trees |
| Common Use Cases | Single-user, simple group sharing | Shared projects, multi-team access, SaaS multi-tenancy |
For further reading, see the Linux ACL man page and a practical guide on ArchWiki: Access Control Lists.
Common Pitfalls and Pro Tips
- Mask gotchas: The ACL mask sets the maximum allowed permissions for named users and groups. If you change a file’s group permissions with
chmod, the mask may be reset, unintentionally revoking access for ACL users. Always check withgetfaclafter changes. - Backup/restore headaches: Most backup tools will NOT preserve ACLs unless you specify them (
tar --acls,rsync -A). Always test restores in a dev environment before relying on ACLs for audit/compliance. - Filesystem support: Not all filesystems (especially network filesystems) support ACLs. Confirm with
mount | grep acland test before rolling out. - Complexity management: Document any use of ACLs and review them regularly. Overuse leads to unmanageable permission sets and security confusion.
- Diagnosing “Permission denied”: Always check for both classic permissions and ACLs:
$ namei -l /path/to/file $ getfacl /path/to/fileThese commands help you trace permissions at each directory level and reveal hidden ACLs.
- Default ACLs are not retroactive: Setting a default ACL on a directory only affects new files, not existing ones. Use
setfacl -Rto apply to current files.
Conclusion and Next Steps
Mastering Linux permissions and ACLs is essential for anyone managing multi-user systems, shared infrastructure, or sensitive data. Classic permissions are simple and fast for most use cases, but ACLs give you the power to build secure, collaborative workflows without sacrificing flexibility.
Action steps:
- Experiment with
chmod,setfacl, andgetfaclon a test VM or disposable directory. - Audit your current permissions: find files with ACLs using
find / -perm +1000 -exec getfacl {} + 2>/dev/null | grep -B1 'user:'. - Check your backups: verify that your archive tools preserve ACLs and test a restore with
getfacl. - Read the official documentation: Linux ACL man page and ArchWiki: ACLs.
If you’re building secure, multi-user Linux environments, understanding these tools could be the difference between a smooth deployment and a late-night incident. Bookmark this guide and revisit as your needs grow.




