List of Articles Icon

Knowledge Base

Guides and answers for your VPS, the client area, and billing

How do Linux file permissions work? (And what are attributes?)

What this is

The permission model behind every Permission denied, every 403, and every "why can't the web server read my upload". It's a small, consistent system, ten minutes here and ls -l output becomes legible forever.

The model: three actions, three audiences

Every file and directory carries permissions for three actions, read (r), write (w), execute (x), granted separately to three audiences: the owner (one user), the group (one group of users), and others (everyone else). It also carries exactly one owner and one group, that's the whole state.

Reading ls -l:

-rw-r--r-- 1 www-data www-data  4096 Jul  2 10:00 index.php
drwxr-xr-x 2 deploy   deploy    4096 Jul  2 10:00 uploads

First character: type (- file, d directory, l symlink). Then three triplets, owner/group/others: rw- r-- r-- means the owner reads and writes, everyone else reads. Then the owner and group names.

What r, w, x mean, files vs directories

  • On a file: read the contents / change the contents / run it as a program.
  • On a directory, the part that trips everyone: r = list the names inside, w = create/delete/rename entries inside, and x = traverse, enter it, or reach anything through it. A file you can read inside a directory you can't traverse is unreachable, which is why a 700 home directory above a web root produces 403s with perfect file permissions.

Octal notation, decoded once

Each triplet is a number: r=4, w=2, x=1, summed. So:

  • 644 = rw-r--r--, the standard file: owner edits, world reads.
  • 755 = rwxr-xr-x, the standard directory (and executable): owner full, world can enter/read.
  • 600/700, private file/directory, what .env files and ~/.ssh want.
  • 777 = everyone can do everything, the "fix" that's always wrong: on a server it means any compromised process can rewrite your code.

Changing things: chmod, chown, chgrp

chmod 644 file.php                 # set exact permissions (octal)
chmod u+x deploy.sh                # symbolic: add execute for the owner
chmod -R g+w /var/www/shared       # recursive, careful with -R and x!
chown www-data:www-data -R /var/www/site    # owner and group together

One recursion trap: chmod -R 644 strips the x from directories and breaks traversal. The idiom that sets files and directories correctly in one pass is in the 403 guide (find -type d → 755, find -type f → 644).

The special bits: setuid, setgid, sticky

A fourth, leading octal digit covers three special cases you'll mostly read rather than set:

  • setuid (4xxx, s in the owner triplet): the program runs as its owner regardless of who launches it, how passwd edits a root-owned file. On your own files, almost never; a stray setuid-root binary is a compromise artifact worth noticing.
  • setgid (2xxx): on a directory, new files inherit the directory's group instead of the creator's, genuinely useful for shared web roots (chmod g+s /var/www/shared).
  • sticky (1xxx, t on the end): in a world-writable directory, only a file's owner may delete it, why /tmp is 1777 and everyone's temp files survive each other.

umask: where default permissions come from

New files don't appear as 666/777, the umask subtracts bits at creation. The usual 022 yields 644 files and 755 directories, which is why fresh files are usually right without thought. If a service creates files your web server can't read, its umask (settable per systemd unit with UMask=) is the suspect.

Attributes: the layer beneath permissions

Separate from permissions, ext4 supports file attributes, flags on the file itself, managed with chattr and listed with lsattr. The two that matter in practice:

  • i (immutable): chattr +i file, the file can't be modified, deleted, or renamed by anyone, root included, until chattr -i. Legitimate for lock-down-this-config; also a known malware persistence trick, when a file refuses deletion as root, lsattr it.
  • a (append-only): writes can only add, never rewrite, occasionally used to protect logs.

If a permission mystery survives everything above, check lsattr before questioning reality.

A note on ACLs

When one-owner-one-group isn't expressive enough ("these two users, plus the web server, but nobody else"), POSIX ACLs add per-user/per-group entries on top: setfacl -m u:deploy:rw file, inspect with getfacl, and a + at the end of ls -l's permission block is the tell that ACLs are in play. Most single-admin servers never need them; knowing the + exists prevents one specific afternoon of confusion.

Still need help?

You can open a support ticket. So we can help on the first reply, it's worth mentioning:

  • the VPS hostname or IP,
  • the ls -l line for the file or folder, and who needs which access.
  • "What do 644, 755, and 777 actually mean?"
  • "Why does execute on a directory matter?"
  • "What are setuid, setgid, and the sticky bit?"
  • "Why can't root delete this file (chattr immutable)?"
  • "What does the + at the end of ls -l permissions mean?"
Last reviewed: 2026-07-02