File permissions in Linux are always a bit of a hassle to manage. One of the first questions a new user has is usually something like “why am I getting this permission denied error?”
That is when some helpful soul tells them all the wonders of the chmod command. But the chmod command is quite limited in that it can only set permissions for three groups of users: the files owner, the owning group and others. Others includes every user that isn’t in the group. That can be a lot of users in some cases. What if you just want to also give access to one user that isn’t in the group?
That is where file access lists (ACL) can be extremely helpful.
In this blog post I’ll share with you what file access lists in Linux are and how you can use them. You will see how the offer more options and flexibility. You will learn how to use the two main commands for ACLs: setfacl and getfacl. So let’s get started and see if we can’t learn something new.
How to use getfacl
To query the ACL of a file you will need to use the command getfacl. This command will print out the access list for the file or folder you pass to it.
Let’s create an empty file and query it:
linuxdigest@linuxdigest:~$ ls -l total 0 -rw-rw-r-- 1 linuxdigest linuxdigest 0 Mar 26 20:53 textfile.txt
We now have an empty file that has read and write permissions for the owner and group. Other users have only read permissions. This is what we get if we call getfacl:
linuxdigest@linuxdigest:~$ getfacl textfile.txt # file: textfile.txt # owner: linuxdigest # group: linuxdigest user::rw- group::rw- other::r--
As you can see, the file already has some entries in the access list. Namely the permissions it was given by default. Note: the default values can vary by system based on the user’s umask value.
How to use setfacl
Now that we know how to query the ACLs, we can go ahead and try to add our own. The setfacl command is our tool for this.
Imagine that we want the user Alice to be able to read our file and Bob should be able to read and write to the file.
linuxdigest@linuxdigest:~$ setfacl -m u:alice:r textfile.txt linuxdigest@linuxdigest:~$ setfacl -m u:bob:rw textfile.txt
The “-m” argument tells setfacl that we want to assign permissions to the file and the “u” before the username says the permissions are assigned to a user.
Similarly, we can assign read permissions for a whole group as well. This time we will assign read permissions to the accountants group. The command is the same except that the “u” is changed to “g”:
linuxdigest@linuxdigest:~$ setfacl -m g:accountants:r textfile.txt
Let’s fetch the ACLs of our file and see what has changed:
linuxdigest@linuxdigest:~$ getfacl textfile.txt # file: textfile.txt # owner: linuxdigest # group: linuxdigest user::rw- user:alice:r-- user:bob:rw- group::rw- group:accountants:r-- mask::rw- other::r--
Our access list is now much longer than it was in the beginning. It is quite obvious that this is much more powerful than using the chmod command.
Remove an entry from an access list
Bob has changed jobs now, so there is no reason for him to have access to the file. As a good system administrator I will have to revoke his access. This can be done with the “-x” argument. This will remove the whole entry. Notice that we don’t specify what permissions we are removing, since the “-x” argument removes the entry completely
linuxdigest@linuxdigest:~$ setfacl -x u:bob textfile.txt
How to tell if a file has an access list
Obviously, you can always use getfacl to see what access list entries a file has. But that isn’t always practical and you may have forgotten that you have created any access lists.
Luckily the “ls” command will let you know that there is more information than the file permissions are displaying. If a file has an ACL other than the standard permissions a “+” sign will be appended to the permissions.
linuxdigest@linuxdigest:~$ ls -l total 0 -rw-rw-r--+ 1 linuxdigest linuxdigest 0 Mar 26 20:53 textfile.txt
As you can see, the permissions are displayed as -rw-rw-r–+. Letting us know if the file has an extended access list.
Reset a file access list to defaults
Now that we have practiced our access list skills a bit, we might want to remove the access list and just use regular file permissions.
The “-b” option tells setfacl to remove all extended access list entries. The default entries for the user, group, and others will be retained. The file’s permissions will be just as they were when we originally created it:
linuxdigest@linuxdigest:~$ setfacl -b textfile.txt linuxdigest@linuxdigest:~$ getfacl textfile.txt # file: textfile.txt # owner: linuxdigest # group: linuxdigest user::rw- group::rw- other::r--
Set a default entry for a directory
Let’s imagine a scenario where we have multiple users on a server and we want to have our web server serve web pages from the user’s home directory. For this to be possible, the user that runs the web server must be able to read the directory and the files in it.
The “-d” argument allows us to create an access list entry on a directory and have all files, in the directory, inherit that entry. Even if the file hasn’t been created yet.
Let’s try it and create a directory named www in our home directory and let the www-data user read and write to it:
linuxdigest@linuxdigest:~$ rm -rf htdocs linuxdigest@linuxdigest:~$ mkdir www linuxdigest@linuxdigest:~$ setfacl -dm u:www-data:rw www
Let’s go ahead and try creating a file and see the access list for it:
linuxdigest@linuxdigest:~$ touch www/index.html linuxdigest@linuxdigest:~$ getfacl www/index.html # file: www/index.html # owner: linuxdigest # group: linuxdigest user::rw- user:www-data:rw- group::rwx #effective:rw- mask::rw- other::r--
How convenient! The www-data user has full read and write access to the file. So it should be able to fetch the file when needed.
That’s it for now
I hope you have a basic understanding of Linux ACLs now. I encourage you to create some files and test these commands as I have in the examples above. You never know when this skill will come in handy.