HandyTools Hub

← All guides

chmod and Linux File Permissions Explained: What 755, 644, and rwx Really Mean

2026-08-11

Every developer who has deployed to a Linux server has hit it: Permission denied when running a script, a web server that can’t read its own files, or well-meaning advice to “just chmod 777 it” — which fixes the symptom while opening a security hole. File permissions are one of the oldest parts of Unix, and their model is small enough to fit in your head permanently. This guide explains that model — who the three characters apply to, why 755 means what it means, and the handful of rules that keep a multi-user system safe.

The Three Questions Every File Answers

Linux decides access by asking three questions, in order:

  1. Are you the file’s owner? If yes, the user permissions apply.
  2. Are you in the file’s group? If yes, the group permissions apply.
  3. Otherwise, the other (everyone else) permissions apply.

The first matching question wins — the checks don’t combine. If you own a file but the owner permissions say “no read,” being in a group that can read it won’t help you. This trips people up constantly: removing the owner’s access while leaving group access open effectively locks the owner out.

You can see the owner and group on any file with ls -l:

-rwxr-xr-- 1 alice developers 4096 Aug 11 09:00 deploy.sh

Here alice is the owner, developers is the group, and the leading -rwxr-xr-- is the permission string.

Reading rwxr-xr—: The Permission String

The ten characters after the file-type dash are three triplets: owner, group, other. Each triplet is read (r), write (w), execute (x) — or a dash where the permission is absent. So rwxr-xr-- decodes as:

  • Owner: rwx — read, write, execute
  • Group: r-x — read and execute, no write
  • Other: r-- — read only

Execute means different things by file type. For a regular file it’s “may be run as a program.” For a directory, x means “may enter and access files inside,” r means “may list the names inside,” and w means “may create, delete, or rename entries.” That’s why a directory you can list but not enter behaves so strangely — r without x lets you see names but touch nothing.

Octal Notation: Why 755 Is rwxr-xr-x

Each triplet is three bits, so it maps neatly onto one octal digit: read = 4, write = 2, execute = 1, summed within the triplet. rwx = 4+2+1 = 7, r-x = 4+1 = 5, r-- = 4 = 4. The classic combinations:

  • 755 (rwxr-xr-x) — owner can do everything, everyone else can read and execute. The standard for scripts, programs, and directories.
  • 644 (rw-r--r--) — owner edits, everyone reads. The standard for web content, configs, and source files.
  • 600 (rw-------) — owner only. Right for private keys, .env files, credential stores.
  • 700 (rwx------) — owner only, executable. Right for ~/.ssh and private script directories.

When the combinations stop being obvious mid-task, the chmod Calculator converts between octal and the rwx string both ways and shows exactly who gets what — much faster than counting bits in your head.

Symbolic Mode: Changing One Thing Without Recomputing Everything

Octal mode sets all nine bits at once. Symbolic mode adjusts only what you name, using who (u/g/o/a), an operator (+ add, - remove, = set exactly), and the permission letters:

chmod u+x deploy.sh      # make it executable for the owner
chmod go-w config.ini    # strip write from group and other
chmod o= secrets.txt     # remove ALL permissions from other
chmod -R u=rwX,go=rX site/   # recursive: files 644, dirs 755

That last one uses the conditional X (capital): it applies execute only to directories and files that already have some execute bit. It’s the safe way to fix a whole tree in one pass — directories become traversable, plain files stay non-executable.

Why 777 Is Almost Always Wrong

chmod 777 gives read, write, and execute to literally every account on the machine. On a shared server or container host, any compromised process — a vulnerable web app, a rogue cron job, another tenant — can now modify your files. The canonical horror story is a web-writable upload directory that’s also executable: attacker uploads a script, attacker runs the script.

The reason 777 is so tempting is that it silences Permission denied instantly. But the actual problem is almost never “everyone needs everything” — it’s one of:

  • Wrong owner: the web server runs as www-data but the files belong to your user. Fix with chown, not chmod.
  • Wrong group strategy: put collaborating users in a shared group and use 664/775 with the group set.
  • A missing execute bit on a directory somewhere up the path — /home/alice itself might be blocking traversal.

Treat 777 as a diagnostic (“does the error vanish? then it was permissions”) and never as the fix.

Special Bits: setuid, setgid, and the Sticky Bit

Three extra bits live in a fourth, leading octal digit:

  • setuid (4): an executable runs with the file owner’s privileges instead of the caller’s. This is how passwd (owned by root) lets ordinary users change their own password. Never set it on scripts you control casually.
  • setgid (2): on an executable, runs with the file’s group; on a directory, new files inherit the directory’s group instead of the creator’s primary group. That directory behavior is the backbone of shared project folders — combine with 2775 and every team member’s new files stay group-accessible.
  • sticky bit (1): on a directory, only a file’s owner can delete or rename it, even if others have write access. /tmp is 1777 — writable by all, deletable only by each file’s creator.

You’ll see them in ls -l as s, s, and t replacing the execute characters (-rwsr-xr-x, drwxrwsr-x, drwxrwxrwt).

A Server Hardening Checklist

  • Web content: 644 files, 755 directories, owned by the deploy user — the web server only needs to read.
  • Uploads directory: 755 or tighter, owned by the web user, and mounted/configured noexec — writable but never executable.
  • Private keys and secrets: 600, owner-only; ~/.ssh itself 700.
  • Shared team directory: 2775 with a dedicated group (the setgid bit keeps new files in the group).
  • Scripts: 755 if others run them, 700 if only you do.
  • Never 777 in production; if you’re tempted, find the real owner/group problem instead.

When in doubt about what a mode expands to before you run it, check it in the chmod Calculator — a five-second sanity check beats a recursive mistake on a live tree. And if the reason you’re touching permissions is protecting credentials, remember permissions are the second line of defense; strong secrets are the first — the Password Generator creates them locally.