Most "Permission denied" errors on a Linux server come down to three letters and three groups of people. Once you can read them, you can fix web roots, SSH keys and scripts with confidence instead of guessing. This guide explains how Linux permissions work and which values are safe for common files.
Before you start
- A Linux VPS with any supported distribution: Ubuntu 22.04 or 24.04, Debian 12, or AlmaLinux or Rocky Linux 8 or 9. Permissions work the same on all of them.
- An SSH session. You can try every read-only command here as a normal user.
Read the output of ls -l
List a folder with details:
ls -l /var/wwwdrwxr-xr-x 3 www-data www-data 4096 Nov 9 09:14 example.com
-rw-r--r-- 1 root root 612 Nov 2 11:30 index.htmlTake the first line apart:
d: the type.dis a directory,-a regular file,la symbolic link.rwxr-xr-x: the permissions, in three sets of three.www-data www-data: the owner (a user) and the group.- The rest is the size, date and name.
The nine permission characters split into three sets:
rwx r-x r-x
owner group othersA letter means the permission is granted. A dash means it is not.
Owner, group and others
Linux checks who you are in a fixed order and uses the first set that matches:
- If you are the file's owner, the owner set applies.
- Otherwise, if you are a member of the file's group, the group set applies.
- Otherwise, the others set applies.
Only one set is used. If a file is ---rwxrwx and you are the owner, you cannot read it, even though everyone else can. Root ignores most of these checks, which is why working as root hides permission problems.
What r, w and x mean
The letters mean different things for files and for directories.
On a file
r(read): view the contents, for example withcat.w(write): change the contents.x(execute): run it as a program or script.
On a directory
r(read): list the names inside it withls.w(write): create, delete and rename entries in it. This is what allows deleting a file, not the file's ownwbit.x(execute, often called search): enter the directory withcdand reach files inside it.
A web server needs x on every folder in the path to a file, plus r on the file itself. A single folder without x breaks the whole path.
Numeric (octal) permissions
Each letter has a value: r = 4, w = 2, x = 1. Add them for each set:
rwx= 4 + 2 + 1 = 7rw-= 4 + 2 = 6r-x= 4 + 1 = 5r--= 4---= 0
Three digits give owner, group and others. So rwxr-xr-x is 755 and rw-r--r-- is 644.
stat shows both forms at once:
stat -c '%A %a %U:%G %n' /etc/passwd-rw-r--r-- 644 root:root /etc/passwdCommon safe values
- 644 (
rw-r--r--): normal files, such as web pages, images and most configs. - 755 (
rwxr-xr-x): directories, and scripts or programs everyone may run. - 600 (
rw-------): private files only the owner should see, such as SSH private keys,.envfiles andauthorized_keys. - 700 (
rwx------): private directories, such as~/.ssh. - 640 (
rw-r-----): config files with secrets that a service group must read, for example a database password file readable by the web server group. - 750 (
rwxr-x---): app folders that only the owner and one group may enter.
Warning: Avoid 777. It lets any user or process on the server change or replace the file, which is exactly what malware looks for. Fix the owner or group instead.
Special bits in brief
You may see an s or t in place of an x:
- setuid (
sin the owner set): a program runs with the owner's rights./usr/bin/passwduses it. - setgid (
sin the group set): on a directory, new files inherit the directory's group. Useful for shared folders. - sticky bit (
tin the others set): on a directory, users can delete only their own files./tmpuses it.
Check it works
Test how permissions behave with a throwaway file:
echo "hello" > test.txt
chmod 600 test.txt
ls -l test.txt
sudo -u nobody cat test.txtls -l shows -rw-------, and the last command fails with Permission denied, because nobody falls into "others", which has no rights. Run chmod 644 test.txt and try again; now it works. Delete the file with rm test.txt when you are done.
Troubleshooting
- "Permission denied" though the file is 644: a folder in the path is missing
xfor you. Check every level withnamei -l /path/to/file. - You can see a file in
lsbut not open it: the directory gives your, but the file does not. Check the file's own permissions and owner. - SSH ignores your key:
~/.sshorauthorized_keysis too open. Set them to 700 and 600. - A script will not run: it is missing
x. Add it withchmod +x script.sh, as covered in Fix a script "Permission denied" error.
Next steps
- Change permissions with confidence: chmod: change file permissions in Linux.
- Change who owns a file: chown: change file owner and group.
- Track down a specific error: Fix "Permission denied" on Linux.
