Linux File Permissions and chmod
Every file on Linux and macOS has three sets of permissions, for the owner, the file's group, and everyone else. Each set can allow read (r), write (w) and execute (x). In numbers, read is 4, write is 2 and execute is 1, and each digit of a mode is their sum. So chmod 755 gives the owner everything (4+2+1) and others read and execute (4+1), shown as rwxr-xr-x. chmod 644, or rw-r--r--, lets the owner edit and everyone else read.
Reading an ls -l line
-rwxr-xr-x 1 alice staff 2048 Oct 26 09:14 deploy.sh
│└┬┘└┬┘└┬┘ │ │
│ │ │ │ owner group
│ │ │ └── others: r-x
│ │ └───── group: r-x
│ └──────── owner: rwx
└────────── type: - file, d directory, l symlinkRead the nine characters in threes. A letter means the permission is granted, a dash means it is not. The leading character is the file type, not a permission. Paste a string like this into the Chmod Calculator to get the octal mode and a plain-language summary.
What read, write and execute mean
| Permission | On a file | On a directory |
|---|---|---|
| r (4) | View the contents | List the names inside |
| w (2) | Change the contents | Create, delete and rename entries (needs x too) |
| x (1) | Run it as a program or script | Enter it and reach files inside |
The directory column surprises people. Deleting a file depends on write permission on the directory, not on the file itself. And a directory without execute is a locked door: you may be able to list names with read, but you cannot open anything inside it. That is why directories are almost always 755, 750 or 700 while the files in them are 644, 640 or 600.
The modes you will actually use
| Mode | Symbolic | Who can do what | Use it for |
|---|---|---|---|
| 644 | rw-r--r-- | Owner edits, all read | HTML, images, most documents |
| 755 | rwxr-xr-x | Owner full, all read and run | Directories, scripts, programs |
| 600 | rw------- | Owner only | SSH private keys, .env files, tokens |
| 700 | rwx------ | Owner only | ~/.ssh, private script folders |
| 640 / 750 | rw-r----- / rwxr-x--- | Owner and group; others nothing | Config read by a service's group |
| 664 / 775 | rw-rw-r-- / rwxrwxr-x | Owner and group edit | Team-shared project folders |
| 777 | rwxrwxrwx | Anyone can change anything | Almost never |
Why chmod 777 is the wrong fix
When an app cannot write to a folder, chmod 777 makes the error go away by letting every account on the machine modify the files, including a compromised web process or another tenant. The real problem is usually ownership. Find which user the process runs as, give that user or its group ownership with chown, and use 775 or 755. For example, sudo chown -R www-data:www-data uploads/ followed by chmod 755 uploads.
Symbolic chmod: changing one bit at a time
Octal sets all permissions at once. Symbolic mode changes only what you name, which is safer when you do not know the current state:
| Command | Effect |
|---|---|
chmod u+x script.sh | Add execute for the owner |
chmod go-w file | Remove write from group and others |
chmod a+r file | Add read for all three classes |
chmod o= file | Remove every permission from others |
chmod -R u+rwX,go+rX dir | Recursive; capital X adds execute only to directories and files that already had it |
That capital X is the answer to a common mistake: chmod -R 755 on a website marks every image and HTML file executable. To set directories and files separately, use find:
find site/ -type d -exec chmod 755 {} +
find site/ -type f -exec chmod 644 {} +Setuid, setgid and the sticky bit
A fourth, leading digit holds three special flags. Setuid (4) on an executable makes it run with its owner's rights, which is how passwd updates a root-owned file. Setgid (2) on a directory makes new files inherit the directory's group, useful for shared folders (2775). Sticky (1) on a directory lets users delete only their own files, which is why /tmp is 1777. In an ls -l listing they appear as s or t in the execute position; a capital letter means the flag is set but execute is not. Setuid programs are a common target for privilege escalation, so audit any you did not expect.
Default permissions and umask
New files do not start at 777. Programs request 666 for files and 777 for directories, and the umask removes bits from that. The common umask of 022 removes write for group and others, giving 644 files and 755 directories. A umask of 077 gives 600 and 700, which suits a private server account. Run umask to see yours.
Common errors and their fixes
- “Permission denied” running ./script.sh: the execute bit is missing.
chmod u+x script.sh. - SSH “UNPROTECTED PRIVATE KEY FILE”: the key is readable by others.
chmod 600 ~/.ssh/id_ed25519andchmod 700 ~/.ssh. - Web server returns 403 Forbidden: a directory on the path lacks execute for the server's user, or a file lacks read. Check every directory from the root down.
- A cron job silently does nothing: often a script without execute permission. See cron syntax explained for other causes, and test the schedule in the Cron Expression Parser.
Permissions are one layer. ACLs (setfacl), SELinux and AppArmor policies, and mount options such as noexec can all deny access even when the mode looks right, so if a mode checks out and access still fails, look at those next.