Linux File Permissions Explained: chmod 755, 644 & 777
Linux file permissions decide who can read, write, or run every file and folder on the system. Each item has three classes of user (the owner, a group, and everyone else), and each class gets three permission bits: read (r), write (w), and execute (x). That is nine bits per file. chmod sets them, and the shorthand you see everywhere is octal: each class’s rwx collapses into a single digit from 0 to 7 (read 4 + write 2 + execute 1).
Three modes cover almost everything you will ever type:
- 755 (
rwxr-xr-x) — directories and scripts: the owner can change them, everyone else can read and run them. - 644 (
rw-r--r--) — ordinary files: the owner writes, everyone else reads. - 777 (
rwxrwxrwx) — full access for everyone. Almost always wrong; it is a security hole, not a fix.
Toggle any combination in the free chmod calculator and watch the octal, the rwx string, and the exact command update together. The rest of this guide explains how those numbers work and where each one belongs.
Linux File Permissions in 30 Seconds
| Octal | Symbolic | Typical use |
|---|---|---|
| 400 | r-------- | SSH private key, read-only |
| 600 | rw------- | Private files, SSH keys, .env |
| 644 | rw-r--r-- | Web pages, config, most files |
| 700 | rwx------ | Private directories (~/.ssh) |
| 755 | rwxr-xr-x | Scripts, binaries, web directories |
| 775 | rwxrwxr-x | Group-shared directories |
| 777 | rwxrwxrwx | Everyone, everything — avoid |
| 1777 | rwxrwxrwt | Shared temp dirs like /tmp |
Rule of thumb: 644 for files, 755 for directories, and tighten from there. Loosen a mode only when something concrete breaks, never preemptively.
The Permission Model: Owner, Group, Others
Three classes share one file. The owner (usually whoever created it), a single group, and others, meaning every account that is neither the owner nor a member of the group. Each class independently gets read, write, and execute:
- read (r) — view a file’s contents, or list a directory’s entries.
- write (w) — change a file, or add and remove entries in a directory.
- execute (x) — run a file as a program, or enter (
cdinto) a directory.
The twist that trips people up: on a directory, the bits mean something different. r lets you list names, w lets you create and delete entries inside, and x lets you traverse, reaching the files below so you can cd in. You can hold r without x on a directory, run ls on it, and still get “Permission denied” the moment you try to enter. That is exactly why directories are 755, not 644.
Reading an ls -l line
Run ls -l and every entry begins with a ten-character block:
$ ls -l
-rw-r--r-- 1 jack staff 1400 Jul 17 10:00 index.html
drwxr-xr-x 5 jack staff 160 Jul 17 10:00 assets
Read it left to right. The first character is the file type, not a permission: - is a regular file, d a directory, l a symlink, c or b a device, p a named pipe, s a socket. The next nine characters are three groups of rwx: owner, group, others. So -rw-r--r-- is a regular file where the owner reads and writes (rw-) while group and others only read (r-- r--), which is 644. drwxr-xr-x is a directory at 755.
Some systems append a marker after the nine bits. A trailing . signals an SELinux context, a + means an ACL adds rules beyond the basic bits, and on macOS an @ marks extended attributes. None of them change the octal. Ignore the marker and read the nine characters.
Octal Notation: How 755 Becomes rwxr-xr-x
Octal file permissions work because each permission is a power of two:
- read = 4
- write = 2
- execute = 1
Add up the bits a class holds and you get its digit. rwx is 4 + 2 + 1 = 7. r-x is 4 + 1 = 5. r-- is 4. So rwxr-xr-x reads, in threes, as 7 5 5. Do the same for rw-r--r-- and you get 4 + 2, 4, 4 → 644. That is the whole trick; there is nothing more to octal permissions than three independent sums.
Permission digits 0–7 at a glance
| Digit | Binary | Permissions |
|---|---|---|
| 0 | 000 | No permissions |
| 1 | 001 | Execute only |
| 2 | 010 | Write only |
| 3 | 011 | Write + execute |
| 4 | 100 | Read only |
| 5 | 101 | Read + execute |
| 6 | 110 | Read + write |
| 7 | 111 | Read + write + execute |
Octal is simply base 8, so each digit packs three bits with no overlap into the next class. If the positional arithmetic feels rusty, the number base converter shows how base 8 maps onto binary the same way each permission digit does.
chmod 755 vs 644 vs 777: The Modes You’ll Actually Type
755, 644, and 777 side by side:
| Octal | Symbolic | Owner | Group | Others | Typical use | Risk |
|---|---|---|---|---|---|---|
| 644 | rw-r--r-- | read/write | read | read | Regular files | Safe default |
| 755 | rwxr-xr-x | all | read/exec | read/exec | Dirs, scripts | Safe default |
| 600 | rw------- | read/write | — | — | Private files, keys | Very safe |
| 700 | rwx------ | all | — | — | Private dirs | Very safe |
| 775 | rwxrwxr-x | all | all | read/exec | Group-shared dirs | Group can write |
| 777 | rwxrwxrwx | all | all | all | (avoid) | World-writable |
The difference between 755 and 644 is a single bit: execute. Directories, scripts, and binaries need x to be entered or run, so they land at 755. A regular file such as an HTML page, an image, or a config has no reason to be executable, so it stays 644. Mixing the two up is behind most everyday permission errors.
Why 777 is dangerous. It hands write access to every account on the machine, including a compromised service account or a hijacked web process. A world-writable document root is the textbook route to a defaced site or injected malware, because anyone who reaches it can overwrite your code. When a forum post tells you to chmod 777 something “to make it work”, the real problem is nearly always ownership, covered below.
The 1777 exception. /tmp is world-writable on purpose, but with a safeguard. Mode 1777 adds the sticky bit, which lets everyone create files while stopping users from deleting or renaming files they do not own. That is why shared temp directories are safe at 1777 but never at plain 777. Type 777 into the chmod calculator and the risk panel flags it immediately, while 1777 is recognised as the standard shared-directory pattern.
Numeric vs Symbolic Mode
chmod takes the same bits two ways.
Numeric (absolute) mode states the complete result. chmod 755 file sets all nine bits to rwxr-xr-x regardless of what was there before. This is what you want in scripts and deployment, where you are enforcing a known-good state.
Symbolic (relative) mode describes a change. chmod u+x file flips one bit (add execute for the owner) and leaves everything else alone. chmod u=rwx,go=rx file sets whole classes explicitly. Symbolic mode suits one-off adjustments where restating the entire mode would be overkill.
# Numeric: overwrite the whole mode
$ chmod 644 report.txt
# Symbolic: change only what you name
$ chmod u+x deploy.sh # add execute for the owner
$ chmod go-w shared.conf # remove write from group and others
$ chmod u=rw,go=r notes.md # set each class explicitly → 644
One trap with symbolic mode: chmod +x without a class is filtered by your umask. With the common umask 022, chmod +x script.sh adds execute for everyone, so it matches chmod a+x. Under a stricter umask like 077 it only affects the owner. When you want a guaranteed outcome, name the class: u+x for the owner alone, a+x for everyone.
Special Permissions: setuid, setgid and the Sticky Bit
Beyond the nine standard bits, a fourth, leading octal digit carries three special modes, the setuid, setgid, and sticky bit trio:
- setuid = 4000 — the program runs with the file owner’s privileges, not the caller’s. This is how
passwd, owned by root, lets an ordinary user update a root-owned password database. - setgid = 2000 — the same idea for the group. On a directory it also makes new files inherit the directory’s group, which keeps a shared project consistently group-owned.
- sticky bit = 1000 — on a shared directory, restricts deletion so users can only remove their own files.
/tmpat 1777 is the canonical example.
$ chmod 4755 /usr/local/bin/mytool # setuid
$ chmod 2775 /srv/shared # setgid on a shared dir
$ chmod 1777 /tmp # sticky bit
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 59976 Jul 17 10:00 /usr/bin/passwd
The s/S and t/T casing rule
In ls -l, the special bits reuse the execute slot, and the case tells you whether execute is also set. Lowercase s (setuid/setgid) or t (sticky) means the special bit and execute are on, the normal case. Uppercase S or T means the special bit is set but execute is not, which is usually a mistake, because a special bit on a non-executable file does nothing useful.
Compare rwsr-xr-x (4755, setuid with execute, correct) against rwSr--r-- (4644, setuid without execute, suspicious). Whenever you see a capital S or T, check whether someone dropped the execute bit by accident.
The GNU directory gotcha nobody mentions
Nearly every tutorial gets this platform difference wrong. On Linux (GNU coreutils), a numeric chmod 755 dir does not clear an existing setuid or setgid bit on that directory. It preserves it. If a directory is already 2755 (setgid) and you run chmod 755 expecting a clean slate, the setgid bit stays, and the directory is really still 2755.
To actually clear it, be explicit:
$ chmod 00755 dir # five-digit form zeroes the special digit
$ chmod =755 dir # = clears every bit not listed
$ chmod u-s,g-s dir # remove setuid and setgid by name
BSD and macOS do the opposite: a numeric chmod 755 clears the special bits by default. So a deploy script that “resets” permissions with chmod -R 755 behaves differently on a Mac laptop than on a Linux server. This retention is documented in the GNU coreutils manual; when in doubt, use the five-digit or u-s,g-s form so the outcome is identical everywhere.
umask: What Newly Created Files Get
You rarely chmod every file by hand; most get their mode at creation, and umask decides it. A umask is a set of bits to switch off. New files start from base 666 and new directories from 777, and the umask masks bits away:
effective mode = base & ~umask
Files begin at 666, not 777, because a brand-new file has no business being executable by default. That bit is added deliberately with chmod +x.
| umask | New files | New dirs | Meaning |
|---|---|---|---|
| 022 | 644 | 755 | Default — others read, not write |
| 077 | 600 | 700 | Private to the owner |
| 002 | 664 | 775 | Group collaboration |
Work the default 022 through by hand: 666 & ~022 = 666 & 755 = 644, and 777 & ~022 = 755. Check your current value with umask, and set a session default with, say, umask 077 on a machine where nothing should be group- or world-readable.
chmod vs chown: Permissions vs Ownership
chmod and chown answer different questions. chmod changes what the owner, group, and others may do: the permission bits. chown changes who the owner and group actually are. Reaching for 777 is often an ownership problem wearing a permissions costume.
The classic case: a web server running as www-data cannot write its upload directory. chmod 777 makes the error disappear by letting the whole world write, and leaves a hole behind. The correct fix assigns ownership to the process that needs it:
# Wrong: opens the directory to every account on the box
$ sudo chmod -R 777 /var/www/uploads
# Right: give it to the web user, keep a tight mode
$ sudo chown -R www-data:www-data /var/www/uploads
$ sudo find /var/www/uploads -type d -exec chmod 755 {} +
$ sudo find /var/www/uploads -type f -exec chmod 644 {} +
Diagnostic order when something is unexpectedly unreadable: run ls -l to see who owns it first, decode the mode second, then decide whether the fix is chown, chmod, or adding a user to a group.
Recursive permissions done right
A blanket chmod -R 755 . marks every regular file executable, which is noise at best and a quiet risk at worst. Recurse by type instead:
$ find . -type d -exec chmod 755 {} + # directories → 755
$ find . -type f -exec chmod 644 {} + # files → 644
GNU chmod offers a one-line shortcut with the capital X, which adds execute only to directories and to files that already carry an execute bit:
$ chmod -R u+rwX,go+rX .
The chmod calculator generates the directories-only and files-only find commands for any mode you pick, so you can copy the correct split instead of reaching for a plain -R.
Linux File Permission Best Practices
- Grant the least privilege that works. Start from the tightest mode and open up only what breaks. Every extra write bit is attack surface.
- Default to 644 files inside 755 directories. This pairing serves almost every web root and repository checkout. Regular files rarely need execute; directories always do.
- Never leave 777 on anything a server can reach. If several accounts must write, use a shared group with 775 or 2775 (setgid keeps group ownership consistent) rather than opening the mode to the world.
- Keep SSH private keys at 600, or 400 once final. OpenSSH refuses group- or world-readable private keys outright. See the OpenSSH manual for the exact key-file requirement. Public keys and
authorized_keysare fine at 644. - Layer file modes with other controls. Permissions are the base; pair them with basic auth from the htpasswd generator when a folder needs a login, and treat file modes as one piece of the picture covered in our web security essentials guide.
FAQ
What does the d or l at the start of drwxr-xr-x mean?
The first character in an ls -l line is the file type, not a permission. d marks a directory, l a symlink, - a regular file, c or b a device, p a named pipe, and s a socket. Only the nine characters after it encode the actual read, write, and execute bits.
What is the difference between a lowercase s and an uppercase S in permissions?
A lowercase s and an uppercase S both mean the setuid or setgid bit is set. Lowercase s means execute is also set, the normal working case. Uppercase S means the special bit is on but execute is off (as in 4644), which is almost always a misconfiguration, since a special bit is meaningless without execute.
What is umask and how does it decide default permissions?
umask is the set of permission bits switched off when a file is created. New files begin at base 666 and directories at 777, then effective = base & ~umask removes the masked bits. The default 022 yields 644 files and 755 directories; run umask to see yours, or umask 077 for a more private default.
When should I use 400 or 700 instead of 644 or 755?
Use 400 or 700 when a file or directory must stay fully private. 400 (r--------) is a read-only private file, ideal for a finalized SSH private key you never edit. 700 (rwx------) is a directory only the owner can enter, like ~/.ssh or ~/.gnupg. Unlike 644 and 755, they grant nothing to anyone else.
Why can I list a directory but not cd into it?
Directory permissions split listing from traversal: the r bit lets you list names, the x bit lets you enter. A directory with r but no x (a 644 directory) shows its names under ls yet blocks cd and any access to the files inside. Add execute (make it 755) to render it enterable.
Do file permissions work the same on macOS as on Linux?
File permissions share the same core rwx and octal model on both, because both follow POSIX, but details differ. BSD and macOS clear a directory’s setuid/setgid on a numeric chmod by default, while Linux preserves it. Reading a mode differs too: stat -c '%a' file on Linux, stat -f '%Lp' file on macOS, and macOS adds ACLs and file flags.
Can I change file permissions without the command line?
You can calculate and decode permissions without a terminal. The free chmod calculator lets you tick a permission matrix, type an octal value, or paste an ls -l line, then copies back the exact chmod command. Applying it to a real file still needs that command on the server, or a GUI or FTP client that exposes permission fields.