linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Simulator
  • Knowledge base
  • Interview prep
Index
Categories
All entries
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
home/linux/kb/File system/posix-acl

kb/filesystem ── File system ── intermediate

POSIX ACL: extended access permissions

POSIX ACL extends the classic rwx permissions: you can grant access to many users and groups without reshuffling the owner and group. setfacl writes, getfacl reads. A default ACL on a directory is inherited by its children.

view as markdownaka: acl, posix-acl, getfacl, setfacl, default-acl

Why ACL

Classic [[file-permissions|rwx]] lets you set rights for one owner, one group, and everyone else. When you need "Alice read+write, Bob read, everyone else nothing," three sets are not enough.

Your options:

  • Create a new group with Alice and Bob, but Bob needs read only; a single group cannot express that
  • Use setgid plus a shared group, which still gives everyone in the group the same rights
  • POSIX ACL, which grants rights to individual users or groups one at a time

ACL is an extension of rwx, not a replacement. The base owner/group/other stay; ACL is added on top.

Where it works

Supported on ext4, xfs, btrfs, tmpfs (with RAM on kernel 6 and later), and zfs. It does not work on FAT/NTFS or on old vfat. Mount with acl (often the default on ext); on xfs it is on by default.

Check it:

bash
mount | grep ' / '            # look for acl in the options (or just the absence of noacl)
tune2fs -l /dev/sda1 | grep -i acl

getfacl: reading

bash
$ getfacl /home/shared/report.pdf
# file: home/shared/report.pdf
# owner: alice
# group: team
user::rw-
user:bob:r--
group::r--
group:auditors:r--
mask::r--
other::---

Reading the output:

  • user::rw- is the owner's rights (alice)
  • user:bob:r-- is a named user; the "r" bit
  • group::r-- is the group's rights (team)
  • group:auditors:r-- is a named group
  • mask::r-- is the upper bound for every ACL entry except owner and other
  • other::--- is everyone else

If ls -l shows a + after the permissions:

-rw-r--r--+ 1 alice team 12K May  2 14:00 report.pdf

that means "the file has an ACL."

setfacl: writing

Basic syntax:

bash
setfacl -m u:bob:r-- file
setfacl -m u:bob:rwx,g:auditors:rx file
setfacl -m u:bob:- file              # explicitly "nothing"
setfacl -x u:bob file                # remove the ACL for bob
setfacl -b file                       # clear all ACL (keep the base rwx)
setfacl --restore=acl-backup.txt      # from a backup

Options:

OptionWhat it does
-mmodify: add or change
-xremove specific entries
-bclear all
-kremove the default ACL
-Rrecursive
-dwork with the default ACL (not the effective one)

Who the entry targets

PrefixWho
u:NAMEa specific user
g:NAMEa specific group
m::mask
o::other
u::owner (same as chmod u)
g::owning group

Mask: the upper bound

The mask limits the effective rights for every named user/group and for the owning group:

user::rw-
user:bob:rwx        ← declared rwx
group::rwx
mask::r--           ← but the mask is r only
other::r--

Bob effectively has only r--. ls shows effective:r-- to the right of the entry. This is a feature, not a bug: run chmod g-w and guarantee that no ACL can grant write.

setfacl recomputes the mask automatically:

bash
setfacl -m u:bob:rwx file        # the mask becomes rwx
setfacl -n -m u:bob:rwx file     # -n: do NOT recompute the mask

Default ACL: inheritance

Only on directories. A default ACL applies to new files and subdirectories created inside it:

bash
setfacl -d -m u:bob:rx /home/shared
setfacl -d -m g:team:rwx /home/shared

Now any new file in /home/shared is created with these ACL plus the usual uid/gid logic. Existing files are not touched.

This is the main use case for ACL in production: a shared folder for a team, so you do not have to fight umask, setgid, and chown every time.

To copy the default into the effective ACL for all existing files:

bash
getfacl --default /home/shared > acl.tpl
setfacl --set-file=acl.tpl -R /home/shared

