Free — no signup required

Access Control Lists (ACLs): Beyond Basic Permissions

3 min read

When User/Group/Others Isn't Enough

The traditional Unix permission model has a fundamental limitation: you can only define permissions for one user (the owner), one group, and everyone else. What if you need to give specific access to multiple users or groups?

Example scenario: You have a file owned by alice:developers, but you also need to give read access to user bob (who is not in the developers group) and write access to the ops group.

Traditional permissions can't express this. You'd have to either:
1. Add bob to the developers group (but then he'd have access to all developers' files)
2. Make the file world-readable (but then everyone can read it)

Neither is ideal. This is where Access Control Lists (ACLs) come in.

What are ACLs?

ACLs extend the basic permission model by allowing you to define permissions for multiple named users and groups on the same file. Think of it as a fine-grained permission table attached to each file. Most modern Linux filesystems (ext4, XFS, Btrfs) support ACLs by default; the tooling to manage them (the acl package, providing the getfacl and setfacl commands) is a common addition on distributions that don't ship it out of the box.

Reading and writing ACLs: getfacl prints a file's complete ACL — the standard owner/group/other entries plus any named-user and named-group entries layered on top, such as a specific bob getting read access or the ops group getting read-write, alongside the file's regular owner and group permissions. setfacl is the mirror command: it grants a named user or group a permission, removes a specific named entry, or wipes all extended entries back to plain Unix permissions. A + at the end of the permission string in ls -l output (e.g. -rw-r--r--+) is the only visual hint that a file carries ACL entries — you have to run getfacl to see what they actually are.

The ACL mask: the mask entry in getfacl output defines the maximum effective permission for any named user or group entry — it does not constrain the owner or other. If the mask is r--, a named entry granting rw- is capped down to read-only in practice, and getfacl flags this with an #effective: comment next to the entry. The mask recalculates automatically whenever you add a new ACL entry, but it can also be set directly. This has a sharp production edge: running a plain chmod on a file's group bits when that file has ACLs actually changes the mask, which can silently reduce the effective permissions of every named ACL entry on it.

Default ACLs for directories: a default ACL set on a directory is inherited by every file and subdirectory created inside it afterward — the ACL equivalent of SGID, but for arbitrary named users and groups rather than just the group owner. This is how an access pattern is made to "stick" for an entire shared directory going forward, instead of requiring setfacl to be reapplied to every new file by hand.

Key Point: ACLs are powerful but add complexity. Use them when the standard user/group/others model genuinely can't express your access requirements. In practice, ACLs are most useful in NFS-mounted shared filesystems, CI/CD systems where multiple service accounts need different access levels, and compliance environments where fine-grained audit trails are required. Always document ACL usage in your infrastructure runbooks—they're invisible to ls -l (only the + hints at their presence) and can cause confusing permission behavior if not tracked.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free