11.7 Access Control Lists (ACLs): getfacl and setfacl
Right, so you’ve mastered the basic chmod and chown incantations. You feel pretty good about yourself, and you should. But then you hit a wall. What if you need to give two different users two different sets of permissions on the same file? The standard Unix permissions model looks at you, shrugs, and says, “One owner, one group, and the rest. That’s all you get. Take it or leave it.”
This is, frankly, a bit pathetic. It’s like a restaurant that only lets you order from the set menu, no substitutions. The designers of the early Unix system were brilliant, but they clearly didn’t anticipate the Byzantine permission structures we’d need in a multi-user world. So, we got a patch: Access Control Lists (ACLs). ACLs are our way of saying, “Actually, I will have substitutions, and I’d like to add a side of permissions for this specific user, please.”
Think of a file’s standard permissions as the foundation of a house. ACLs are the custom-built additions on top—a new porch for one user, a skylight for a group. They give you granular control, letting you define permissions for specific users and groups beyond the limited trio of user/group/other.
The Two Key Commands: getfacl and setfacl
Your main tools for this are getfacl (to see what’s going on) and setfacl (to make changes). They’re brilliantly straightforward. Let’s say you have a directory for a project, /shared_project, and you want to let your colleague Alice read and write to it, but Bob should only be able to read.
First, let’s see what we’re working with. The getfacl command is your diagnostic tool.
getfacl /shared_project
You’ll probably see something gloriously boring:
# file: shared_project
# owner: yourusername
# group: yourgroup
user::rwx
group::r-x
other::r-x
This is just the standard permissions, translated into ACL-speak. The user:: entry refers to the file’s owner. Now, let’s get fancy and add an entry specifically for Alice.
Modifying ACLs with setfacl
The -m (modify) option for setfacl is how you add or change rules. The syntax is setfacl -m u|g:name:permissions file.
sudo setfacl -m u:alice:rwx /shared_project
sudo setfacl -m u:bob:r-x /shared_project
Boom. Done. Now run getfacl /shared_project again. The output is far more interesting.
# file: shared_project
# owner: yourusername
# group: yourgroup
user::rwx
user:alice:rwx
user:bob:r-x
group::r-x
mask::rwx
other::r-x
Look at that! We now have explicit entries for user:alice and user:bob. The system will check these rules in addition to the standard ones. When determining if Alice can access the file, it first checks the owner (you), sees that it’s not her, then finds her specific ACL entry and uses those permissions.
The Mask: The Permission Ceiling
See that mask::rwx entry? This is the ACL system’s secret police. The mask defines the maximum allowed effective permissions for all ACL entries that are not the owner or “other.” This includes named users, named groups, and the owning group. It’s a safety catch.
Let’s say some overzealous admin gives a user ridiculous permissions:
sudo setfacl -m u:intern:rwx /very_important_file
But then, a sensible admin comes along and sets a restrictive mask:
sudo setfacl -m m::r-- /very_important_file
Run getfacl now. The intern’s entry will still say rwx, but the mask is r--. The effective permissions for the intern will be r-- (a logical AND between the entry and the mask). The getfacl command is smart enough to show you the effective permissions, and it might even show the intern’s entry as # effective: r-- if you use the -s (skip) option. The mask is why you should always use getfacl to check the real permissions, not just look at the raw output of ls -l.
Default ACLs: The Gift That Keeps on Giving
Here’s where ACLs become pure magic. You can set a default ACL on a directory. Any new file or directory created inside it will automatically inherit these ACL rules. This is how you build a properly controlled shared space without having to manually fix permissions every five minutes. Use the -d flag.
sudo setfacl -d -m g:dev_team:rwX /shared_project
Notice I used a capital X instead of a lowercase x. This is a clever bit of setfacl syntax: it means “execute only if it’s a directory or if the file already has execute permission for someone.” It’s a safe way to set execute permissions recursively without accidentally making all your text files executable. You’re welcome.
Common Pitfalls and How to Avoid Them
- The Mask Will Bite You: The most common “WTF” moment is when you set an ACL, it looks right in
getfacl, but the user can’t do what they should. Check the mask first. Nine times out of ten, that’s the culprit. You can set it explicitly withsetfacl -m m::permsor just let it be recalculated automatically when you add new entries. - Backups Matter: Not all backup utilities preserve ACLs.
tar, for example, needs the--aclsflag to do it right. If you’re using ACLs in production, test your restores. Religiously. - It’s a Patch, Not a Core Feature: Because ACLs were bolted on later, some older tools can get confused.
ls -lshows a+at the end of the permission string if an ACL is present (e.g.,drwxr-xr-x+). That’s your signal that there’s more to the story than meets the eye. - Removing ACLs: To delete a specific entry, use
setfacl -x u:alice file. To nuke the entire ACL and go back to the standard, boring permissions, usesetfacl -b file. Choose wisely.
ACLs are that perfect blend of “why isn’t this the default?” and “thank the gods this exists.” They solve real-world problems that the standard model simply can’t handle. Use them. Your future self, who isn’t constantly chmod-ing everything, will thank you.