Full example: a shared team folder

bash
# Create it
sudo mkdir /srv/team-share
sudo chgrp team /srv/team-share
sudo chmod g+s /srv/team-share          # setgid: inherit the group
# Default ACL: the team gets rwx, auditors get r only
sudo setfacl -d -m g:team:rwx /srv/team-share
sudo setfacl -d -m g:auditors:rx /srv/team-share
sudo setfacl -d -m o::- /srv/team-share
# Bring the existing files in line too
sudo setfacl -R -m g:team:rwx,g:auditors:rx,o::- /srv/team-share

Now any member of team can write to any file, any auditor can read, and "other" sees nothing.

ACL and cp / tar / rsync

Not every tool carries ACL by default:

  • cp preserves ACL with -p (preserve mode includes ACL)
  • tar needs --acls (on older GNU tar, --acls is supported from 1.27)
  • rsync needs -A (--acls); it adds to the standard -a
  • find ... -exec cp: remember -p

Backups:

bash
getfacl -R /srv/team-share > acl-backup.txt
# ...
setfacl --restore=acl-backup.txt

ACL vs SELinux/AppArmor

ACL is DAC (Discretionary Access Control): the owner decides. SELinux/AppArmor is MAC: a system policy layered on top. They do not replace each other. If SELinux denied something, ACL will not help; if ACL denied it, SELinux will not give it back.

More in selinux-apparmor and capabilities.

When something goes wrong

  • setfacl: Operation not supported: mounted without acl (old ext mount), or the filesystem does not support it (vfat, NFSv3 without acl).
  • chmod "ate" the ACL: old semantics, where chmod g+w changed the mask and the ACL along with the group bit. On newer kernels chmod usually touches only the classic bits, but the mask can be recomputed. Smarter: setfacl -m m::rwx.
  • Default ACL is not inherited over NFS: old NFS clients do not support ACL. NFSv4 ACL (a different standard!) is a separate story.
  • tar lost the ACL: there was no --acls. Use bsdtar (libarchive) or --acls --xattrs.
  • You see + but getfacl is empty: this happens with a corrupted ACL blob; run setfacl -b and start over.

Alternatives

  • NFSv4 ACL: a different standard, closer to Windows/Solaris
  • Richacl: deprecated, never merged into mainline
  • xattr directly through [[extended-attributes|setfattr]]: ACL is stored exactly as the xattr system.posix_acl_*

§ команды

bash
getfacl /srv/team-share

Show the directory's ACL: the first thing to look at

bash
setfacl -m u:bob:rx,g:auditors:r-- file.txt

Assign rights to a named user/group: the typical setfacl

bash
setfacl -d -m g:team:rwx /srv/team-share

Default ACL on a directory: inherited by new files

bash
setfacl -bR /srv/team-share

Clear all ACL recursively: back to clean rwx

bash
getfacl -R /srv/team-share > acl-backup.txt

Back up the ACL of the whole subtree: before a migration

bash
rsync -aA --acls /src/ /dst/

rsync that carries ACL: without -A they are lost

bash
ls -l file.txt | grep '+$'

A file with an ACL: the plus sign after rwx in the permissions

§ см. также

  • file-permissionsFile permissions: rwx and chmodEvery file has three permission sets: for the owner, the group, and others. Each set is three bits: read (r), write (w), execute (x). You change them with `chmod`.
  • extended-attributesExtended attributes (xattr): arbitrary file metadataxattr are key-value metadata on an inode beyond stat. 4 namespaces: user (open), trusted (root), system (ACL), security (SELinux, capabilities). getfattr reads, setfattr writes.
  • inodeInodeAn inode is a filesystem record that holds metadata and pointers to a file's data blocks. The filename lives separately, in a directory, and simply points to the inode.
  • fhsFilesystem Hierarchy Standard (FHS)FHS is the standard for what lives in which Linux root directory: /etc holds config, /var holds changing data, /usr holds the distro's static files, /home holds users, /tmp holds temporary files.
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies