Linux file permissions and chmod, explained
“Permission denied” is one of the first errors every developer meets on a Linux server, and chmod 777 is the fix that makes it go away — while opening a security hole. Understanding the nine permission bits takes ten minutes and saves you from both.
This guide covers how permissions are represented, what the common octal modes mean, how to read ls -l output, and the special bits that trip people up. Try every example in the free chmod calculator: tick boxes or type a mode and get both chmod commands with a plain-English explanation.
Owner, group, others — and read, write, execute
Every file and directory has an owner (a user), a group, and permissions for three classes of people: the owner, members of the group, and others (everyone else). Each class gets three bits:
- r — read (4): read a file’s contents; list a directory’s entries.
- w — write (2): change a file; create, rename or delete entries in a directory.
- x — execute (1): run a file as a program; enter a directory and reach the files inside it.
The directory meanings are the ones that surprise people. Deleting a file needs write permission on the directory, not the file. And a directory with r but no x lets you see names but not open anything in it — which is why directories are almost always 755 or 700, never 644.
Octal modes: what 755, 644 and 600 mean
Add up each class’s bits to get one digit from 0 to 7, then write the three digits owner-group-others:
7 = 4+2+1 = rwx 5 = 4+1 = r-x 4 = r--
6 = 4+2 = rw- 0 = ---
- 755 (
rwxr-xr-x) — scripts, binaries and directories: everyone can run or enter, only the owner can change. - 644 (
rw-r--r--) — ordinary files: HTML, images, config that is not secret. - 600 (
rw-------) — private files: SSH private keys,.envfiles, credentials. - 700 (
rwx------) — private directories such as~/.ssh. - 775 / 664 — the group-shared versions of 755 / 644, for teams that share a group.
OpenSSH refuses a private key that others can read — the classic “UNPROTECTED PRIVATE KEY FILE” error is fixed with chmod 600 ~/.ssh/id_ed25519.
Reading ls -l output
ls -l shows the same bits as ten characters:
-rwxr-xr-x 1 deploy www-data 4096 Oct 23 10:00 deploy.sh
drwxr-x--- 2 deploy www-data 4096 Oct 23 10:00 secrets
The first character is the type (- file, d directory, l symlink), then three groups of rwx for owner, group and others. So deploy.sh is 755 and secrets is 750: the group can enter and list it, others cannot. Paste either string into the chmod calculator to get the octal value. A trailing ., + or @ marks SELinux contexts, ACLs or macOS extended attributes.
Symbolic chmod: changing one bit at a time
Octal sets all nine bits at once. Symbolic mode changes only what you name, which is safer in scripts:
chmod +x script.sh # add execute for everyone (subject to umask)
chmod u+x,go-w file # owner gains execute; group and others lose write
chmod g=rx,o= dir # group exactly r-x, others nothing
chmod -R u=rwX,go=rX site/ # capital X: execute only on directories (and already-executable files)
The capital X is the trick for fixing a whole tree: directories get x so they can be entered, ordinary files do not become executable. The common alternative is two find commands: find site -type d -exec chmod 755 {} + and find site -type f -exec chmod 644 {} +.
setuid, setgid and the sticky bit
A fourth, leading octal digit holds three special bits:
- setuid (4) — the program runs with its owner’s privileges.
/usr/bin/passwdis4755owned by root, which is how ordinary users can update the shadow password file. Shows assin the owner’s execute column. - setgid (2) — on a program, runs with the file’s group; on a directory, new files inherit the directory’s group instead of the creator’s.
2775is the standard mode for a shared project directory. - sticky (1) — on a directory, only a file’s owner can delete or rename it, even if others can write to the directory. That is why
/tmpis1777and shows atat the end.
A capital S or T in ls -l means the special bit is set but the execute bit underneath is not — usually a mistake.
Why chmod 777 is almost always wrong
777 gives every account on the machine — including a compromised web process — permission to modify or replace the file. On a web server that means an uploaded script can overwrite your code. The real problem behind “permission denied” is nearly always ownership, not mode:
# the web server (www-data) needs to write uploads
sudo chown -R deploy:www-data uploads/
sudo chmod -R 2775 uploads/ # group-writable, new files keep the group
Also check your umask: it is subtracted from the default 666 (files) and 777 (directories) when files are created, so a umask of 022 yields 644 and 755. Working with servers, containers or deploy scripts? The IP subnet calculator and cron expression builder cover the next two things you will need.
Work out any chmod mode — free visual calculatorFrequently asked questions
What does chmod 755 mean?
The owner can read, write and execute (7); the group and everyone else can read and execute (5 and 5). It is the normal mode for scripts, programs and directories.
What is the difference between chmod 644 and 755?
644 (rw-r--r--) has no execute permission and suits regular files. 755 (rwxr-xr-x) adds execute, which programs need to run and directories need to be entered.
What permissions should an SSH key have?
The private key must be 600 and the ~/.ssh directory 700. Public keys and authorized_keys can be 644. OpenSSH refuses private keys that other users can read.
How do I calculate chmod permissions online?
Use the free chmod calculator at code.doaide.com/tools/chmod-calculator: tick read, write and execute for owner, group and others, or type a mode like 755 or rwxr-xr-x, and copy the octal or symbolic chmod command.
More guides
- How to review code with AI, free and without sign-up
- How to convert code between languages with AI (Python, Java, JavaScript and more)
- How to generate unit tests with AI: from zero tests to a real suite
- The best free code review tools in 2026
- AI code tools for beginners: learn faster without learning less
- 10 free AI code tools every developer needs in 2026
- DoAide Code: the free alternative to GitHub Copilot
- How to review code with AI for free: workflows that stick
- How to write clean code in 2026
- Best practices for code documentation
- The best free online code formatter in 2026
- Online regex tester and builder: write regular expressions that actually work
- Free online SQL formatter and validator
- Code snippet sharing for developers: stop pasting code into chat
- How to generate a JSON Schema from a JSON sample
- The flexbox cheat sheet: every property and what it actually moves
- Meta tags for SEO: what your pages actually need in 2026
- UUID v4 vs v7: which one should you use?
- CSS Grid explained: tracks, fr, minmax and template areas
- How to mock a REST API for frontend development
- CSP, CORS and security headers, explained
- YAML, JSON, CSV and XML: converting data and config files safely