Linux File Permissions, Explained Properly

Permissions are the most misunderstood corner of Linux — and the source of half of all server problems, from "403 Forbidden" to SSH refusing your key. This guide builds the model from scratch. Ten minutes here saves hours of cargo-cult chmod 777 later.

Reading the permission string

Run ls -l and look at the first column of any line:

-rwxr-xr--  1 diego developers  4096 Aug  4 09:41 deploy.sh

That ten-character string is four pieces. The first character is the type: - for a regular file, d for a directory, l for a symlink. The remaining nine characters are three triplets of rwx — read, write, execute — for three audiences in order: the owner (user), the group, and others (everyone else). A dash means that permission is absent.

So -rwxr-xr-- reads: regular file; owner can read, write and execute; group members can read and execute; everyone else can only read. The third and fourth columns of ls -l (diego developers) tell you who the owner and group actually are.

What r, w and x really mean

For files, the letters mean what you'd expect: read the contents, modify the contents, run it as a program. For directories they mean something subtly different, and this is where most confusion lives:

Two consequences worth engraving: a directory without x is a locked door regardless of the permissions of what's inside, and deleting a file is governed by the directory's write bit, not the file's.

The numbers: where 755 comes from

Each permission has a value: r = 4, w = 2, x = 1. Add them per triplet and you get one digit per audience:

DigitsTripletsMeaningTypical use
755rwx r-x r-xOwner: everything. Rest: read + executeDirectories, scripts, binaries
644rw- r-- r--Owner edits, everyone readsRegular files, web content
700rwx --- ---Owner onlyPrivate directories, ~/.ssh
600rw- --- ---Owner reads/writes, nobody else anythingSSH keys, credentials, .env files
777rwx rwx rwxEveryone can do everythingAlmost never the right answer

Why the pattern "755 for directories, 644 for files"? Directories need x to be enterable; regular files should not be executable unless they are actually programs. Web servers follow exactly this convention.

chmod755ownerr4w2x14+2+1 = 7groupr42x14+0+1 = 5othersr42x14+0+1 = 5r = read (4) · w = write (2) · x = execute (1)result in ls -l: rwx r-x r-x
How 755 decomposes: one octal digit per audience, each the sum of its permission bits.

chmod: changing permissions

Numeric mode sets all nine bits at once; symbolic mode adjusts specific ones:

chmod 644 index.html      # set exactly rw-r--r--
chmod +x deploy.sh        # add execute for everyone
chmod u+x deploy.sh       # add execute for the owner only
chmod g-w,o-r report.txt  # remove group write and others read
chmod -R 755 public_html/ # recursive — see the warning below
Careful with chmod -R 755 on mixed content: it makes every file executable too. The clean recipe uses find: find . -type d -exec chmod 755 + for directories and find . -type f -exec chmod 644 + for files.

chown: changing who owns things

Permissions are meaningless without knowing who the "owner" and "group" are. chown assigns them:

sudo chown www-data:www-data /var/www/html -R   # web root belongs to the web server
sudo chown diego:developers shared-report.txt

The pattern behind most "my app can't write its own files" incidents: a deployment ran as your user, so new files belong to you, while the service runs as www-data. Re-owning the tree fixes it. See the full chown guide.

The recipes you'll actually need

Practice it now

This sandbox has a backup.sh that isn't executable. Check it with ls -l, fix it with chmod 755 backup.sh, and verify the string changed:

Keep going

The chmod reference and chown reference cover every option, and the chmod lessons of the interactive course make you do this from muscle memory.