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 symlink

Read 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

PermissionOn a fileOn a directory
r (4)View the contentsList the names inside
w (2)Change the contentsCreate, delete and rename entries (needs x too)
x (1)Run it as a program or scriptEnter 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

ModeSymbolicWho can do whatUse it for
644rw-r--r--Owner edits, all readHTML, images, most documents
755rwxr-xr-xOwner full, all read and runDirectories, scripts, programs
600rw-------Owner onlySSH private keys, .env files, tokens
700rwx------Owner only~/.ssh, private script folders
640 / 750rw-r----- / rwxr-x---Owner and group; others nothingConfig read by a service's group
664 / 775rw-rw-r-- / rwxrwxr-xOwner and group editTeam-shared project folders
777rwxrwxrwxAnyone can change anythingAlmost 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:

CommandEffect
chmod u+x script.shAdd execute for the owner
chmod go-w fileRemove write from group and others
chmod a+r fileAdd read for all three classes
chmod o= fileRemove every permission from others
chmod -R u+rwX,go+rX dirRecursive; 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_ed25519 and chmod 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.

Sources and further reading