Linux VPS

Fine-grained permissions with ACLs (setfacl and getfacl)

Give extra users or groups access to a file or folder without changing its owner, using POSIX ACLs with setfacl and getfacl, including default ACLs for new files.

AdvancedLinux server4 min read

Standard Linux permissions allow one owner, one group and everyone else. Sometimes that is not enough: a deploy user needs write access to a folder owned by the web server, and a backup user needs read access to everything. Access control lists (ACLs) add extra entries for named users and groups. This guide shows how to read, set, inherit and remove ACLs.

Before you start

  • A Linux VPS with Ubuntu 22.04 or 24.04, Debian 12, or AlmaLinux or Rocky Linux 8 or 9.
  • Root or sudo access over SSH.
  • Comfort with normal permissions. If needed, read Linux file permissions explained first.

Install the tools and check filesystem support

The setfacl and getfacl commands come from the acl package. AlmaLinux and Rocky install it by default. On Ubuntu and Debian, install it if it is missing:

Bash
sudo apt update && sudo apt install acl

On AlmaLinux or Rocky:

Bash
sudo dnf install acl

ext4 and XFS, the usual filesystems on these systems, support ACLs out of the box, with no extra mount option. Check the filesystem type of a path with:

Bash
df -T /var/www

Read ACLs with getfacl

Bash
getfacl --omit-header /var/www/example.com

Without --omit-header, the output also starts with three comment lines naming the file, owner and group.

user::rwx
group::r-x
other::r-x

With no ACL set, the output just mirrors the normal permissions. A + at the end of the mode in ls -l, such as drwxr-xr-x+, tells you a file has extra ACL entries.

Grant access to a user or group

Give the user deploy read and write access to one file:

Bash
sudo setfacl -m u:deploy:rw /var/www/example.com/config.php

Give the group developers full access to a folder:

Bash
sudo setfacl -m g:developers:rwx /var/www/example.com
  • -m modifies (adds or changes) entries.
  • u:name:perms targets a user and g:name:perms a group.
  • Permissions use the familiar r, w and x letters.

Apply to a whole tree with -R. Use capital X so only folders get execute:

Bash
sudo setfacl -R -m u:deploy:rwX /var/www/example.com

Set default ACLs for new files

An ACL on a folder does not apply to files created later. For that you need a default ACL, which new files and folders inherit:

Bash
sudo setfacl -R -m d:u:deploy:rwX /var/www/example.com

The d: prefix marks a default entry. Usually you set both: a normal entry for what exists now and a default entry for what comes later:

Bash
sudo setfacl -R -m u:deploy:rwX,d:u:deploy:rwX /var/www/example.com

Now any file the web server creates in this tree is also writable by deploy.

Understand the mask

When ACL entries exist, the group bits shown by ls -l become the mask. The mask caps what named users and groups can actually do. getfacl shows it, and marks entries the mask reduces with #effective::

user:deploy:rwx                 #effective:r-x
mask::r-x

Here deploy has rwx on paper but only r-x in practice. A chmod g-w on the file lowers the mask and silently removes write access from every ACL entry. Reset it with:

Bash
sudo setfacl -m m::rwx /var/www/example.com

Remove ACLs

Remove one entry:

Bash
sudo setfacl -x u:deploy /var/www/example.com/config.php

Remove default entries from a folder:

Bash
sudo setfacl -k /var/www/example.com

Remove every ACL entry and go back to plain permissions:

Bash
sudo setfacl -R -b /var/www/example.com

Back up and restore ACLs

getfacl output can be saved and replayed, which helps before large changes:

Bash
getfacl -R /var/www/example.com > /root/example-acl.txt
sudo setfacl --restore=/root/example-acl.txt

Run the restore from /, because getfacl stores relative paths. Note that cp and many backup tools do not copy ACLs unless asked: use cp -a, rsync -A or tar --acls.

When ACLs beat groups

Use groups first. They are simpler and visible in ls -l. Reach for ACLs when:

  • One extra user needs access, but you cannot change the owner or group, for example a folder owned by www-data.
  • Different users need different rights on the same folder.
  • New files must stay accessible no matter which program creates them.

Check it works

Confirm the entry and its effective rights with getfacl, then test as the user:

Bash
getfacl /var/www/example.com | grep deploy
sudo -u deploy touch /var/www/example.com/acl-test && echo OK
sudo rm /var/www/example.com/acl-test

OK means deploy can write in the folder.

Troubleshooting

  • "setfacl: command not found": install the acl package as shown above.
  • "Operation not supported": the filesystem or mount does not support ACLs. Check it with df -T and findmnt.
  • ACL is set but access is denied: the mask is too strict, or a parent folder lacks x for the user. Check #effective: in getfacl, and walk the path with namei -l.
  • New files lack the ACL: you set only access entries. Add default entries with d:.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.