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:
- Are you the file’s owner? If yes, the user permissions apply.
- Are you in the file’s group? If yes, the group permissions apply.
- 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,.envfiles, credential stores.700(rwx------) — owner only, executable. Right for~/.sshand 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-databut the files belong to your user. Fix withchown, not chmod. - Wrong group strategy: put collaborating users in a shared group and use
664/775with the group set. - A missing execute bit on a directory somewhere up the path —
/home/aliceitself 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
2775and 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.
/tmpis1777— 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:
644files,755directories, owned by the deploy user — the web server only needs to read. - Uploads directory:
755or tighter, owned by the web user, and mounted/configurednoexec— writable but never executable. - Private keys and secrets:
600, owner-only;~/.sshitself700. - Shared team directory:
2775with a dedicated group (the setgid bit keeps new files in the group). - Scripts:
755if others run them,700if only you do. - Never
777in 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.